Skip to content

Commit

Permalink
Merge pull request #55 from ysekiy/docupdate
Browse files Browse the repository at this point in the history
v0.3.0
  • Loading branch information
ysekiy authored May 24, 2024
2 parents b927e60 + 65e6d2d commit 4b8ee29
Show file tree
Hide file tree
Showing 60 changed files with 14,190 additions and 4,398 deletions.
4 changes: 3 additions & 1 deletion .env.development-template
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
VITE_INDEX_ID=*****
# VITE_SERVER_URL=http://localhost:8080
# VITE_SERVER_URL=http://localhost:8080
VITE_MODEL_ID=anthropic.claude-3-haiku-20240307-v1:0
VITE_BEDROCK_REGION=us-west-2
67 changes: 7 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

このソリューションは AWS 上で検索用途の Retrieval Augmented Generation (RAG) を構築するサンプルコードです。

![](docs/png/rag-screenshot.png)

Retrieval Augmented Generation(RAG)とは、生成系の言語 AI モデルに外部メモリをつけるというコンセプトを指します。これまで大規模な事前トレーニング済み言語モデル (LLM) は、事前学習済みのデータを元に確からしい情報を作文できることが分かっています。ただし、知識を問うようなタスクの場合、事実でない事柄を出力するリスクを伴います。さらに、情報の出典や更新を LLM 単体で行うことは依然として未解決の研究課題です。そこで情報を LLM の学習データではなく、外部に保存し出力時に Prompt に埋め込む方式が提唱され RAG と名付けられました。このサンプルではユーザーのリクエストに最も関連する情報を企業のナレッジベースから取得し、LLM に集約させ作文する RAG ソリューションを実現します。

## Architecture Overview / 全体の構成図
Expand All @@ -23,37 +25,9 @@ Retrieval Augmented Generation(RAG)とは、生成系の言語 AI モデルに

これまでは検索アプリケーションを運用する場合、データを取り込むコネクターの開発、全文データベースの運用、ベクトル生成用のアルゴリズム開発などが必要でした。一方 Amazon Kendra はフルマネージドサービスであるためそれらの開発・運用は不要です。Amazon Kendra には、Amazon Simple Storage Service (Amazon S3)、SharePoint、Confluence、ウェブサイトなどの一般的なデータソースへのコネクタがあらかじめ組み込まれており、HTML、Word、PowerPoint、PDF、Excel、テキストファイルなどの一般的なドキュメント形式もサポートしています。エンドユーザーの権限で許可されているドキュメントのみに基づいて応答をフィルタリングするために、アクセス制御リスト (ACL) にも対応しており、エンタープライズ企業での導入実績もあります。

### LLM は2つから選択可能

