Pinecone Assistantを試す
お客様の独自データから正確な洞察を安全に生成するAPIサービス、Pinecone Assistantがパブリックプレビュー版としてご利用いただけるようになりました。今年初めにベータ版を発表して以来、数千人の開発者が幅広い用途(例えば、財務分析、法的調査、eコマースアシスタントなど)でRAGベースのアシスタントを作成しています。本日、パブリックプレビュー版としてこの機能をすべてのユーザーに公開できることを嬉しく思います。
今回のリリースでは、LLMサポートの拡張、正確性と完全性のベンチマーク評価用評価API、メタデータによるファイルの関連付けとフィルタリング機能、新しいコンソールUIなどの新機能をご紹介いたします。欲しい答えを簡単に手に入れる方法
開発者は、依然として、個人データに関する質問に正確に回答できるAIアシスタントの構築に苦労しています。一般に公開されているモデルは、このデータに気づいておらず、Retrieval Augmented Generation(RAG)のようなアプローチで提供するには、AIの専門知識と貴重なエンジニアリング時間が必要です。
Pinecone Assistantは、RAGを搭載したアプリケーションの構築に必要な多くのシステムやステップ(チャンキング、エンベッディング、ファイルストレージ、クエリ計画、ベクトル検索、モデルのオーケストレーション、再ランキングなど)を抽象化しながら、プライベートデータに関する高品質で信頼性の高い回答を提供することに重点を置いています。これは、シンプルなAPIを通じて行われ、これにより、.txtまたは.pdf形式のファイルを追加し、数分以内に構築を開始することができます。アップロードされたファイルは暗号化され、分離され、モデルのトレーニングを行わずに有益な回答を生成する目的でのみ使用されます。いつでも簡単にデータを恒久的に削除できるため、アシスタントが何を記憶し、何を忘れるかを管理することができます。
Pinecone Serverlessに支えられ、高速かつ高精度なベクトル検索用に特別に構築された
RAGに関する当社の研究では、何十億ものエンベッディングを効率的に保存し検索できるPinecone Serverlessのようなベクトルデータベースを活用することで、多くのタスクにおいてLLMのパフォーマンスを劇的に向上できることが示されています。Pinecone AssistantはServerlessを活用して、最も関連性の高い文書のみを取得し、一貫した文脈を構築することで、LLMが各分野で最も正確な結果を生成できるようにします。初期のベンチマークでは、Pinecone Assistantは他のアシスタントAPI(OpenAI Assistantなど)よりも優れたパフォーマンスを発揮することが示されています。
AIアシスタントの評価、特にプライベートデータを使用した知識集約型のタスクについては、多くの開発者にとって依然として課題となっています。その理由はいくつかありますが、1)RAGパイプラインのすべてのコンポーネントにベンチマークが確立されているわけではないこと、2)生成型AIの出力はスタイル、構造、内容が大幅に異なる可能性があり、一貫した評価基準を適用することが難しいこと、3)事実の検証は、信頼できるソースとの照合が必要になることが多いため、難しいこと、などが挙げられます。
そこで、AIが生成した回答が基準となる回答とどの程度一致しているかを測定するRAGベンチマークフレームワークを開発しました。生成された回答と基準となる回答の一致度を比較することで、RAGシステムの途中出力ではなく、エンドユーザーが目にするものを評価し、人間の好みを代用することができます。このフレームワークは現在、評価APIを通じて、Pinecone Assistantのすべてのスタンダードおよびエンタープライズユーザーが利用可能です。
Pinecone Assistantはすべてのユーザーが利用可能です。今すぐ構築を開始しましょう
Pinecone Assistant はすべてのユーザが利用可能です。今すぐ構築を開始しましょう。 Pinecone Assistant は現在、すべてのユーザがパブリックプレビューを利用可能です。 Starter (無料) プランでは、1GB のファイルストレージ、200K の出力トークン、1.5M の入力トークンに制限されています。 StandardとEnterpriseプランのユーザーは、無制限のアシスタントにアクセスでき、月額ストレージは3ドル/GB、1Mインプットトークンあたり8ドル、1Mアウトプットトークンあたり15ドル、アシスタント1人あたり0.20ドル/日です。 アシスタントの価格とパブリックプレビューの制限については、こちらをご覧ください。
今後数ヶ月のうちに、LLMの追加、生成された回答の引用や参照に関する制御の強化、アシスタントに指示を与える機能、評価APIの機能強化を予定しています。 Pinecone Assistantの詳細、サンプルアプリケーションを試して、知識豊富なAIアプリケーションの構築を今すぐ始めましょう。
ベクトルDBベンダーがRAG用のフレームワーク・サービスを作ったという感じかな。個人的に、評価もセットになっているというところに興味がある。
ドキュメントに従って進めてみるが、以下に制限等が書いてある。
アップロードできるファイルの制約
- ファイル形式は
.txt
と.pdf
のみ - クエリごとの最大入力トークンは64000
プランごとの制約
項目 | Starter | Standard/Enterprise |
---|---|---|
最大アシスタント数 | 3 | 無制限 |
最大トークン数/分 | 30,000 | 150,000 |
LLMの最大処理トークン数 | 1,500,000 | 無制限 |
最大出力トークン | 200,000 | 無制限 |
ファイルストレージ容量 | 1GB | 10GB |
アップロード可能なファイル数 | 10 | 10000 |
Assistantの料金
項目 | Starter | Standard | Enterprise |
---|---|---|---|
ストレージ料金 | (1GB込) | $3 / GB / 月 | $3 / GB / 月 |
入力トークン料金 | (150,000込) | $8 / 1M | $8 / 1M |
出力トークン料金 | (200,000込) | $15 / 1M | $15 / 1M |
アシスタント日額 | - | $0.20 / アシスタント / 日 | $0.20 / アシスタント / 日 |
入出力トークン料金は、gpt-4oかclaude-3.5-sonnetあたりと近いのかなーと思うけど、ちょっと割高感ある。PineconeのブログではAzure OpenAI gpt-4oとAmazon Bedrock Claude−3.5−Sonnetが使用されている様子なので、諸々管理等の手間賃と思えば、まあ許容できるケースもあるのかも?
ストレージはOpenAI Assistant APIと似たような感じ。
アシスタントごとに料金がかかるのはあるけど(ざっくり$6/月)、それほど大きな金額でもないか。
名前の通り、OpenAI Assitant APIが競合って感じかなぁ。モデル起点かデータ起点かが違いのイメージ。
自分は知らなかったけど、Inference APIみたいなサービスもあるんだね。Embeddingモデルが提供されているようだけど、multilingual-e5-largeとかが提供されている。モデルプロバイダーがどんどん手を広げるのと同じくベクトルDBベンダーもどんどん手を広げているって感じだなぁ。
パッケージインストール
ではやっていく。Colaboratoryで。
インストール
pip install --upgrade pinecone pinecone-plugin-assistant
!pip freeze | grep pinecone
pinecone==5.3.1
pinecone-plugin-assistant==0.2.0
pinecone-plugin-inference==1.1.0
pinecone-plugin-interface==0.0.7
なるほど、通常のSDKに加えて、プラグインで機能を増やせるようになっているみたい。
アシスタントの作成
まずアシスタントを作成する。
from pinecone import Pinecone
from google.colab import userdata
pc = Pinecone(api_key=userdata.get('PINECONE_API_KEY'))
assistant = pc.assistant.create_assistant(
assistant_name="example-assistant",
metadata={
"author": "kun432",
"version": "1.0"
},
timeout=30 # アシスト操作が完了するまで30秒ほど待つ
)
PineconeのGUIを見てみると、アシスタントが作成されていた。GUIからでも作成できるみたい。
アシスタントをクリックすると見慣れたPlayground的な画面が出てくる。ここでファイルをアップロードして試したりもできるみたいだけど、ここは割愛。
アシスタントにファイルをアップロード
アシスタントでRAGを行うためのファイルをアップロードする。対応しているのは.txtと.pdfなので、今回は以下の、神戸市が公開している観光に関する統計・調査資料のうち、「令和4年度 神戸市観光動向調査結果について」を使う。
PDFファイル直
PDFファイルをダウンロード
!wget https://www.city.kobe.lg.jp/documents/15123/r4_doukou.pdf
アシスタントにアップロード
from pinecone import Pinecone
from google.colab import userdata
pc = Pinecone(api_key=userdata.get('PINECONE_API_KEY'))
# アシスタント作成後は、以下のようにアシスタント名で接続する
assistant = pc.assistant.Assistant(
assistant_name="example-assistant",
)
# アシスタントにファイルをアップロード
response = assistant.upload_file(
file_path="r4_doukou.pdf",
timeout=None
)
print(response)
{'created_on': '2024-09-21T13:03:31.860479167Z',
'id': '34ede5a0-5d9d-4754-b1f1-2f8f500fd3f1',
'metadata': None,
'name': 'r4_doukou.pdf',
'percent_done': 1.0,
'signed_url': None,
'size': 1180120.0,
'status': 'Available',
'updated_on': '2024-09-21T13:03:53.013769009Z'}
アップロードできたみたい。
アップロードしたファイルの状態は以下のように確認できる。
# ファイルのステータスの確認(上と同じ出力)
print(assistant.describe_file(file_id="34ede5a0-5d9d-4754-b1f1-2f8f500fd3f1"))
{'created_on': '2024-09-21T13:03:31.860479167Z',
'id': '34ede5a0-5d9d-4754-b1f1-2f8f500fd3f1',
'metadata': None,
'name': 'r4_doukou.pdf',
'percent_done': 1.0,
'signed_url': None,
'size': 1180120.0,
'status': 'Available',
'updated_on': '2024-09-21T13:03:53.013769009Z'}
アシスタントにアップロードしたファイルの一覧
print(assistant.list_files())
[{'created_on': '2024-09-21T13:03:31.860479167Z',
'id': '34ede5a0-5d9d-4754-b1f1-2f8f500fd3f1',
'metadata': None,
'name': 'r4_doukou.pdf',
'percent_done': 1.0,
'signed_url': None,
'size': 1180120.0,
'status': 'Available',
'updated_on': '2024-09-21T13:03:53.013769009Z'}]
ファイルの削除はこちら
なお、アップロードしたファイルはGUIでも確認できた。ベクトルDB側のメニューには何も変化がなかったので、完全にアシスタント内部で管理されるように思える
アシスタントとRAGでチャット
ではRAG。
from pinecone import Pinecone
from pinecone_plugins.assistant.models.chat import Message
from google.colab import userdata
pc = Pinecone(api_key=userdata.get('PINECONE_API_KEY'))
# アシスタントに接続
assistant = pc.assistant.Assistant(
assistant_name="example-assistant",
)
# アシスタントとチャット
chat_context = [Message(content='神戸への主な交通手段の内訳を教えて。')]
response = assistant.chat_completions(messages=chat_context)
結果はこんな感じ
import json
print(json.dumps(response.to_dict(), indent=2, ensure_ascii=False))
{
"id": "000000000000000067c3b0b610083c1a",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"role": "assistant",
"content": "神戸への主な交通手段の内訳は以下の通りです:\n\n- **車、バイク**: 40.9%\n- **鉄道**(新幹線、JR、阪急、阪神、山陽の計): 46.9%\n - 新幹線: 11.0%\n - JR: 18.9%\n - 阪急: 9.8%\n - 阪神: 6.3%\n - 山陽: 0.9%\n- **レンタカー**: 1.1%\n- **タクシー**: 0.2%\n- **バス**: 5.6%\n- **船・フェリー**: 0.5%\n- **飛行機(神戸空港)**: 2.5%\n- **飛行機(伊丹空港)**: 1.0%\n- **飛行機(関西空港)**: 0.6%\n- **その他**: 0.8% [1, pp. 6].\n\n地区別に見ると、鉄道利用者の割合が最も高いのは北野(62.2%)で、次いで神戸港(60.0%)、市街地(57.3%)となっています。一方、車やバイクの利用者が最も多いのは西北神(85.3%)です [1, pp. 6].\n\nReferences:\n1. [r4_doukou.pdf](https://storage.googleapis.com/knowledge-prod-files/(....snip....) \n"
}
}
],
"model": "gpt-4o-2024-05-13"
}
RAGのドキュメントからの内容を踏まえて回答されているのがわかるし、どうやらアップロードしたファイルは引用できるようにGoogle Cloud Storageで公開されるようになっているみたい(署名付きURLになっていた)。あと、回答の生成に使用されたモデルはgpt-4oの様子。
ストリーミングも可能。
chat_context = [Message(content='神戸への主な交通手段の内訳を教えて。')]
chunks = assistant.chat_completions(messages=chat_context, stream=True)
for chunk in chunks:
if chunk:
print(str(chunk.choices[0].delta.content))
# ↓わかりやすいように改行をいれるが通常は不要
print()
神
戸
への
主
な
交通
手
段
の
内
訳
は
以下
の
通
り
です
:
(snip)
会話履歴を組み立ててみる。
chat_context = [
Message(content='神戸の観光について調べてるんだよね。', role='user'),
Message(content='そうなんですね。私は神戸の観光についての統計調査についてお答えできますよ。どんなことを知りたいですか?', role='assistant'),
Message(content='じゃあ、観光客が神戸に行く時の主な交通手段の内訳を教えて。', role='user')
]
response = assistant.chat_completions(messages=chat_context)
print(str(response.choices[0].message.content))
神戸に行く際の主な交通手段については、以下のような内訳があります。
全市のデータでは、最も多いのは「車、バイク」で40.9%、次いで鉄道(「新幹線」「JR」「阪急」「阪神」「山陽」の計)が46.9%となっています [1, pp. 6]。
地区別に見ると、鉄道利用者の割合が最も高いのは『北野』で62.2%、次いで『神戸港』で60.0%、『市街地』で57.3%です。一方、『西北神』では「車、バイク」の利用が85.3%と非常に高い割合を占めています [1, pp. 6]。
また、バスの利用者は『有馬』で18.6%と他の地区に比べて高い割合となっています [1, pp. 6]。
References:
(snip)
会話を続けてみる。
# アシスタントのレスポンスを会話履歴に追加
chat_context.append(
Message(
content=str(response.choices[0].message.content),
role=response.choices[0].message.role,
)
)
chat_context.append(Message(content='鉄道会社の内訳もわかる?'))
response = assistant.chat_completions(messages=chat_context)
print(str(response.choices[0].message.content))
はい、鉄道会社ごとの利用状況もわかります。以下がその内訳です。
全市のデータでは、鉄道利用者の内訳は以下の通りです:
- JR: 18.9%
- 阪急: 9.8%
- 阪神: 6.3%
- 山陽: 0.9%
- 新幹線: 11.0% [1, pp. 6]
地区別に見ると、例えば『北野』では以下のようになっています:
- JR: 17.4%
- 阪急: 15.6%
- 阪神: 6.2%
- 山陽: 0.6%
- 新幹線: 22.4% [1, pp. 6]
他の地区の詳細な内訳も同様に記載されていますが、全体的にJRと新幹線の利用が多い傾向にあります。
References:
(snip)
ドキュメントにメタデータを付与して置いた場合は、メタデータでフィルタができる。アップロード時にメタデータの指定が必要だけど、今回は設定してなかったのでスキップ。
chat_context = [Message(content='神戸への主な交通手段の内訳を教えて。')]
response = assistant.chat_completions(messages=chat_context, filter={"category": "siteseeing"})
print(str(response.choices[0].message.content))
モデルの変更。デフォルトはgpt-4oで、claude-3-5-sonnetも選択できる、って感じかな。
chat_context = [Message(content='神戸への主な交通手段の内訳を教えて。')]
response = assistant.chat_completions(messages=chat_context, model="claude-3-5-sonnet")
print(str(response.choices[0].message.content))
ここまでの所感としては、RAGエージェントが簡単に作れるという印象。これまでであれば、
- モデル: OpenAI
- ベクトルDB: Pinecone
となっていたのが、Pineconeだけで完結するということになる。が、それはOpenAI Assitant APIをを使った場合も同じで、逆にOpenAI Assistantが提供している以下のような機能は見当たらなかった。
- Threadを使ったステートフルな会話履歴
- code_interpreterやFunction Calling
この点を踏まえると、Pinecone Agentの強みは、ブログにもある通り、
Pinecone Assistantは、RAGを搭載したアプリケーションの構築に必要な多くのシステムやステップ(チャンキング、エンベッディング、ファイルストレージ、クエリ計画、ベクトル検索、モデルのオーケストレーション、再ランキングなど)を抽象化しながら、プライベートデータに関する高品質で信頼性の高い回答を提供することに重点を置いています。
初期のベンチマークでは、Pinecone Assistantは他のアシスタントAPI(OpenAI Assistantなど)よりも優れたパフォーマンスを発揮することが示されています。
あたりの「精度高いRAGエージェント」を「シンプル」に実現するということにフォーカスしているということだと思う。あ、あとはRAGエージェントだけあって根拠の引用が提示されるのもメリットじゃないかな(Assitant APIでその辺ができるのかは知らない)
で、それを確認するために、評価APIがあるということになるのだろう。
評価
評価を行うためのAPI。これはPinecone SDKとは全く関係がないAPIエンドポイントとして提供されている様子。ただし、注意としては以下。
- APIはStandard/Enterpriseプランの場合のみ利用可能
- (多分)Assitantと同じく、入出力トークンで課金される
サンプルのコード。シンプルにrequestsを使って、質問・LLMの回答・正しい回答を投げるだけ。
import requests
from google.colab import userdata
url = "https://prod-1-data.ke.pinecone.io/assistant/evaluation/metrics/alignment"
payload = {
"question": "フランス、イギリス、スペインの首都はどこですか?",
"answer": "パリはフランスの首都であり、バルセロナはスペインの首都です。",
"ground_truth_answer": "パリはフランスの首都であり、ロンドンはイギリスの首都であり、マドリッドはスペインの首都です。"
}
headers = {
"Api-Key": userdata.get('PINECONE_API_KEY'),
"Content-Type": "application/json"
}
response = requests.request("POST", url, json=payload, headers=headers)
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
{
"metrics": {
"correctness": 0.6667,
"completeness": 0.6667,
"alignment": 0.6667
},
"reasoning": {
"evaluated_facts": [
{
"fact": {
"content": "パリはフランスの首都である。"
},
"entailment": "entailed"
},
{
"fact": {
"content": "ロンドンはイギリスの首都である。"
},
"entailment": "entailed"
},
{
"fact": {
"content": "マドリッドはスペインの首都である。"
},
"entailment": "contradicted"
}
]
},
"usage": {
"prompt_tokens": 1295,
"completion_tokens": 71,
"total_tokens": 1366
}
}
評価結果は、評価メトリクスによる数値と、LLMの回答を正しい回答に照らし合わせて如何に根拠となるポイントを抑えているかの説明で返される。
評価メトリクス
メトリクス | 説明 |
---|---|
correctness(正確性) | RAGシステムの回答の正確性 |
completeness(完全性) | 基準回答と比較したRAGシステムの回答の完全性 |
alignment | 正確性と完全性のスコアを合わせたスコア |
根拠説明
ステータス | 説明 |
---|---|
entailed | 根拠が正しい回答によって裏付けられている |
contradicted | 根拠が正しい回答と矛盾している |
neutral | 根拠が正しい回答によって支持も否定もされていない |
上にも書いた通り、評価APIはPinecone SDKと直接連携していないので、
- 評価データを作成
- 評価データを元にPinecone Assistantで推論
- 結果を評価APIで判定
という流れになるのだと思う。このあたりSDKやGUIと連動して、もっとシームレスにやれたらいいんじゃないかと思うけど、逆に今のほうが汎用的には使えるということも言える(Pineconeのstandard以上のプラン契約があれば、Pinecone使ってなくても使えるということでもある)。まあpublic previewだし。
まとめ
少し上の所感に書いた通り。シンプルにRAGエージェントが作れるってのが1つのウリ。
で、もう1つのウリである精度については自分で評価しないと判断できないと思う。ただ少し試した感じだと悪くなさそうな印象を持っている。RAGで弱いと言われている、全体概要的なクエリでもなんかいい感じに答えてくれている感がある。
あと、ここはちょっと疑問なんだけど、すでにPinecone上で作成済みのベクトルDBとは連携できないのかな?そういうインタフェースが見当たらなかったのだけど、ここつなげると良いと思うんだよね。そしたらもう自分でエージェント作る必要がなくなるし。BedrockにおけるKnowledge baseとAgentsみたいな感じにしたほうが使いやすそう。
まだpublic betaなので、色々足りないところもあるとは思うが、個人的には現時点でも十分使いやすい印象。今後に期待できそうだけど、ニーズがどれだけあるかなーというところかな。
主に引用周りで機能追加されたのかな?