DeepSeek R1はその優れた推論チェーン処理能力で注目を集めていますが、Spring AIなどの主要フレームワークでは流式出力や思考過程の保持に制限があり、十分なサポートが提供されていません。deepseek4j 1.4では、ベクトルモデル対応など重要な機能拡張が実装されました。
設計思想
このライブラリは、DeepSeek APIの利用を簡素化し、Function CallingやJSONパース、Reasonerといった高度な機能を容易にアプリケーションへ統合できるように設計されています。ただし、DeepSeek公式にはベクトルエンコーダーが存在しないため、当初はベクトル検索機能は含まれていませんでした。
技術的選択
現在、R1モデル上でのプライベートナレッジベース構築ニーズが高まっており、私たちはOpenAI互換プロトコルを介してベクトルモデルを統合するアプローチを採用しました。これにより以下の利点が得られます:
- 軽量性:追加依存ライブラリ不要
- 互換性:既存コードとの衝突なし
- 標準化:業界標準プロトコルによる学習コスト低減
環境構築
Ollama モデル設定
# 推論用モデル
ollama run deepseek-r1:14b
# 埋め込み用モデル
ollama run bge-m3:latest
Milvus データベース起動
# スクリプト取得
curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.sh
# 起動
bash standalone_embed.sh start
Maven 依存関係
<dependency>
<groupId>io.github.pig-mesh.ai</groupId>
<artifactId>deepseek-spring-boot-starter</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>io.milvus</groupId>
<artifactId>milvus-sdk-java</artifactId>
<version>2.5.3</version>
</dependency>
application.yml 設定例
deepseek:
base-url: http://localhost:11434/v1
model: deepseek-r1:14b
api-key: ollama-local
embedding:
api-key: ${deepseek.api-key}
base-url: ${deepseek.base-url}
model: bge-m3:latest
ナレッジベース初期化
データベース接続
ConnectConfig config = ConnectConfig.builder()
.uri("YOUR_CLUSTER_ENDPOINT")
.token("YOUR_TOKEN")
.build();
MilvusClientV2 client = new MilvusClientV2(config);
テキストのベクトル化と登録
@Autowired
private EmbeddingClient embedder;
public void indexDocuments() {
String content = Files.readString(Paths.get("/path/to/doc.txt"));
List<String> chunks = splitText(content, 400);
List<JsonObject> records = chunks.stream().map(chunk -> {
List<Float> vector = embedder.embed(chunk);
JsonObject obj = new JsonObject();
JsonArray vecArray = new JsonArray();
vector.forEach(vecArray::add);
obj.add("vector", vecArray);
obj.addProperty("content", chunk);
return obj;
}).collect(Collectors.toList());
InsertReq req = InsertReq.builder()
.collectionName("knowledge_base_v1")
.data(records)
.build();
client.insert(req);
}
RAGエンドポイント実装
@GetMapping(value = "/ask", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ChatCompletionResponse> handleQuery(@RequestParam String question) {
List<Float> queryVec = embeddingClient.embed(question);
SearchReq searchReq = SearchReq.builder()
.collectionName("knowledge_base_v1")
.data(Collections.singletonList(new FloatVec(queryVec)))
.outputFields(List.of("content"))
.topK(3)
.build();
SearchResp results = milvusClient.search(searchReq);
String context = results.getSearchResults().stream()
.flatMap(List::stream)
.map(r -> r.getEntity().get("content").toString())
.collect(Collectors.joining("\n---\n"));
ChatCompletionRequest chatReq = ChatCompletionRequest.builder()
.model("deepseek-r1:14b")
.addUserMessage(
"以下の参考情報を基に、ユーザーの質問に答えてください。\n\n" +
"【質問】\n" + question + "\n\n" +
"【参考情報】\n" + context
)
.build();
return deepSeekClient.chatFluxCompletion(chatReq);
}
改善ポイント
- ハイブリッド検索:キーワード+ベクトルの併用
- 結果再ランキング:関連度スコアによる並び替え
- Prompt最適化:指示文の精密化とフォーマット統一
- 定期更新:ナレッジベースの陳腐化防止
- キャッシュ戦略:高頻度クエリのレスポンス高速化