HAMADAの語り草

興味のある技術のアウトプットをしたいと思います

AWSのハンズオンをGoで書いて入門した話 ~翻訳APIを作ったよ~

はじめに

こんにちは!!会津大学学部二年のHAMADAです。

11月も後半に差し掛かり、寒さに苦しんでいる今日この頃です。

今回は、AWSのハンズオンGoで書いて入門したお話です。

動機・目的

今までAWSGCP、Firebaseなどに対する得体の知れなさを持っていましたが、私が作りたいものや、学びたい技術とは切っても切れないものなので思い切って挑戦してみました!!  足りないポイント、間違った解釈があるかと思いますが、暖かい目でみていただけると嬉しいです。

使った技術

  • AWS
    Amazon Web Service 色々できるやつ。今回使ったのは以下

    • Lambda
      関数をAWS上で実行できる。
    • API Gateway
      APIの管理、配布、保守などを目的としたもの。繋ぎ合わせ
    • DynamoDB
      NoSQLのDB  jsonのやつ。今回これで苦しみました。
  • Go
    最近よく書く言語。try catchではなくerror処理ができるところが好き。

参考にしたハンズオンリンク

pages.awscloud.com

手順

  1. AWS Lambdaを構築、Amazon Translateを呼び出す。
  2. API Gateway を用いて Lambda Function と組み合わせてWeb APIを作成する。
  3. Amazom DynamoDB を用いて翻訳したデータを保存する。

1. AWS Lambdaを構築、Amazon Translateを呼び出す

awsにログインして、Lamdaを開きます。

アカウントの作成方法やセキュリティの設定などは機会があれば書こうと思います。

オレンジの関数の作成を押します。

今回は1から作成を選択し、関数名を自分で記入しランタイムをGo 1.xにしました。

pythonやNode.jsではAWS上でプログラムが書けるのですが、Goは対応していないのでvscodeでプログラムを書いてfunction.zipファイルをアップロードします。

書いたコード

//Translate/transltate.go
package translate
    import (
	"fmt"
	"log"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/translate"
)


 func TranslateFunc() {
 	InputText := "日本語だよ!こっちは英語"
 	InputLang := "ja"
 	OutputLang := "en"
 	sess := session.Must(session.NewSession())
 	trans := translate.New(sess)

 	result, err := trans.Text(&translate.TextInput{
 		SourceLanguageCode: aws.String(InputLang),
 		TargetLanguageCode: aws.String(OutputLang),
 		Text:               aws.String(InputText),
 	})
 	if err != nil {
 		log.Print("おかしいぜ")
 	}

 	fmt.Println(*result.TranslatedText)
 }
//handler.go
package main

import (
	"github.com/ahmos0/goLambdaFirst.git/Testgreeting"
	"github.com/ahmos0/goLambdaFirst.git/Translate"
	"github.com/aws/aws-lambda-go/lambda"
)

func exucuteFunc() {
        Translate.TranslateFunc()
}

func main() {
	lambda.Start(exucuteFunc)
}

InputTextの日本語を英語に変換します。InputLangは今回日本語なので"ja"。これをOutputLangは"en"にして変換しています。

その後Translateのセッションを確立しています。

trans.Textに翻訳の対象となる言語(今回は日本語)、翻訳先の言語(今回は英語)、対象となる文字列を translate.TextInput で翻訳与えてあげます。

handler.goから実行します。

Lambda上にzipファイルとしてあげる際に、以下を実行しました。

go build
GOOS=linux go build -o handler handler.go
zip function.zip handler 

普段通りbuildしてあげてから、handlerを作成します。これは、Lambda関数で呼び出す主軸のようなものですね。その後、handlerをzipにしてあげればOKです。

テストのやり方などは、最終checkの段階に書こうと思います。

2. API Gateway を用いて Lambda Function と組み合わせてWeb APIを作成する

右上のAPIを作成から作ります。

REST APIを選びます。

設定は上記のようにしました。

 

リソースの作成から/translate

メソッドの作成からGETを作成します。

GETの統合リクエストを選択し、以下のように設定。

書いたコード

//Translate/translate.go
package Translate

import (
	"fmt"
	"log"

	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/translate"
)

var OutputText string

func TranslateFunc(req events.APIGatewayProxyRequest) string {
	InputText := req.QueryStringParameters["InputText"]
	InputLang := "ja"
	OutputLang := "en"
	sess := session.Must(session.NewSession())
	trans := translate.New(sess)

	log.Println(InputText + "これです")

	result, err := trans.Text(&translate.TextInput{
		SourceLanguageCode: aws.String(InputLang),
		TargetLanguageCode: aws.String(OutputLang),
		Text:               aws.String(InputText),
	})
	if err != nil {
		log.Print("おかしいぜ")
	}

	OutputText := *result.TranslatedText

	return OutputText
}

//handler.go
package main

