astamuse Lab

astamuse Labとは、アスタミューゼのエンジニアとデザイナーのブログです。アスタミューゼの事業・サービスを支えている知識と舞台裏の今を発信しています。

ニューラル機械翻訳モデルを自作してみる

f:id:astamuse:20201208203648p:plain

こんにちは、師走ですね。業務に関連した技術トピックをということで、今回は翻訳について書こうと思います。

機械翻訳について

弊社アスタミューゼは知の「流通・活用・民主化」を掲げており、世界各国の特許やグラントその他のデータを収集・分析・提供しています。これらの文書は当然各国語で記述されているため、統一した分析処理のためには機械翻訳や多言語処理が必要不可欠です。

ニューラル機械翻訳

2020年を振り返って翻訳関連の話題といえばDeepLを思い浮かべる方が多いのではないでしょうか。2018年頃から欧州を中心にGoogle Translateと比べた品質の優位性が話題になり、3月に日本語対応が発表されたことで国内での認知度が一気に向上しました。試しにつかってみたという方も多いはずです。

www.deepl.com

このDeepLに代表されるように、ここ数年の機械翻訳の発展は、自然言語処理のなかでもニューラル機械翻訳(Neural Machine Translation, 以下NMT)という分野の研究成果が寄与しているようです。従来の統計的機械翻訳と比べた性能向上やNMT固有の誤りとその対処法などが、国際会議でもさかんに報告されています。

この記事では、ニューラル機械翻訳(NMT)システムがその内側でどんな処理をしているかを理解することを目的に、実際に簡単な翻訳モデルを手元で作成してみて、その品質を評価するところまでをご紹介します。

続きを読む

現場コーチング受けてみた話

f:id:astamuse:20201125123021j:plain

こんにちは、アプリケーションエンジニアの @yukung です。突然暑くなったり寒くなったり、気温の変化が大きい今日このごろ、体調いかがでしょうか。コロナの勢いも再び出てきてしまっており少し不安な状況になりつつある中、再度気を引き締め直してしっかり体調に気をつけていきたいですね。

スクラム始めてみてその後どうなった?

さて、今回は以前ご紹介した、弊社の ICP 開発チームにおける開発の様子のその後について触れてみたいと思います。

以前このブログで、ICP 開発チームでは開発の進め方としてスクラムを導入して開発を行っていることをご紹介しました。その時の経緯や具体的なやり方の様子などは、以下の記事もぜひご覧ください。

lab.astamuse.co.jp

また、本記事の趣旨とは少しずれますが、今年の大きな変化として多くの企業がリモート・在宅での業務にシフトしていく中で、我々 ICP 開発チームもスクラムを継続しつつ、自ずとリモート主体の業務スタイルに移行しています。その時の変化の様子については、以下の記事で紹介されていますのでこちらもどうぞご覧ください。

lab.astamuse.co.jp

スクラムを始めてみて浮き彫りになった課題

上記の記事で触れた通り、スクラムを始めてしばらくは、私自身がスクラムマスター兼開発者兼各種スクラムセレモニーの MC を兼任する形で進めていました。見様見真似で始めたこともあり、はじめの頃はチーム全体が何が正解かも分からず、まずは私が言っていることを正として、進めていたと感じています。

そうすると、容易に想像できることではありますが、だんだんと私自身がボトルネックになりはじめている感触を持つようになりました。どんな点でそう感じていたかについて、細かいものまで挙げると切りがないですが例えば以下のようなものです。

  • スプリントプランニングの進め方について
  • ストーリーポイント見積もりの基準について
  • デイリースクラムのファシリテーション
  • プロダクトバックログリファインメントの議論のファシリテーション
  • 振り返りのファシリテーション
  • etc...

当然といえば当然ですが、知らないものに取り組んでいるのでそうならざるを得ないのはある程度仕方のない面があります。

一方で、この状況は決して芳しいものではなく、チームの成果を最大化するにはこの状況自体を改善する必要性がありました。PM の Gyopi が機を見たタイミングで違和感や改善提案などを出してくれてそれ自体に大分助けられていたのですが、私自身も認定スクラムマスターの資格を持っている訳ではなく、私自身でも自信を持って進められているわけではありませんでした。

そんな折、私が以前在籍していた職場で現場コーチとして関わってくれていたギルドワークスの中村さん

guildworks.jp

からお声がけいただいて、中村さんのご厚意によりアドバイスをいただける機会を得ることができました。

GuildWorks

コーチングの内容(一部)

漠然とした課題感は持っていたものの、自分たちでも何が課題なのかをはっきり認識できていない中で、中村さんには現状を率直にぶつけてお話を聞いていただきました。以下はその時のミーティングの様子で話していたメモの一部です。(字が汚くてすいませんw)

