はじめに
SpringAIは、SpringBootを活用してAIアプリケーションを開発するためのフレームワークで、AIモデルプロバイダーや、ベクトルデータベースプロバイダーとの接続をサポートしている。この度は、OpenAIのモデルでテキストのエンベディングを行い、ベクトルデータベースPineconeに生成したベクトルの登録を確認した。
【参考】
https://docs.spring.io/spring-ai/reference/index.html
の情報では、プロパティファイルに接続情報を記載するのみで動作するはずだが、Embeddingがうまくできず、Javaのクラスに接続情報を記載した。
環境
- Windows11
- Java 17
- SpringAI 1.0.0-SNAPSHOT
事前に必要なもの
- PineconeのIndex
- エンドポイントのURL
- APIキー
- OpenAIのAPIキー
依存関係の追加
Mavenプロジェクトで実行しており、pom.xmlの依存関係には、次のものを追加した。
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-transformers</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pinecone-store</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
Pinecone接続情報の設定
次の4つの情報が必要。Severlessの場合、Environmentの情報がわかりにくかったが、エンドポイントのURLからAPIキー以外の情報が取得できる。
- APIキー
- Environment
- ProjectID
- 作成したIndex名
接続先のエンドポイントのURLは、以下のような形式。
https://<Index名>-<ProjectID>.svc.<Environment>.pinecone.io
Pinecone設定用のConfigクラスに、必要な情報を設定した。
【Pineconeの接続情報の設定】
@Bean
public PineconeVectorStoreConfig pineconeConfig() {
return PineconeVectorStoreConfig.builder()
.withApiKey("<APIキー>")
.withEnvironment("<Environment>")
.withProjectId("<ProjectID>")
.withIndexName("<Index名>")
.withNamespace("") // the free tier doesn't support namespaces.
.build();
}
テキストのエンベディングのため、EmbeddingModelを指定。使用モデルは、「text-embedding-ada-002」を指定した。プロパティの設定のみでできるかと思うが、うまくいかず、結局OpenAiEmbeddingModel、OpenAiEmbeddingOptionsを使用した。
【EmbeddingModelの作成】
@Bean
EmbeddingModel customEmbeddingModel(){
return new OpenAiEmbeddingModel(
new OpenAiApi(System.getenv("SPRING_AI_OPENAI_API_KEY")),
MetadataMode.EMBED,
OpenAiEmbeddingOptions.builder()
.withModel("text-embedding-ada-002")
.build(),
RetryUtils.DEFAULT_RETRY_TEMPLATE);
}
PineconeVectorStoreにcustomEmbeddingModelを登録することで、vectoreStoreで、エンベディングを行い、Pineconeにベクトルを登録できる。
【VectorStoreクラスの生成】
private EmbeddingModel customEmbeddingModel;
private VectorStore vectorStore ;
public TextEmbeddingService(EmbeddingModel customEmbeddingModel,PineconeVectorStoreConfig pineconeConfig) {
this.customEmbeddingModel = customEmbeddingModel;
this.vectorStore = new PineconeVectorStore(pineconeConfig, customEmbeddingModel);
}
Documentクラスに、エンベディングするテキストを設定し、vectorStore.add(documents)により、Pineconeに登録できる。
Metadataを登録する場合、DocumentクラスにMapクラスで登録する。
【データ登録】
List <Document> documents = List.of(
new Document("TEST123 This is a test1", Map.of("meta1", "meta2")),
new Document("TEST123 This is a test2"),
new Document("TEST123 This is a test3.", Map.of("meta3", "meta4")));
// Add the documents
vectorStore.add(documents);
Documentクラスにエンベディングしたい文字列を設定すると、ベクトルに変換されてPineconeに登録されるが、設定した文字列も、METADATAとして、document_contentに登録される。
Pineconeを検索する場合、similaritySearch関数により指定したtextの類似項目を取得することができる。
public List<Document> getSimilarDocuments(String text, int topK) {
return vectorStore.similaritySearch(SearchRequest.query(text).withTopK(topK));
}
おわりに
接続情報をソースコードに記載せずとも動作するはずだが、うまくいかなかった。