import (
	"github.com/ahmos0/goLambdaFirst.git/Testgreeting"
	"github.com/ahmos0/goLambdaFirst.git/Translate"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

type Response struct {
	StatusCode int    `json:"statusCode"`
	Body       string `json:"body"`
}

func ExucuteFunc(request events.APIGatewayProxyRequest) (Response, error) {
	OutputText := Translate.TranslateFunc(request)
	return Response{
		StatusCode: 200,
		Body:       OutputText,
	}, nil
}

func main() {
	lambda.Start(ExucuteFunc)
}

events.APIGatewayProxyRequestで文字列を確保し、Translate.TranslateFuncで翻訳しています。QueryStringParamerters["InputText"]で元の日本語文を取得しています。

できているかの確認は、今回も最後のチェックで説明します。

 

3. Amazom DynamoDB を用いて翻訳したデータを保存する

DynamoDBでテーブル作成をします.

右上のテーブル作成から作ります。

テーブルの作成は以下のように設定しました。

テーブルの項目は、timestamp、InputText、OutputTextを作りました。

書いたコード

//database/DynamoDB.go
package database

import (
	"fmt"
	"time"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
)

type Item struct {
	TimeStamp   string `json:"timestamp" dynamodbav:"timestamp"`
	InputTextj  string `json:"inputtext" dynamodbav:"InputText"`
	OutputTextj string `json:"outputtext" dynamodbav:"OutputText"`
}

func OperateDB(InputText string, OutputText string) {
	sess := session.Must(session.NewSessionWithOptions(session.Options{
		SharedConfigState: session.SharedConfigEnable,
	}))
	fmt.Println(InputText)
	fmt.Println(OutputText)
	dynamo := dynamodb.New(sess)

	t := time.Now()
	item := Item{
		TimeStamp:   *aws.String(t.String()),
		InputTextj:  *aws.String(InputText),
		OutputTextj: *aws.String(OutputText),
	}
	av, err := dynamodbattribute.MarshalMap(item)
	if err != nil {
		fmt.Println(err.Error())
	}
	tableName := "translate-history"
	input := &dynamodb.PutItemInput{
		TableName: aws.String(tableName),
		Item:      av,
	}

	_, err = dynamo.PutItem(input)
	if err != nil {
		fmt.Println(err.Error())
	}
}

//Translate/translate.go
package Translate

import (
	"fmt"
	"log"

	"github.com/ahmos0/goLambdaFirst.git/database"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/translate"
)

var OutputText string

func TranslateFunc(req events.APIGatewayProxyRequest) string {
	InputText := req.QueryStringParameters["InputText"]
	InputLang := "ja"
	OutputLang := "en"
	sess := session.Must(session.NewSession())
	trans := translate.New(sess)

	log.Println(InputText + "これです")

	result, err := trans.Text(&translate.TextInput{
		SourceLanguageCode: aws.String(InputLang),
		TargetLanguageCode: aws.String(OutputLang),
		Text:               aws.String(InputText),
	})
	if err != nil {
		log.Print("おかしいぜ")
	}

	OutputText := *result.TranslatedText

	fmt.Println(OutputText + "わーい")
	database.OperateDB(InputText, OutputText) //ここでdatabaseに追加する

	return OutputText
}

handler.go は前と同じコードです。

実際にできたものを確認していきます

API Gatewayからアクション>APIのデプロイを選択

このようにします。

GETを選択し、URLの呼び出しというところのリンクに飛びます.

すると今のままでは、Internal server errorが返ってきます。

{"message": "Intenal sever error" }

URLの末尾をdev/translate?InputText=やったか?

のように指定すると

did you do it?

のように返ってきます。

DynamoDBの方には、タイムスタンプ、入力した日本語、返ってきた英語が保存されます。



こんな感じですね。

テストのやり方

テストイベントを作成して、右上のテストからテストを実行します。

成功すれば、この上に成功と緑色で表示されログを見れます。

今回は、queryStringParametersの中身だけ変更しました。そのほかはAPICallのテンプレです。

 

今回のgithub repository

github.com

感想と展望

AWSに触れるのは初めてでさまざまな難題にも悩まされましたがなんとか完走できてよかったです。結構詰まることもあったので、できた時は快感でした!!!一つずつ積み重ねていくことの重要性を実感できました。またpythonで話を聴きながらgoで書くというのが自分の力で実装できたという自信にもつながったのでよかったです。ここまで読んでいただきありがとうございました。拙い部分も多いので、間違った点などあればご指摘いただけると幸いです。次回またよろしくお願いいたします!!!

 

所属サークル

A-PxL (@aizu_PxL) / Twitter

私のTwitter

HAMADA (@AHMOS_HMD) / Twitter

私のgithub

ahmos0 (HAMADA) · GitHub

 

参考リンク

pages.awscloud.com

aws.amazon.com

github.com