本ソリューションは日本語を利用するお客様を想定し、日本語に対応しているLLMの利用を前提としています。デフォルトでは、Rinna 社が開発したモデル [rinna/japanese-gpt-neox-3.6b-instruction-ppo](https://huggingface.co/rinna/japanese-gpt-neox-3.6b-instruction-ppo) か、 Anthropic 社の claude をご利用いただくことが可能です。

なお、ご利用の仕方として、rinnaについては Amazon Sagemaker で エンドポイントを立ててご利用いただくことを想定しております。Endrpointを立ち上げるための [script](llm/deploy_llm.sh) もご用意あります。
一方、claude については、Anthropic社が提供するAPI経由での利用を想定しております。そのため、claude をご希望の場合、事前に [API KEYの取得](https://www.anthropic.com/) をお願い致します

### 3つの検索モードを提供

本ソリューションは、RAGを提供するのは勿論ですが、Kendra単体での検索や、LLM単体でのQ&A用途でもご利用いただけるように工夫をしているのが特徴となります。

| モード | 機能 | 特徴 |
|:--------|:---------------------------------------|:----------------------------|
| #rag | Kendraで検索した文章をコンテキストとして、LLMで回答を生成するモード | |
| #kendra | kendraでキーワドに関連する文書検索を行うモード | |
| #ai | LLMでキーワードに関連する回答を生成するモード | 「ピン留め」機能により、明示的にコンテキストを指定可能 |

#### Ragモード(#rag)

キーワードをもとに、Amazon Kendra でドキュメントの検索を行い、その検索結果のドキュメントをコンテキストとした上で、LLMにクエリを投げてレスポンスを表示するモードです。
こちらでは、結果として「LLMの回答」「Kendraの検索結果」の2つが出力されます。なお、検索実行から終了までの体感速度を上げる工夫として、Kendraの検索結果をそのままLLMに投げるのではなく、検索結果を画面に一度表示をしてから、LLMに投げるという二段構えを採用しています。

#### Kendraモード(#kendra)

キーワードをもとに、Amazon Kendra でドキュメントの検索を行い、その検索結果のドキュメントを一覧で表示するモードです。
こちらでは、結果として「Kendraの検索結果」が出力されます。

#### AIモード(#ai)

キーワードをもとに、LLM に対してクエリを投げて、そのレスポンスを表示するモードです。なお、本RAGソリューションでは、過去の検索結果を「ピン止めして記録しておく」機能があるのですが、AIモードで検索を行う際には、「ピン留め」したテキストを、クエリのコンテキストに含めて検索することが可能となります。つまり、「ピン留め」はLangChainのメモリのような役割を行います。
### LLM は Anthropic Claude3 haiku on Amazon Bedrock を利用

本ソリューションは日本語を利用するお客様を想定し、Anthropic Claude3 haiku の利用を前提としています。Claude 3 Haiku 基盤モデルは、Claude 3 ファミリーの中で最速かつ最もコンパクトなモデルであり、ほぼ瞬時の応答性と、人間の対話を模倣したシームレスな生成人工知能 (AI) エクスペリエンスを実現するように設計されています。

### その他の特徴

Expand All @@ -68,38 +42,12 @@ Amazon Kendra でのドキュメント検索のフィルター条件を指定す

2023/07/19 時点で英語のドキュメントに限定されますが、増分学習が可能です。検索結果の各ドキュメントの左下に表示される Goodボタン、Badボタン を押すことで、次回以降の検索結果に反映されます。

<!-- ![](docs/png/feature2.png) -->

#### (3) 明示的にcontextを指定しLLMのみを使用 (AIモードのみ)

AIモードの場合、ピン留めしたテキストをコンテキストとして含んでクエリを投げることが可能です。
それにより、コンテキスト情報を前提とした回答を生成することが可能です。

<!-- ![](docs/png/feature3.png) -->


## Search Flow / 検索の流れ

検索の流れは以下のとおりです。

#### Ragモード(#rag)

![](docs/png/flow-rag.png)

#### Kendraモード(#kendra)

![](docs/png/flow-kendra.png)


#### AIモード(#ai)

![](docs/png/flow-ai.png)



## Preview / 動作イメージ

![](docs/png/rag-screenshot.png)

![](docs/png/search-flow.png)

## デプロイ/開発

Expand All @@ -110,10 +58,9 @@ AIモードの場合、ピン留めしたテキストをコンテキストとし
| リソース | 1月あたりのコスト ($USD) |
| --------------------------------- | ---------------------:|
| Kendra Index | 810 |
| SageMaker Endpoint (g4dn.xlarge) | 530 |
| Fargate (0.5 vCPU, 1 GB Memory) | 18 |
| Amplify | 5 |
| 合計 | 1363 |
| 合計 | 833 |

* 価格は 開発時点での内容になります。最新情報は AWS 公式ウェブサイト(https://aws.amazon.com/ )にてご確認ください。

Expand Down
10 changes: 1 addition & 9 deletions amplify/backend/api/fargate/src/docker-compose-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,8 @@ services:
- ALLOW_ORIGINS=*
- SAGEMAKER_ENDPOINT_NAME=Rinna-Inference
- LLM=claude_bedrock
secrets:
- KENDRA_INDEX_ID
# - ANTHROPIC_API_KEY
networks:
- private
networks:
public:
private:
secrets:
KENDRA_INDEX_ID:
file: ../secrets/.secret-kendra
# ANTHROPIC_API_KEY:
# file: ../secrets/.secret-anthropic
private:
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ AWS_REGION=us-west-2
AWS_BEDROCK_REGION=us-east-1
ALLOW_ORIGINS=*
SAGEMAKER_ENDPOINT_NAME=Rinna-Inference
KENDRA_INDEX_ID=*******
ANTHROPIC_API_KEY=
LLM=claude_bedrock
AWS_ACCESS_KEY_ID=*******
Expand Down
13 changes: 0 additions & 13 deletions amplify/backend/api/fargate/src/langchain/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
3. `.env` ファイルを編集
- (MUST) `AWS_REGION` は AWS のリージョンを指定(Kendra や SageMaker が動いている)
- (MUST) `AWS_BEDROCK_REGION` には bedrock の利用リージョンを指定
- (MUST) `KENDRA_INDEX_ID` を Kendra の Index ID に指定
- (MUST) `AWS_ACCESS_KEY_ID` に Amplifyを操作できるユーザ のアクセスキーを設定
- (MUST) `AWS_SECRET_ACCESS_KEY` に に Amplifyを操作できるユーザ のシークレットアクセスキーを設定
- (WANT) `ALLOW_ORIGINS` は Access-Control-Allow-Origin の設定値 を指定
Expand Down Expand Up @@ -59,8 +58,6 @@
export ALLOW_ORIGINS="*"
# SAGEMAKER_ENDPOINT_NAME は SageMaker エンドポイント名 を指定
export SAGEMAKER_ENDPOINT_NAME="Rinna-Inference"
# KENDRA_INDEX_ID を Kendra の Index ID に指定
export KENDRA_INDEX_ID=*********
# export ANTHROPIC_API_KEY="xxxxxx" # Claude を利用するための API Key がセットされていればこちらに値をセットする
export LLM="rinna" # rinna, claude, claude_bedrock から指定可能ください。Anthropic を利用する場合は claudeを指定ください。
```
Expand Down Expand Up @@ -98,7 +95,6 @@ VSCODEからデバッグ実行するには、
"AWS_BEDROCK_REGION": "us-west-2",
"ALLOW_ORIGINS": "*",
"SAGEMAKER_ENDPOINT_NAME": "Rinna-Inference",
"KENDRA_INDEX_ID": "************",
"LLM": "rinna",
// "ANTHROPIC_API_KEY" : "",
},
Expand All @@ -113,12 +109,3 @@ VSCODEからデバッグ実行するには、
## 補足 docker-compose.ymlの用途について
`amplify/backend/api/fargate/src/docker-compose.yml` はローカル開発ではご利用頂けないのでご注意ください。
docker-compose.yml の中で、secret として宣言されている `KENDRA_INDEX_ID` は、コンテナの /run/secret/配下にファイルをバインドする機能なのですが、
アプリ内では、`KENDRA_INDEX_ID` は、`環境変数` として読み込む設計になっているため、docker-compose up を行なっても、`KENDRA_INDEX_ID` を発見できないエラーが発生して正しく動きません。
理由は次の通りです。
Amplifyは Custom の Dockerイメージを利用してバックエンドを構築する場合、 docker-compose.yml を解析して、自動でデプロイ用の CloudFormation を作成して、バックエンドを構築する仕組みとなっています。
つまり、docker-compose.yml は AWS 上でのセットアップのために利用されます。
なお、本ソリューションのセキュリティ要件として、`KENDRA_INDEX_ID` は SecretManager で管理し、コンテナ起動時に環境変数に読み込む挙動になっているのですが、それを実現するために、docker-compose.yml で `KENDRA_INDEX_ID` を secret で管理する指定にしています。
1 change: 0 additions & 1 deletion amplify/backend/api/fargate/src/langchain/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
allow_headers=["*"],
)
REGION = os.environ["AWS_REGION"]
KENDRA_INDEX_ID: str = os.environ["KENDRA_INDEX_ID"]
SAGEMAKER_ENDPOINT_NAME: str = os.environ.get("SAGEMAKER_ENDPOINT_NAME", None)
LLM: Literal["rinna", "claude", "claude_bedrock"] = os.environ.get("LLM", "claude_bedrock")
kendra_client = boto3.client("kendra", region_name=REGION)
Expand Down
77 changes: 77 additions & 0 deletions amplify/backend/awscloudformation/override.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// Licensed under the MIT-0 License (https://github.com/aws/mit-0)

import { AmplifyProjectInfo, AmplifyRootStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyRootStackTemplate, amplifyProjectInfo: AmplifyProjectInfo) {
const authRole = resources.authRole;

const basePolicies = Array.isArray(authRole.policies)
? authRole.policies
: [authRole.policies];

// amplify add で追加した Lambda 関数の ARN を取得する
const envName = amplifyProjectInfo.envName;

// 開発中の環境からデプロイ先のリージョン名を取得
const fs = require("fs");
const amplify_meta_json = JSON.parse(fs.readFileSync("amplify/team-provider-info.json"));
const region_name = amplify_meta_json[envName].awscloudformation.Region;

// arnから抽出してデプロイ先の Account ID を取得
const authRoleArn = amplify_meta_json[envName].awscloudformation.AuthRoleArn;
const account_id = authRoleArn.split(':')[4];

const functionArn = "arn:aws:lambda:" + region_name + ":" + account_id + ":function:streamClaude3-" + envName

// claude stream func Lambda の Invoke権限を追加
authRole.policies = [
...basePolicies,
{
policyName: "amplify-permissions-custom-resources",
policyDocument: {
Version: "2012-10-17",
Statement: [
{
Resource: functionArn,
Action: [
"lambda:InvokeFunction"
],
Effect: "Allow",
},
],
},
},
];

// .env ファイルを読み込む
let envContent = fs.readFileSync('.env', 'utf-8');

// STREAM_FUNC_ARN の値を更新または追加
const streamFuncArnPattern = /^VITE_STREAM_FUNC_NAME=.*/gm;
if (streamFuncArnPattern.test(envContent)) {
envContent = envContent.replace(streamFuncArnPattern, `VITE_STREAM_FUNC_NAME=streamClaude3-${envName}`);
} else {
envContent += `\nVITE_STREAM_FUNC_NAME=streamClaude3-${envName}`;
}

// VITE_MODEL_ID の値を追加
const modelId = "anthropic.claude-3-haiku-20240307-v1:0"
const modelIdPattern = /^VITE_MODEL_ID=.*/gm;
if (modelIdPattern.test(envContent)) {
envContent = envContent.replace(modelIdPattern, `VITE_MODEL_ID=${modelId}`);
} else {
envContent += `\nVITE_MODEL_ID=${modelId}`;
}

// VITE_BEDROCK_REGION の値を追加
const bedrockRegionPattern = /^VITE_BEDROCK_REGION=.*/gm;
if (bedrockRegionPattern.test(envContent)) {
envContent = envContent.replace(bedrockRegionPattern, `VITE_BEDROCK_REGION=${region_name}`);
} else {
envContent += `\nVITE_BEDROCK_REGION=${region_name}`;
}

// .env ファイルに書き込む
fs.writeFileSync('.env', envContent);
}
26 changes: 25 additions & 1 deletion amplify/backend/backend-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,15 @@
"serviceType": "managed"
}
},
"function": {},
"custom": {},
"function": {
"streamClaude3": {
"build": true,
"dependsOn": [],
"providerPlugin": "awscloudformation",
"service": "Lambda"
}
},
"hosting": {
"amplifyhosting": {
"providerPlugin": "awscloudformation",
Expand All @@ -77,6 +85,22 @@
}
},
"parameters": {
"AMPLIFY_function_streamClaude3_deploymentBucketName": {
"usedBy": [
{
"category": "function",
"resourceName": "streamClaude3"
}
]
},
"AMPLIFY_function_streamClaude3_s3Key": {
"usedBy": [
{
"category": "function",
"resourceName": "streamClaude3"
}
]
},
"AMPLIFY_hosting_amplifyhosting_appId": {
"usedBy": [
{
Expand Down
6 changes: 6 additions & 0 deletions amplify/backend/function/streamClaude3/amplify.state
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"pluginId": "amplify-nodejs-function-runtime-provider",
"functionRuntime": "nodejs",
"useLegacyBuild": true,
"defaultEditorFile": "src/index.js"
}
10 changes: 10 additions & 0 deletions amplify/backend/function/streamClaude3/custom-policies.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"Action": [
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:*::foundation-model/*"
]
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"lambdaLayers": []
}
1 change: 1 addition & 0 deletions amplify/backend/function/streamClaude3/parameters.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
5 changes: 5 additions & 0 deletions amplify/backend/function/streamClaude3/src/event.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
Loading

0 comments on commit 4b8ee29

Please sign in to comment.