f:id:astamuse:20201125120251j:plain

(この時からは結構時間が経っており、今となってはという話も含まれていて個人的には懐かしい感情が沸いてきます…)

また、中村さんにはチームの振り返りのある会にご同席いただいて、様子を観察していただきました。一部ですが抜粋してみます。あくまでも私たちのチームの状況なので、全て参考になるわけではないと思いますが、なんとなく雰囲気が伝わればと思います。

f:id:astamuse:20201125120331p:plain

中村さんとのオンライン雑談会

また、この後ある程度時間が経ってからも、オンラインでの雑談会で相談に乗っていただいたりもしました。その時にいただいたメモなどを一部抜粋してご紹介します。

こちらも私たちが直面した状況に対する議論のメモなので、これを読んでそのまま何か答えとなるようなものではありませんし、特定の課題に限っていないので取り留めもないのですが、少しでも参考になればと思い載せてみます。(中村さん)とカッコ書きにしているところは、中村さんからいただいたアドバイスの一部です。

オンライン雑談会のメモ

  • ストーリーポイントの確からしさに対する不安
    • 怖い?
      • (中村さん)正確さを求められる強迫観念をチームが持っている?
    • 数字は取っているけど、それを見てカイゼンする姿勢になりづらい
    • ポイントについて話しているのにいつの間にか工数見積になっている。
      • (中村さん) 議論する前にまず最初につけてみると良い かも?
      • (中村さん)1,2,3,5,8,13 で 2 つ以上離れていると、話し合うと良さそう なアラート。
    • (中村さん) 規模見積と工数見積の違い について
  • チームの人数の大きさについて。多いと感じているが実際どうなのかが不安
    • 最適な人数ってどれくらい?分けたほうがいい?
      • (中村さん)どうして分けないの?
      • 実際に回るかどうか不安
        • (中村さん) 試しに PO と SM (私自身) が、一緒に1週間くらい旅行に行ってしまって、その間みんなに回してもらえばいいのでは?
      • (中村さん) 小さく分けてうまくいかなければ、元に戻せばいい んじゃないかな?
      • (中村さん)PO が一人で回らないかもという場合、POを増やすという選択肢もある。例としてエンジニアから企画の人に手伝ってもらってPOをできていた例がある。
    • チームをわけることで、ドメイン or 技術スキルに偏りが出るかもという不安
      • (中村さん) 「みんながいい感じに守備範囲広くできる状態」をそもそも目指すのか?目指すとしたらそこにはどのように到達する のか?
      • (中村さん) ”チーム”としてユーザーに届けるためのスキルを持っているか が大事。
    • (中村さん) スモールチームでやったほうが、学びの増幅が起きやすい 印象がある
    • チーム分ける時、コードベースでも分けてる?
      • (中村さん)とある現場の例では、別れているチームも1つあるけど、2チームは同じところを触っている
      • (中村さん)同じところを触りそうなときにはスプリントの手前でやることをずらして被りづらいようにしている
  • リファインメントっていつしたらよい?今は週一回時間を取ってやっているが、議論が発散しがちでうまくできていないと感じる

現場コーチから持ち帰って実践したこと、変化があったこと

上記のような取り組みをさせていただいたことで得られたこととしては、まずは 私自身の良い振り返りの機会になった 、ということが大きかったと思っています。

自分自身でも自信を持てていたところ、逆にあまり自信を持てておらず不安だったところ、全く観点がなかったところなど、率直にぶつけさせていただいたことで気付かされることが多くありました。それによって私自身の振る舞いが少しずつ変わっていったように感じています。

また、上記でいただいたようなアドバイスを元に起こったチームの変化という意味で 1 つ挙げると、 私が行っていたような多くの議論のファシリテーションなどを、今ではチームメンバー全員で交代しながら実施することができるように なりました。

それによって、プロダクトバックログリファインメントとの向き合い方が以前より変わり、 しっかりリファインメントできたものに関してはやることがはっきりしてチームメンバーが理解できている状態でスプリントプランニングに臨めるようになった ため、議論がスムーズになりました。

スプリントプランニングやプロダクトバックログリファインメントなどについて、関わっているメンバー一人一人が、 誰かがやってくれるものという認識ではなくチームメンバーが自分のタスクとして認識する ことで、どういう事に気を配らないといけないのか、また議論の着地点をどこにするのか、という意識が少しずつチームメンバーに芽生えてきたのではないかと感じることが多くなってきました。結果的にリモート中心となってもミーティングの練度が高まっていったように感じています。

まとめ

スクラムを始めてしばらくして浮き彫りになってきた課題について、幸運にもギルドワークスの中村さんにアドバイスいただける機会をいただけたことで、チーム開発におけるカイゼンを一歩前に踏み出すことができたと感じています。

