chore: 清理 docs 目录冗余文档(55个→9个)
删除: - docs/1.0/ 全部22个(旧Simple KB文档,已被替代) - docs/2.0/ 全部2个(空文件/过时) - docs/design/ 全部4个(旧功能设计) - docs/plans/ 旧版5个(保留v2.0设计文档) - docs/superpowers/ 全部4个(飞书集成文档) - docs/根目录杂项 8个(开发规范/快速参考/调试/飞书/Git设置) - docs/3.0/knowledge_graph_analysis.md(不相关) 保留: - docs/3.0/ 考核工作流设计 2个 - docs/plans/ v2.0设计文档 1个 - docs/tests/ 测试文档 6个 合计: 55个 → 9个 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,219 +0,0 @@
|
||||
# Embedding モデル ID 連携の修正
|
||||
|
||||
## 🐛 問題の記述
|
||||
|
||||
```
|
||||
混合検索失敗: NotFoundException: ModelConfig with ID "embedding-3" not found or not owned by user.
|
||||
```
|
||||
|
||||
## 🔍 問題の分析
|
||||
|
||||
### 混同されやすい概念
|
||||
|
||||
システム内には2種類の異なる「ID」が存在します:
|
||||
|
||||
1. **モデル設定テーブルの ID** (`ModelConfig.id`)
|
||||
- データベースの主キー
|
||||
- 例:`"embedding-3"`, `"default-embedding"`
|
||||
- 用途:`ModelConfigService.findOne(id, userId)`
|
||||
|
||||
2. **モデル識別子** (`ModelConfig.modelId`)
|
||||
- AI ベンダー側でのモデル名
|
||||
- 例:`"text-embedding-3-large"`, `"text-embedding-ada-002"`
|
||||
- 用途:AI API 呼び出し時のパラメータ
|
||||
|
||||
### データフロー
|
||||
|
||||
```
|
||||
ユーザー設定: user_setting.selectedEmbeddingId = "embedding-3" ✅ テーブルID
|
||||
|
||||
フロントエンド: settings.selectedEmbeddingId
|
||||
↓ 転送
|
||||
バックエンド Controller: selectedEmbeddingId = "embedding-3"
|
||||
↓ 転送
|
||||
ChatService: embeddingModel.id = "embedding-3" ✅ 正常
|
||||
↓ 転送
|
||||
hybridSearch: embeddingModelId = "embedding-3"
|
||||
↓ 転送
|
||||
EmbeddingService.getEmbeddings(embeddingModelId)
|
||||
↓ 呼び出し
|
||||
ModelConfigService.findOne("embedding-3", userId) ✅ 正常
|
||||
```
|
||||
|
||||
### 以前の誤り
|
||||
|
||||
**ChatService.ts (誤り):**
|
||||
|
||||
```typescript
|
||||
// 182行目付近
|
||||
searchResults = await this.hybridSearch(
|
||||
[message],
|
||||
userId,
|
||||
embeddingModel.modelId, // ❌ 誤り! "text-embedding-3-large" を渡してしまっていた
|
||||
);
|
||||
```
|
||||
|
||||
**hybridSearch (受信側):**
|
||||
|
||||
```typescript
|
||||
private async hybridSearch(
|
||||
keywords: string[],
|
||||
userId: string,
|
||||
embeddingModelId?: string, // "text-embedding-3-large" を受け取ってしまう
|
||||
)
|
||||
```
|
||||
|
||||
**EmbeddingService (期待値):**
|
||||
|
||||
```typescript
|
||||
async getEmbeddings(
|
||||
texts: string[],
|
||||
userId: string,
|
||||
embeddingModelConfigId: string, // 本来は "embedding-3" を期待
|
||||
) {
|
||||
const modelConfig = await this.modelConfigService.findOne(
|
||||
embeddingModelConfigId, // ❌ "text-embedding-3-large" で検索しても見つからない!
|
||||
userId,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## ✅ 修正内容
|
||||
|
||||
### 修正箇所
|
||||
|
||||
**server/src/chat/chat.service.ts:**
|
||||
|
||||
```typescript
|
||||
// 182行目付近
|
||||
searchResults = await this.hybridSearch(
|
||||
[message],
|
||||
userId,
|
||||
embeddingModel.id, // ✅ テーブルID "embedding-3" を使用するように変更
|
||||
);
|
||||
```
|
||||
|
||||
### 修正後のフロー
|
||||
|
||||
```
|
||||
1. ユーザーが埋め込みモデルを選択: text-embedding-3-large
|
||||
↓
|
||||
2. システムが user_setting テーブルに保存:
|
||||
selectedEmbeddingId = "embedding-3" (ModelConfig テーブルの主キー)
|
||||
↓
|
||||
3. フロントエンドがチャットリクエストを送信:
|
||||
{ selectedEmbeddingId: "embedding-3" }
|
||||
↓
|
||||
4. バックエンド Controller が受信:
|
||||
selectedEmbeddingId = "embedding-3"
|
||||
↓
|
||||
5. ChatService がモデルを検索:
|
||||
embeddingModel = models.find(m => m.id === "embedding-3")
|
||||
// 結果: { id: "embedding-3", modelId: "text-embedding-3-large", ... }
|
||||
↓
|
||||
6. ChatService が hybridSearch を呼び出し:
|
||||
hybridSearch(..., embeddingModel.id) // "embedding-3" を渡す
|
||||
↓
|
||||
7. hybridSearch が EmbeddingService を呼び出し:
|
||||
getEmbeddings(..., "embedding-3")
|
||||
↓
|
||||
8. EmbeddingService が設定を検索:
|
||||
findOne("embedding-3", userId) // ✅ 設定が見つかる
|
||||
↓
|
||||
9. AI API を呼び出し:
|
||||
model: "text-embedding-3-large" // modelId を用いて API を実行
|
||||
```
|
||||
|
||||
## 📊 ID の対応関係
|
||||
|
||||
| シーン | 使用するフィールド | 例 | 用途 |
|
||||
|------|-----------|--------|------|
|
||||
| ユーザー設定 | `user_setting.selectedEmbeddingId` | `"embedding-3"` | ユーザーの選択を保存 |
|
||||
| 設定の検索 | `ModelConfig.id` | `"embedding-3"` | データベースクエリ |
|
||||
| API 呼び出し | `ModelConfig.modelId` | `"text-embedding-3-large"` | AI ベンダーのインターフェース |
|
||||
|
||||
## 🔑 重要な原則
|
||||
|
||||
### 1. データベース操作にはテーブル ID を使用する
|
||||
|
||||
```typescript
|
||||
// ✅ 正解
|
||||
const model = await modelConfigService.findOne(modelId, userId); // modelId = "embedding-3"
|
||||
|
||||
// ❌ 誤り
|
||||
const model = await modelConfigService.findOne(modelId, userId); // modelId = "text-embedding-3-large"
|
||||
```
|
||||
|
||||
### 2. API 呼び出しにはモデル識別子を使用する
|
||||
|
||||
```typescript
|
||||
// ✅ 正解
|
||||
fetch(apiUrl, {
|
||||
body: JSON.stringify({
|
||||
model: modelConfig.modelId, // "text-embedding-3-large"
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 内部的な受け渡しにはテーブル ID を使用する
|
||||
|
||||
```typescript
|
||||
// ✅ 正解
|
||||
embeddingService.getEmbeddings(texts, userId, modelConfig.id); // "embedding-3"
|
||||
|
||||
// ❌ 誤り
|
||||
embeddingService.getEmbeddings(texts, userId, modelConfig.modelId); // "text-embedding-3-large"
|
||||
```
|
||||
|
||||
## 🧪 検証
|
||||
|
||||
### テスト手順
|
||||
|
||||
1. **ユーザー設定の確認**
|
||||
|
||||
```sql
|
||||
SELECT selectedEmbeddingId FROM user_setting WHERE userId = 'xxx';
|
||||
-- 期待値: "embedding-3" (テーブルID)
|
||||
```
|
||||
|
||||
2. **モデル設定の確認**
|
||||
|
||||
```sql
|
||||
SELECT id, modelId, name FROM model_config WHERE userId = 'xxx';
|
||||
-- 期待値: embedding-3 | text-embedding-3-large | Text Embedding 3 Large
|
||||
```
|
||||
|
||||
3. **チャットメッセージの送信**
|
||||
- バックエンドログを確認
|
||||
- 期待される出力: "使用嵌入模型: Text Embedding 3 Large text-embedding-3-large ID: embedding-3"
|
||||
|
||||
4. **埋め込みベクトルの生成確認**
|
||||
- ログに "从 Text Embedding 3 Large 获取到 X 个嵌入向量" と表示されること
|
||||
|
||||
### 期待されるログ出力
|
||||
|
||||
```
|
||||
=== ChatService.streamChat ===
|
||||
User ID: user-123
|
||||
Selected Embedding ID: embedding-3
|
||||
ID に基づいてモデルを検索: embedding-3
|
||||
使用するモデル: Text Embedding 3 Large text-embedding-3-large ID: embedding-3
|
||||
埋め込みベクトルを生成中...
|
||||
Text Embedding 3 Large から 1 個の埋め込みベクトルを取得しました。次元数: 2560
|
||||
```
|
||||
|
||||
## 📁 修正されたファイル
|
||||
|
||||
- `server/src/chat/chat.service.ts` - 182行目。 `embeddingModel.modelId` ではなく `embeddingModel.id` を渡すように変更。
|
||||
|
||||
## 💡 学んだ教訓
|
||||
|
||||
1. **2種類の ID を区別すること**:テーブル主キー vs モデル識別子
|
||||
2. **パラメータ名を明確にすること**:`embeddingModelConfigId` vs `embeddingModelId`
|
||||
3. **呼び出し先の期待値を確認すること**:`EmbeddingService` がどのタイプの ID を求めているか
|
||||
4. **ログ出力の工夫**:デバッグを容易にするため、両方の ID を出力する
|
||||
|
||||
```typescript
|
||||
console.log('使用するモデル:', embeddingModel.name, embeddingModel.modelId, 'ID:', embeddingModel.id);
|
||||
// 出力: 使用するモデル: Text Embedding 3 Large text-embedding-3-large ID: embedding-3
|
||||
```
|
||||
Reference in New Issue
Block a user