Phoenix에서 Microsoft Translator 텍스트 API를 사용해보기

16555 단어 AzureElixirPhoenix
(이 기사는 fukuoka.ex (그 2) Elixir Advent Calendar 2017 - Adventar 의 19일째, 자연 언어 처리 Advent Calendar 2017 - Qiita 의 16일째입니다)

어제는 @zacky1972 씨의 「 ZEAM 개발 로그 v0.1.6.1 Elixir / Rustler 작은 자료집 ~ Rustler로 목록에서 바이너리로 변환 」였습니다!

주제



이전 기사 「 Phoenix + Vue.js 입문 」에서는 Phoenix + Vue의 구성으로, DB에 보존한 레코드를 화면 표시하는 부분까지를 썼습니다.

이번에는 Phoenix에서 Microsoft Translator 텍스트 API을 두드려 결과를 얻을 때까지를 써 보겠습니다. 환경은 마지막 기사와 같습니다.

사전 준비



사전 준비로 azure에 가입한 후 API를 사용 설정하고 키를 가져와야 합니다.

key의 발행에 대해서는 이하의 기사가 참고가 되었습니다.
Microsoft Translator 텍스트 API에서 일본어를 영어로 번역하는 샘플

key의 발행이 끝나면, 다음으로 진행합시다.

목표



"일본어 제목 및 본문과 영어로 번역 된 제목과 본문이 화면에 표시됩니다."를 목표로합니다.

httpoison 도입



Phoenix에서 API를 두드리기 위해 Elixir의 HTTP 클라이언트인 httpoison을 도입합니다. json parser의 poison도 함께 넣어 둡시다.

GitHub - edgurgel/httpoison: Yet Another HTTP client for Elixir powered by hackney
GitHub - devinus/poison: An incredibly fast, pure Elixir JSON library

mix.exs의 applications, deps에 추가합니다.
  def application do
    [
      extra_applications: [:logger, :runtime_tools, :httpoison, :poison]
    ]
  end

  defp deps do
    [
     ...
      {:poison, "~> 3.1"},
      {:httpoison, "~> 1.0"}
    ]
  end

변경 후, 결정된 mix deps.get 를 실행해 둡니다.

$ mix deps.get

API를 두드리는 모듈 준비



API를 두드리는 코드를 작성합니다. 실제로 API를 두드리는 부분을 lib/translate_api.ex 모듈로 잘라 보았습니다.
defmodule TranslateApi do
  @moduledoc """
  Microsoft Translate Api Client written by Elixir.
  """
  @translate_api_endpoint "https://api.cognitive.microsofttranslator.com/translate?api-version=3.0"
  @issue_token_endpoint "https://api.cognitive.microsoft.com/sts/v1.0/issueToken"

  @doc """
  get authorization token from the token service.
  """
  def get_token() do
    {:ok, response} =
      HTTPoison.post(@issue_token_endpoint, "{}", [
        {"Ocp-Apim-Subscription-Key", "<API key>"}
      ])

    response.body()
  end

  @doc """
  translate texts by microsoft translate api.

  ## Examples
  translate(["hello", "world"], %{"from" => "en", "to" => "ja"})
  """
  def translate(texts \\ [], params \\ %{"to" => "en", "from" => "ja"}) do
    data = Enum.map(texts, fn text -> %{"Text" => text} end)

    {:ok, %HTTPoison.Response{body: body}} =
      HTTPoison.post(
        @translate_api_endpoint,
        Poison.encode!(data),
        [
          {"Content-Type", "application/json"},
          {"Authorization", "Bearer " <> get_token()}
        ],
        params: params
      )

    Poison.decode!(body)
    |> Enum.map(fn %{"translations" => [%{"text" => text}]} -> text end)
  end
end

translate()에 리스트를 건네주면, 일본어→영어로 번역한 결과를 얻을 수 있도록 했습니다.
TranslateApi.translate(["こんにちは", "世界"])["Hello", "World"]

API를 실행하기 위해 token이 필요하기 때문에 token 검색을위한 함수를 준비했습니다. 10분 만에 만료되는 듯 합니다만, 매번 두드릴 필요가 없기 때문에, 거기는 향후의 과제입니다(땀)

post값은 다음과 같은 JSON 포맷으로 할 필요가 있으므로, data = Enum.map(texts, fn text -> %{"Text" => text} end) 의 부분으로 post용의 데이터를 만들고 있습니다.
[
  {
    "Text" => "翻訳したい文字"
  },
  {
    "Text" => "翻訳したい文字"
  },
  {
    "Text" => "翻訳したい文字"
  },
  ...
]

API를 두드려 레코드 값을 번역 → View로 전달


article_controller.ex 의 index() 를 수정합니다.
  def index(conn, _params) do
    articles = Blog.list_articles()
    |> Enum.map(fn article ->
      # 翻訳の実行
      [en_title, en_body] = TranslateApi.translate([article.title, article.body])

      # 結果をmapに追加
      Map.merge(article, %{en_title: en_title, en_body: en_body})
    end)

    render(conn, "index.json", articles: articles)
  end

DB에서 얻은 레코드의 각 행에 대해 제목과 본문에 대한 번역을 수행하고 article 맵에 추가합니다.
레코드 수분 리퀘스트가 달려 버리므로, 제대로 만들면 실장에 궁리가 필요할 것 같습니다.

사실 이것만으로는 view에서 값을 사용할 수 없습니다. article_view.exrender("article.json") 부분에 번역 결과 필드를 추가합니다.
  def render("article.json", %{article: article}) do
    %{id: article.id, title: article.title, body: article.body, en_title: article.en_title, en_body: article.en_body}
  end

이제 뷰 측에 값이 전달됩니다. 건너온 값을 표시해 봅시다.
<div v-for="article in articles">
  <h2>{{ article.title }}({{ article.en_title }})</h2>
  <pre>{{ article.body }}</pre>
  <pre>{{ article.en_body }}</pre>
  <hr>
</div>

번역한 결과를 볼 수 있었습니다!



요약



Microsoft Translator 텍스트 API를 사용하여 문자열을 번역할 수 있습니다. 「외부 API로 취득한 JSON을, 독자적인 포맷으로 변형한다」라고 하는 처리는 패턴 매치 덕분에 쓰기 쉽습니다♪

다음 번에는 @ 코바타코의 "Slack bot에서 알림을 받고 싶은 게시일에 대한 알림 with Qiita API
"입니다! 기대하세요!

만원 감사! Elixir MeetUp을 6 월 말에 개최합니다
※응모 다수에 의해, 증 프레임했습니다
「fukuoka.ex#11:DB/데이터 사이언스에 커넥트 하는 Elixir」 을 6/22(금) 19시에 개최합니다. 특별 게스트도 맞이해, 매우 진한 2시간이 되는 것 틀림없습니다! 흥미가 있는 분은 꼭 참가해 주세요!

좋은 웹페이지 즐겨찾기