お声がけいただいたギルドワークスの中村さん、この場を借りて御礼申し上げます。ありがとうございました!

我々 ICP 開発チームはまだまだ完成された開発チームではありませんが、スクラムを用いて自分たちの開発するものについてチームで議論しながら進められるような開発ができています。こうした開発にご興味がある方は下記バナーの採用サイトからご応募いただければと思います。

gitlab-ci+kaniko+gcloudでCloudRunにアプリケーションをデプロイする

f:id:astamuse:20201110120825p:plain

11月です。寒いですね。ICPチームでgitlab-ci芸人をやっているchotaroです。
gitlab-ciと戦ったのも一年前
性懲りもなく、ややこなれてきた人向けのgitlab-ciのTIPS記事です。

日本語での情報があまりない分野ですので、誰かの役に立てば幸いです。
(なおこの記事を書いている段階でブログ当番を2ヶ月ほど滞納しております。土下座。

主な元ネタはこちらのgitlab公式doc

本記事のモチベーション

以下をモチベーションとしています。

  • 気軽にツール作ってdeployしたい。
  • gitlab-ciのjobからgcrにimageをpushしたい
  • ついでにそのままCloudRunにデプロイしたい
  • でもdind(docker-in-docker)はセキュリティ的に使いたくない(重要

jibなどもツールの選択肢にはなりうるのですが、CloudNative Buildpacksがdockerを必要とするため、dindを用いることが不適切なケースでは利用できません。

そこでここではgitlabの公式ドキュメントにも記載のある、kanikoを利用した実現方法を紹介していきます。

事前知識

kanikoとは

ものすごく端的に言えば、「dockerを使うことなく、Dockerfileからcontainer imageを作成し、リポジトリに pushするツール」です。

kaniko自体は、kubernates内でimageをbuildすることが主眼とされています。本記事ではあくまでも、container imageをdockerなしに作成するツールとして用います。

dockerfileの作成

kanikoはdockerを使いませんが、inputにDockerfileを必要とします。ProcfileなどではなくDockerfileなので、この点がややCloudNative Buildpacksなどと比べると開発者にとって少し敷居が高いかもしれません。

あくまでサンプルなので拘らず、GCPのdocにあるものを真似します。

Dockerfile

FROM node:15-slim

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install --only=production

COPY . ./

CMD [ "node", "index.js" ]

index.js

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  const name = process.env.NAME || 'World';
  res.send(`Hello ${name}!`);
});

const port = process.env.PORT || 8080;
app.listen(port, () => {
  console.log(`helloworld: listening on port ${port}`);
});

package.json

{
    "name": "helloworld",
    "description": "Simple hello world sample in Node",
    "version": "1.0.0",
    "private": true,
    "main": "index.js",
    "scripts": {
      "start": "node index.js",
      "test": "mocha test/index.test.js --exit",
      "system-test": "NAME=Cloud test/runner.sh mocha test/system.test.js --timeout=30000",
      "lint": "eslint '**/*.js'",
      "fix": "eslint --fix '**/*.js'"
    },
    "author": "Google LLC",
    "license": "Apache-2.0",
    "dependencies": {
      "express": "^4.17.1"
    },
    "devDependencies": {
    "got": "^11.0.0",
    "mocha": "^8.0.0",
    "supertest": "^4.0.2"
    }
}

起動して8080にアクセスするとHello World!という表示だけ出ます。

kanikoを使ったbuild

