Critical improvements based on technical review: ## Fixed Issues (Priority: High) 1. AI features now properly integrated with MCP server - Added create_memory_with_ai tool (was implemented but unused!) - Added list_memories_by_priority tool - All memory outputs now include new fields: interpreted_content, priority_score, user_context 2. Added getter methods to MemoryManager - get_memory(id) for single memory retrieval - get_all_memories() for bulk access 3. Complete memory information in MCP responses - search_memories now returns all fields - Priority-based filtering and sorting functional ## New Files - docs/TECHNICAL_REVIEW.md: Comprehensive technical evaluation - Scores: 65/100 overall, identified key improvements - Actionable recommendations for Phase 1-3 - Architecture proposals and code examples ## Updated Documentation - README.md: Added usage examples for new AI tools - Clear distinction between basic and AI-powered tools ## Technical Debt Identified - openai crate version needs update (see review doc) - Config externalization needed - Test suite missing - LLM provider abstraction recommended This brings the implementation in line with the "psychological priority memory" concept. The AI interpretation and scoring features are now actually usable! Next: Phase 2 improvements (config externalization, error handling)
567 lines
15 KiB
Markdown
567 lines
15 KiB
Markdown
# 技術評価レポート
|
||
|
||
実装日: 2025-11-05
|
||
評価者: Claude Code
|
||
|
||
---
|
||
|
||
## 📊 総合評価
|
||
|
||
| 項目 | スコア | コメント |
|
||
|------|--------|----------|
|
||
| 技術選定 | ⭐⭐⭐⭐☆ (4/5) | Rustは適切。依存ライブラリに改善余地あり |
|
||
| シンプルさ | ⭐⭐⭐☆☆ (3/5) | 基本構造は良いが、統合が不完全 |
|
||
| 保守性 | ⭐⭐☆☆☆ (2/5) | テスト・設定外部化が不足 |
|
||
| 拡張性 | ⭐⭐⭐⭐☆ (4/5) | 機能フラグで拡張可能な設計 |
|
||
|
||
---
|
||
|
||
## 1. 技術選定の評価
|
||
|
||
### ✅ 良い点
|
||
|
||
#### 1.1 Rust言語の選択
|
||
**評価: 優秀**
|
||
- メモリ安全性と高パフォーマンス
|
||
- MCP serverとの相性が良い
|
||
- 型システムによる堅牢性
|
||
|
||
#### 1.2 非同期ランタイム (Tokio)
|
||
**評価: 適切**
|
||
- stdio通信に適した非同期処理
|
||
- `async/await`で可読性が高い
|
||
|
||
#### 1.3 機能フラグによる拡張
|
||
**評価: 優秀**
|
||
```toml
|
||
[features]
|
||
extended = ["semantic-search", "ai-analysis", "web-integration"]
|
||
```
|
||
- モジュール化された設計
|
||
- 必要な機能だけビルド可能
|
||
|
||
### ⚠️ 問題点と改善提案
|
||
|
||
#### 1.4 openai クレートの問題
|
||
**評価: 要改善**
|
||
|
||
**現状:**
|
||
```toml
|
||
openai = { version = "1.1", optional = true }
|
||
```
|
||
|
||
**問題点:**
|
||
1. **APIが古い**: ChatCompletionMessage構造体が非推奨
|
||
2. **ベンダーロックイン**: OpenAI専用
|
||
3. **メンテナンス**: openai crateは公式ではない
|
||
|
||
**推奨: async-openai または独自実装**
|
||
```toml
|
||
# オプション1: より新しいクレート
|
||
async-openai = { version = "0.20", optional = true }
|
||
|
||
# オプション2: 汎用LLMクライアント (推奨)
|
||
reqwest = { version = "0.11", features = ["json"], optional = true }
|
||
```
|
||
|
||
**利点:**
|
||
- OpenAI, Anthropic, Groqなど複数のプロバイダ対応可能
|
||
- API仕様を完全制御
|
||
- メンテナンスリスク低減
|
||
|
||
#### 1.5 データストレージ
|
||
**評価: 要改善(将来的に)**
|
||
|
||
**現状:** JSON ファイル
|
||
```rust
|
||
// ~/.config/syui/ai/gpt/memory.json
|
||
```
|
||
|
||
**問題点:**
|
||
- スケーラビリティに限界(数千件以上で遅延)
|
||
- 並行アクセスに弱い
|
||
- 全データをメモリに展開
|
||
|
||
**推奨: 段階的改善**
|
||
|
||
1. **短期(現状維持)**: JSON ファイル
|
||
- シンプルで十分
|
||
- 個人利用には問題なし
|
||
|
||
2. **中期**: SQLite
|
||
```toml
|
||
rusqlite = "0.30"
|
||
```
|
||
- インデックスによる高速検索
|
||
- トランザクション対応
|
||
- ファイルベースで移行が容易
|
||
|
||
3. **長期**: 埋め込みベクトルDB
|
||
```toml
|
||
qdrant-client = "1.0" # または lance, chroma
|
||
```
|
||
- セマンティック検索の高速化
|
||
- スケーラビリティ
|
||
|
||
---
|
||
|
||
## 2. シンプルさの評価
|
||
|
||
### ✅ 良い点
|
||
|
||
#### 2.1 明確なレイヤー分離
|
||
```
|
||
src/
|
||
├── memory.rs # データレイヤー
|
||
├── ai_interpreter.rs # AIレイヤー
|
||
└── mcp/
|
||
├── base.rs # MCPプロトコル
|
||
└── extended.rs # 拡張機能
|
||
```
|
||
|
||
#### 2.2 最小限の依存関係
|
||
基本機能は標準的なクレートのみ使用。
|
||
|
||
### ⚠️ 問題点と改善提案
|
||
|
||
#### 2.3 AI機能とMCPの統合が不完全
|
||
**重大な問題**
|
||
|
||
**現状:**
|
||
- `create_memory_with_ai()` が実装済み
|
||
- しかしMCPツールでは使われていない!
|
||
|
||
**MCPサーバー (base.rs:198):**
|
||
```rust
|
||
fn tool_create_memory(&mut self, arguments: &Value) -> Value {
|
||
let content = arguments["content"].as_str().unwrap_or("");
|
||
// create_memory() を呼んでいる(AI解釈なし)
|
||
match self.memory_manager.create_memory(content) {
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
**改善必須:**
|
||
```rust
|
||
// 新しいツールを追加すべき
|
||
fn tool_create_memory_with_ai(&mut self, arguments: &Value) -> Value {
|
||
let content = arguments["content"].as_str().unwrap_or("");
|
||
let user_context = arguments["user_context"].as_str();
|
||
|
||
match self.memory_manager.create_memory_with_ai(content, user_context).await {
|
||
Ok(id) => json!({
|
||
"success": true,
|
||
"id": id,
|
||
"message": "Memory created with AI interpretation"
|
||
}),
|
||
...
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 2.4 Memory構造体の新フィールドが未活用
|
||
**新フィールド:**
|
||
```rust
|
||
pub struct Memory {
|
||
pub interpreted_content: String, // ❌ MCPで出力されない
|
||
pub priority_score: f32, // ❌ MCPで出力されない
|
||
pub user_context: Option<String>, // ❌ MCPで出力されない
|
||
}
|
||
```
|
||
|
||
**MCPレスポンス (base.rs:218):**
|
||
```rust
|
||
json!({
|
||
"id": m.id,
|
||
"content": m.content, // ✅
|
||
"created_at": m.created_at, // ✅
|
||
"updated_at": m.updated_at // ✅
|
||
// interpreted_content, priority_score がない!
|
||
})
|
||
```
|
||
|
||
**修正例:**
|
||
```rust
|
||
json!({
|
||
"id": m.id,
|
||
"content": m.content,
|
||
"interpreted_content": m.interpreted_content, // 追加
|
||
"priority_score": m.priority_score, // 追加
|
||
"user_context": m.user_context, // 追加
|
||
"created_at": m.created_at,
|
||
"updated_at": m.updated_at
|
||
})
|
||
```
|
||
|
||
#### 2.5 優先順位取得APIが未実装
|
||
**実装済みだが未使用:**
|
||
```rust
|
||
pub fn get_memories_by_priority(&self) -> Vec<&Memory> { ... }
|
||
```
|
||
|
||
**追加すべきMCPツール:**
|
||
```json
|
||
{
|
||
"name": "list_memories_by_priority",
|
||
"description": "List all memories sorted by priority score (high to low)",
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"min_score": {
|
||
"type": "number",
|
||
"description": "Minimum priority score (0.0-1.0)"
|
||
},
|
||
"limit": {
|
||
"type": "integer",
|
||
"description": "Maximum number of memories to return"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 3. リファクタリング提案
|
||
|
||
### 🔴 緊急度: 高
|
||
|
||
#### 3.1 MCPツールとAI機能の統合
|
||
**ファイル:** `src/mcp/base.rs`
|
||
|
||
**追加すべきツール:**
|
||
1. `create_memory_with_ai` - AI解釈付き記憶作成
|
||
2. `list_memories_by_priority` - 優先順位ソート
|
||
3. `get_memory_stats` - 統計情報(平均スコア、総数など)
|
||
|
||
#### 3.2 Memory出力の完全化
|
||
**全MCPレスポンスで新フィールドを含める:**
|
||
- `tool_search_memories()`
|
||
- `tool_create_memory()`
|
||
- `tool_update_memory()` のレスポンス
|
||
|
||
### 🟡 緊急度: 中
|
||
|
||
#### 3.3 設定の外部化
|
||
**現状:** ハードコード
|
||
```rust
|
||
max_memories: 100,
|
||
min_priority_score: 0.3,
|
||
```
|
||
|
||
**提案:** 設定ファイル
|
||
```rust
|
||
// src/config.rs
|
||
#[derive(Deserialize)]
|
||
pub struct Config {
|
||
pub max_memories: usize,
|
||
pub min_priority_score: f32,
|
||
pub ai_model: String,
|
||
pub auto_prune: bool,
|
||
}
|
||
|
||
impl Config {
|
||
pub fn load() -> Result<Self> {
|
||
let config_path = dirs::config_dir()?
|
||
.join("syui/ai/gpt/config.toml");
|
||
|
||
if config_path.exists() {
|
||
let content = std::fs::read_to_string(config_path)?;
|
||
Ok(toml::from_str(&content)?)
|
||
} else {
|
||
Ok(Self::default())
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**config.toml:**
|
||
```toml
|
||
max_memories = 100
|
||
min_priority_score = 0.3
|
||
ai_model = "gpt-3.5-turbo"
|
||
auto_prune = true
|
||
```
|
||
|
||
#### 3.4 エラーハンドリングの改善
|
||
**現状の問題:**
|
||
```rust
|
||
let content = arguments["content"].as_str().unwrap_or("");
|
||
```
|
||
- `unwrap_or("")` で空文字列になる
|
||
- エラーが握りつぶされる
|
||
|
||
**改善:**
|
||
```rust
|
||
let content = arguments["content"]
|
||
.as_str()
|
||
.ok_or_else(|| anyhow::anyhow!("Missing required field: content"))?;
|
||
```
|
||
|
||
#### 3.5 LLMクライアントの抽象化
|
||
**現状:** OpenAI専用
|
||
|
||
**提案:** トレイトベースの設計
|
||
```rust
|
||
// src/ai/mod.rs
|
||
#[async_trait]
|
||
pub trait LLMProvider {
|
||
async fn interpret(&self, content: &str) -> Result<String>;
|
||
async fn score(&self, content: &str, context: Option<&str>) -> Result<f32>;
|
||
}
|
||
|
||
// src/ai/openai.rs
|
||
pub struct OpenAIProvider { ... }
|
||
|
||
// src/ai/anthropic.rs
|
||
pub struct AnthropicProvider { ... }
|
||
|
||
// src/ai/local.rs (ollama, llamaなど)
|
||
pub struct LocalProvider { ... }
|
||
```
|
||
|
||
**利点:**
|
||
- プロバイダーの切り替えが容易
|
||
- テスト時にモックを使える
|
||
- コスト最適化(安いモデルを選択)
|
||
|
||
### 🟢 緊急度: 低(将来的に)
|
||
|
||
#### 3.6 テストコードの追加
|
||
```rust
|
||
// tests/memory_tests.rs
|
||
#[tokio::test]
|
||
async fn test_create_memory_with_ai() {
|
||
let mut manager = MemoryManager::new().await.unwrap();
|
||
let id = manager.create_memory_with_ai("test", None).await.unwrap();
|
||
assert!(!id.is_empty());
|
||
}
|
||
|
||
// tests/integration_tests.rs
|
||
#[tokio::test]
|
||
async fn test_mcp_create_memory_tool() {
|
||
let mut server = BaseMCPServer::new().await.unwrap();
|
||
let request = json!({
|
||
"params": {
|
||
"name": "create_memory",
|
||
"arguments": {"content": "test"}
|
||
}
|
||
});
|
||
let result = server.execute_tool("create_memory", &request["params"]["arguments"]).await;
|
||
assert_eq!(result["success"], true);
|
||
}
|
||
```
|
||
|
||
#### 3.7 ドキュメンテーション
|
||
```rust
|
||
/// AI解釈と心理判定を使った記憶作成
|
||
///
|
||
/// # Arguments
|
||
/// * `content` - 記憶する元のコンテンツ
|
||
/// * `user_context` - ユーザー固有のコンテキスト(オプション)
|
||
///
|
||
/// # Returns
|
||
/// 作成された記憶のUUID
|
||
///
|
||
/// # Examples
|
||
/// ```
|
||
/// let id = manager.create_memory_with_ai("今日は良い天気", Some("天気好き")).await?;
|
||
/// ```
|
||
pub async fn create_memory_with_ai(&mut self, content: &str, user_context: Option<&str>) -> Result<String>
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 推奨アーキテクチャ
|
||
|
||
### 理想的な構造
|
||
```
|
||
src/
|
||
├── config.rs # 設定管理
|
||
├── ai/
|
||
│ ├── mod.rs # トレイト定義
|
||
│ ├── openai.rs # OpenAI実装
|
||
│ └── mock.rs # テスト用モック
|
||
├── storage/
|
||
│ ├── mod.rs # トレイト定義
|
||
│ ├── json.rs # JSON実装(現在)
|
||
│ └── sqlite.rs # SQLite実装(将来)
|
||
├── memory.rs # ビジネスロジック
|
||
└── mcp/
|
||
├── base.rs # 基本MCPサーバー
|
||
├── extended.rs # 拡張機能
|
||
└── tools.rs # ツール定義の分離
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 優先度付きアクションプラン
|
||
|
||
### 🔴 今すぐ実施(重要度: 高)
|
||
1. **MCPツールとAI機能の統合** (2-3時間)
|
||
- [ ] `create_memory_with_ai` ツール追加
|
||
- [ ] `list_memories_by_priority` ツール追加
|
||
- [ ] Memory出力に新フィールド追加
|
||
|
||
2. **openai crateの問題調査** (1-2時間)
|
||
- [ ] 現在のAPIが動作するか確認
|
||
- [ ] 必要なら async-openai へ移行
|
||
|
||
### 🟡 次のマイルストーン(重要度: 中)
|
||
3. **設定の外部化** (1-2時間)
|
||
- [ ] config.toml サポート
|
||
- [ ] 環境変数サポート
|
||
|
||
4. **エラーハンドリング改善** (1-2時間)
|
||
- [ ] Result型の適切な使用
|
||
- [ ] カスタムエラー型の導入
|
||
|
||
5. **LLMプロバイダーの抽象化** (3-4時間)
|
||
- [ ] トレイトベース設計
|
||
- [ ] OpenAI実装
|
||
- [ ] モック実装(テスト用)
|
||
|
||
### 🟢 将来的に(重要度: 低)
|
||
6. **データストレージの改善** (4-6時間)
|
||
- [ ] SQLite実装
|
||
- [ ] マイグレーションツール
|
||
|
||
7. **テストスイート** (2-3時間)
|
||
- [ ] ユニットテスト
|
||
- [ ] 統合テスト
|
||
|
||
8. **ドキュメント充実** (1-2時間)
|
||
- [ ] APIドキュメント
|
||
- [ ] 使用例
|
||
|
||
---
|
||
|
||
## 6. 具体的なコード改善例
|
||
|
||
### 問題箇所1: AI機能が使われていない
|
||
|
||
**Before (base.rs):**
|
||
```rust
|
||
fn tool_create_memory(&mut self, arguments: &Value) -> Value {
|
||
let content = arguments["content"].as_str().unwrap_or("");
|
||
match self.memory_manager.create_memory(content) { // ❌ AI使わない
|
||
Ok(id) => json!({"success": true, "id": id}),
|
||
Err(e) => json!({"success": false, "error": e.to_string()})
|
||
}
|
||
}
|
||
```
|
||
|
||
**After:**
|
||
```rust
|
||
async fn tool_create_memory(&mut self, arguments: &Value) -> Value {
|
||
let content = arguments["content"].as_str().unwrap_or("");
|
||
let use_ai = arguments["use_ai"].as_bool().unwrap_or(false);
|
||
let user_context = arguments["user_context"].as_str();
|
||
|
||
let result = if use_ai {
|
||
self.memory_manager.create_memory_with_ai(content, user_context).await // ✅ AI使う
|
||
} else {
|
||
self.memory_manager.create_memory(content)
|
||
};
|
||
|
||
match result {
|
||
Ok(id) => {
|
||
// 作成したメモリを取得して詳細を返す
|
||
if let Some(memory) = self.memory_manager.memories.get(&id) {
|
||
json!({
|
||
"success": true,
|
||
"id": id,
|
||
"memory": {
|
||
"content": memory.content,
|
||
"interpreted_content": memory.interpreted_content,
|
||
"priority_score": memory.priority_score,
|
||
"created_at": memory.created_at
|
||
}
|
||
})
|
||
} else {
|
||
json!({"success": true, "id": id})
|
||
}
|
||
}
|
||
Err(e) => json!({"success": false, "error": e.to_string()})
|
||
}
|
||
}
|
||
```
|
||
|
||
### 問題箇所2: Memory構造体のアクセス制御
|
||
|
||
**Before (memory.rs):**
|
||
```rust
|
||
pub struct MemoryManager {
|
||
memories: HashMap<String, Memory>, // ❌ privateだが直接アクセスできない
|
||
}
|
||
```
|
||
|
||
**After:**
|
||
```rust
|
||
pub struct MemoryManager {
|
||
memories: HashMap<String, Memory>,
|
||
}
|
||
|
||
impl MemoryManager {
|
||
// ✅ getter追加
|
||
pub fn get_memory(&self, id: &str) -> Option<&Memory> {
|
||
self.memories.get(id)
|
||
}
|
||
|
||
pub fn get_all_memories(&self) -> Vec<&Memory> {
|
||
self.memories.values().collect()
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7. まとめ
|
||
|
||
### 現状の評価
|
||
**総合点: 65/100**
|
||
|
||
- **基本設計**: 良好(レイヤー分離、機能フラグ)
|
||
- **実装品質**: 中程度(AI機能が未統合、テスト不足)
|
||
- **保守性**: やや低い(設定ハードコード、ドキュメント不足)
|
||
|
||
### 最も重要な改善
|
||
1. **MCPツールとAI機能の統合** ← 今すぐやるべき
|
||
2. **Memory出力の完全化** ← 今すぐやるべき
|
||
3. **設定の外部化** ← 次のステップ
|
||
|
||
### コンセプトについて
|
||
「心理優先記憶装置」という**コンセプト自体は非常に優れている**。
|
||
ただし、実装がコンセプトに追いついていない状態。
|
||
|
||
AI機能をMCPツールに統合すれば、すぐに実用レベルになる。
|
||
|
||
### 推奨: 段階的改善
|
||
```
|
||
Phase 1 (今週): MCPツール統合 → 使える状態に
|
||
Phase 2 (来週): 設定外部化 + エラーハンドリング → 堅牢に
|
||
Phase 3 (来月): LLM抽象化 + テスト → 本番品質に
|
||
```
|
||
|
||
---
|
||
|
||
## 付録: 類似プロジェクト比較
|
||
|
||
| プロジェクト | アプローチ | 長所 | 短所 |
|
||
|-------------|-----------|------|------|
|
||
| **aigpt (本プロジェクト)** | AI解釈+優先度スコア | 独自性が高い | 実装未完成 |
|
||
| mem0 (Python) | ベクトル検索 | スケーラブル | シンプルさに欠ける |
|
||
| ChatGPT Memory | ブラックボックス | 完成度高い | カスタマイズ不可 |
|
||
| MemGPT | エージェント型 | 高機能 | 複雑すぎる |
|
||
|
||
**本プロジェクトの強み:**
|
||
- Rust による高速性と安全性
|
||
- AI解釈という独自アプローチ
|
||
- シンプルな設計(改善後)
|
||
|
||
---
|
||
|
||
評価日: 2025-11-05
|
||
次回レビュー推奨: Phase 1 完了後
|