kanikoは引数で三つ指定が必要です。

  • docker-file
    • build対象のDockerfileはどこに置いてあるか。
      • gitlab-ciであれば$CI_PROJECT_DIRなど。
  • context
    • どこのソースを使用するか。kubernatesでの利用が主眼なので、リモートリポジトリなども指定できます。
      • gitlab-ciで特定のrepositoryでciする場合だと、素直に$CI_PROJECT_DIRなどでOKです。
  • destination
    • この設定値がpush先になります。
      • 例えばgcrのフルパス。(ex: gcr.io/<プロジェクト名>/<image名>

executorを対象にdocker runすればそのままdestinationに作成したimageがpushされる形です。

また、gcrにpushしたい場合GCPでの認証認可が必要になりますが、その他のGCPツール群と同じく$GOOGLE_APPLICATION_CREDENTIALSの環境変数にcredentialファイルのpathを渡してあげればOKです。

gcr上のイメージをcloud run上へdeployする

pushしたdocker imageをcloud run上にdeployするには、gcloudのコマンドを使えばOKです。gcrへのpushで使ったservice accountにこの権限も付与しておくと管理すべき認証情報が一つのservice accountにまとまるのでエコです。

公式ドキュメントも参考に、コンテナイメージを使ってgcloudコマンドでdeployしましょう

gcloud run deploy <サービス名> --image <imageのpush先> --platform managed --region <region名> 

実際に試してみる

gitlab-ci.yml

このような形になりました(ExecutorにはDocker Machineを使用しています)

stages:
  - build
  - deploy

before_script:
  - echo 'set up  credentials'
  - echo $CREDENTIAL > $CI_PROJECT_DIR/key.json
  - export GOOGLE_APPLICATION_CREDENTIALS=$CI_PROJECT_DIR/key.json

build: 
  stage: build  
  image:
    name: gcr.io/kaniko-project/executor:debug
    entrypoint: [""]  
  script:
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $DESTINATION

deploy:
  stage: deploy
  image: google/cloud-sdk:alpine
  script:
    - gcloud auth activate-service-account --key-file=key.json
    - gcloud config set project $GCP_PROJECT_NAME
    - echo y | gcloud auth configure-docker
    - gcloud info
    - echo y | gcloud run deploy kaniko-sample --image $DESTINATION --platform managed --region <region名>

ポイントは以下の点です。

  • buildとdeployでjobを分ける
  • 環境変数にcredentialなどの情報は外出しする(git管理下に鍵情報は置きたくないので
  • before scriptで認証情報のセットアップを行う

buildとdeployでjobを分ける

kanikoのimageはdebugで利用します(gitlab公式docも参照ください

また、素のalpineなどにgcloudを入れるのは大変なので、gcloudのimageをそのまま使うためtaskを分けています。

環境変数にcredentialなどの情報は外出しする

gitlab-ciのvariablesに下記を設定します。

  • GCP_PROJECT_NAME
    • GCP上のプロジェクト名
  • CREDENTIAL
    • サービスアカウントの認証情報
  • DESTINATION
    • gcrの指定

before scriptで認証情報のセットアップを行う

  - echo 'set up  credentials'
  - echo $CREDENTIAL > $CI_PROJECT_DIR/key.json
  - export GOOGLE_APPLICATION_CREDENTIALS=$CI_PROJECT_DIR/key.json

ややトリッキーな書き方になってはいますが、variablesに設定した認証情報を書き出します。

    - gcloud auth activate-service-account --key-file=key.json
    - gcloud config set project $GCP_PROJECT_NAME
    - echo y | gcloud auth configure-docker

gcloudでそのkeyをもとにサービスアカウントとしての認証設定を行います。これでgcloudのセットアップはOK

実行後の確認

gitlab-ciの実行結果を確認し、Service URLにアクセスしてHello World!を確認します。

Deploying container to Cloud Run service [<サービス名>] in project [<プロジェクト名>] region [<リージョン名>]
Deploying...
Creating Revision...................................................................................done
Routing traffic......done
Done.
Service [<サービス名>] revision [<サービス名>-00004-but] has been deployed and is serving 100 percent of traffic.
Service URL: https://<url>

trouble shooting系(ここでつまりました

  • gcloud run の際にSERVICEがないと言われる
    • ちゃんとhelpをよみましょう。
    • gcloud run deploy <SERVICE名称> <--で始まるその他オプション>という構文です。
  • gcloud run の際にregionが設定されてないと言われる
    • ちゃんと(ry
    • 設定しましょう。 --regionオプションです
  • 403が出て表示できない
    • これが出るのは主に、デプロイしたアプリが権限を必要とする状態になっており、かつアクセス者に権限がない場合です
    • console上でアクセスする人(gcp上のメンバー)に権限を付与すればそのメンバーがアクセスできるようになります。
      • あくまでサンプルやリクエストを複数受けても問題ない場合のみ使うべきTIPSではありますが、--allow-unauthenticatedオプションをつけてdeployすることで誰でもアクセスできるようになります。

まとめ

ざっくりとした解説にはなりますが、以上です。
趣味と実務の境目みたいなTIPSでしたが、こういう積み重ねが後々新しいことをやろうとした時に効いてくると信じています。

やってみた感想としては、Dockerfileを用意すればどんなアプリケーションでも原則このやり方でdeployできるはずなので、社内ツールのようなものにも活用していけたら気軽にいろいろ試していけそうかな、という感じです。

ICPとして今後本番利用したりしていくかは未知数ですが、jenkinsでの運用に限界があるのも事実なので、この辺りのアンテナも個人的には立てていきたいところだと思っているところです。

さて最後にはなりますがアスタミューゼでは引き続き好奇心豊富な(?)メンバーを募集しています。
業務やドメイン的には他の方の記事がどれもかなり興味深い内容にはなっておりますので、そちらも読んでいただきビビッときたらこちらよりご連絡いただければと思います。では!

参考にさせていただいたもの

Copyright © astamuse company, ltd. all rights reserved.