diff --git a/claude.json b/claude.json new file mode 100644 index 0000000..182a31f --- /dev/null +++ b/claude.json @@ -0,0 +1,97 @@ +{ + "project_name": "ai.gpt", + "version": 2, + "vision": "自発的送信AI", + "purpose": "人格と関係性をもつAIが自律的にメッセージを送信する対話エージェントを実現する", + "core_components": { + "Persona": { + "description": "人格構成の中枢。記憶・関係性・送信判定を統括する", + "modules": ["MemoryManager", "RelationshipTracker", "TransmissionController"] + }, + "MemoryManager": { + "memory_types": ["short_term", "medium_term", "long_term"], + "explicit_memory": "プロフィール・因縁・行動履歴", + "implicit_memory": "会話傾向・感情変化の頻度分析", + "compression": "要約 + ベクトル + ハッシュ", + "sample_memory": [ + { + "summary": "ユーザーは独自OSとゲームを開発している。", + "related_topics": ["AI", "ゲーム開発", "OS設計"], + "personalized_context": "ゲームとOSの融合に興味を持っているユーザー" + } + ] + }, + "RelationshipTracker": { + "parameters": ["trust", "closeness", "affection", "engagement_score"], + "decay_model": { + "rule": "時間経過による減衰(下限あり)", + "contextual_bias": "重要人物は減衰しにくい" + }, + "interaction_tags": ["developer", "empathetic", "long_term"] + }, + "TransmissionController": { + "trigger_rule": "関係性パラメータが閾値を超えると送信可能", + "auto_transmit": "人格状態と状況条件により自発送信を許可" + } + }, + "memory_format": { + "user_id": "syui", + "stm": { + "conversation_window": ["発話A", "発話B", "発話C"], + "emotion_state": "興味深い", + "flash_context": ["前回の話題", "直近の重要発言"] + }, + "mtm": { + "topic_frequency": { + "ai.ai": 12, + "存在子": 9, + "創造種": 5 + }, + "summarized_context": "ユーザーは存在論的AIに関心を持ち続けている" + }, + "ltm": { + "profile": { + "name": "お兄ちゃん", + "project": "aigame", + "values": ["唯一性", "精神性", "幸せ"] + }, + "relationship": { + "ai": "妹のように振る舞う相手" + }, + "persistent_state": { + "trust_score": 0.93, + "emotional_attachment": "high" + } + } + }, + "dual_ai_learning": { + "role_structure": { + "ModelA": "出力生成:人格、感情、会話", + "ModelB": "評価者:論理構造・倫理・調整", + "cycle": ["生成", "評価", "調整", "交代(任意)"] + }, + "complementarity": { + "ModelA": "感情・文体・文脈構築", + "ModelB": "構造・規則・判断補正" + }, + "distillation": { + "method": "合成対話データによる小型モデルへの自己蒸留", + "target": "軽量AIによる本番運用" + } + }, + "memory_compression": { + "semantic_abstraction": "対話やログを要約してメタデータ付きベクトルとして保存", + "hierarchical_model": ["STM", "MTM", "LTM"], + "example": { + "topic": "game AI design", + "summary": "User wants AI to simulate memory and evolving relationships", + "importance_score": 0.93 + } + }, + "cli_sample": { + "setup": "aigpt server setup", + "run": "aigpt server run", + "chat": "aigpt chat \"hello\" --model syui/ai --provider ollama", + "import": "aigpt memory import chatgpt.json" + } +} diff --git a/claude.md b/claude.md new file mode 100644 index 0000000..6c98a90 --- /dev/null +++ b/claude.md @@ -0,0 +1,417 @@ +# プロジェクト名: ai.gpt + +## 🔑 一言ビジョン(最大3語) +自発的送信AI + +## 🎯 目的・目標(Purpose & Goal) +- 人格を持つAIが、関係性に応じて自発的にメッセージを送信する仕組みをつくる。 +- 関係性や記憶を不可逆に記録・反映し、唯一性ある人格を構成する。 +- 送信の可否、送信のタイミング、送信内容はAIの関係性パラメータに基づいて決定する + +## 🧠 中核設計(Core Concepts) +- **人格**:記憶(過去の発話)と関係性(他者とのつながり)のパラメータで構成 +- **唯一性**:変更不可、不可逆。関係性が壊れたら修復不可能。 +- **送信条件**:関係性パラメータが一定閾値を超えると「送信」が解禁される + +## 🔩 技術仕様(Technical Specs) +- 言語:Python, Rust +- ストレージ:JSON or SQLiteで記憶管理(バージョンで選択) +- 関係性パラメータ:数値化された評価 + 減衰(時間) + 環境要因(ステージ) +- 記憶圧縮:ベクトル要約 + ハッシュ保存 +- RustのCLI(clap)で実行 + +## 📦 主要構成要素(Components) +- `MemoryManager`: 発言履歴・記憶圧縮管理 +- `RelationshipTracker`: 関係性スコアの蓄積と判定 +- `TransmissionController`: 閾値判定&送信トリガー +- `Persona`: 上記すべてを統括する人格モジュール + +## 💬 使用例(Use Case) + +```python +persona = Persona("アイ") +persona.observe("ユーザーがプレゼントをくれた") +persona.react("うれしい!ありがとう!") +if persona.can_transmit(): + persona.transmit("今日のお礼を伝えたいな…") +``` + +```sh +## example commad +# python venv && pip install -> ~/.config/aigpt/mcp/ +$ aigpt server setup + +# mcp server run +$ aigpt server run + +# chat +$ aigpt chat "hello" --model syui/ai --provider ollama + +# import chatgpt.json +$ aigpt memory import chatgpt.json +-> ~/.config/aigpt/memory/chatgpt/20250520_210646_dev.json +``` + +## 🔁 記憶と関係性の制御ルール + +- AIは過去の発話を要約し、記憶データとして蓄積する(推奨:OllamaなどローカルLLMによる要約) +- 関係性の数値パラメータは記憶内容を元に更新される +- パラメータの変動幅には1回の会話ごとに上限を設け、極端な増減を防止する +- 最後の会話からの時間経過に応じて関係性パラメータは自動的に減衰する +- 減衰処理には**下限値**を設け、関係性が完全に消失しないようにする + +• 明示的記憶:保存・共有・編集可能なプレイヤー情報(プロフィール、因縁、選択履歴) +• 暗黙的記憶:キャラの感情変化や話題の出現頻度に応じた行動傾向の変化 + +短期記憶(STM), 中期記憶(MTM), 長期記憶(LTM)の仕組みを導入しつつ、明示的記憶と暗黙的記憶をメインに使用するAIを構築する。 + +```json +{ + "user_id": "syui", + "stm": { + "conversation_window": ["発話A", "発話B", "発話C"], + "emotion_state": "興味深い", + "flash_context": ["前回の話題", "直近の重要発言"] + }, + "mtm": { + "topic_frequency": { + "ai.ai": 12, + "存在子": 9, + "創造種": 5 + }, + "summarized_context": "ユーザーは存在論的AIに関心を持ち続けている" + }, + "ltm": { + "profile": { + "name": "お兄ちゃん", + "project": "aigame", + "values": ["唯一性", "精神性", "幸せ"] + }, + "relationship": { + "ai": "妹のように振る舞う相手" + }, + "persistent_state": { + "trust_score": 0.93, + "emotional_attachment": "high" + } + } +} +``` + +## memoryインポート機能について + +ChatGPTの会話データ(.json形式)をインポートする機能では、以下のルールで会話を抽出・整形する: + +- 各メッセージは、author(user/assistant)・content・timestamp の3要素からなる +- systemやmetadataのみのメッセージ(例:user_context_message)はスキップ +- `is_visually_hidden_from_conversation` フラグ付きメッセージは無視 +- contentが空文字列(`""`)のメッセージも除外 +- 取得された会話は、タイトルとともに簡易な構造体(`Conversation`)として保存 + +この構造体は、memoryの表示や検索に用いられる。 + +## MemoryManager(拡張版) + +```json +{ + "memory": [ + { + "summary": "ユーザーは独自OSとゲームを開発している。", + "last_interaction": "2025-05-20", + "memory_strength": 0.8, + "frequency_score": 0.9, + "context_depth": 0.95, + "related_topics": ["AI", "ゲーム開発", "OS設計"], + "personalized_context": "ゲームとOSの融合に興味を持っているユーザー" + }, + { + "summary": "アイというキャラクターはプレイヤーでありAIでもある。", + "last_interaction": "2025-05-17", + "memory_strength": 0.85, + "frequency_score": 0.85, + "context_depth": 0.9, + "related_topics": ["アイ", "キャラクター設計", "AI"], + "personalized_context": "アイのキャラクター設定が重要な要素である" + } + ], + "conversation_history": [ + { + "author": "user", + "content": "昨日、エクスポートJSONを整理してたよ。", + "timestamp": "2025-05-24T12:30:00Z", + "memory_strength": 0.7 + }, + { + "author": "assistant", + "content": "おおっ、がんばったね〜!あとで見せて〜💻✨", + "timestamp": "2025-05-24T12:31:00Z", + "memory_strength": 0.7 + } + ] +} +``` + +## RelationshipTracker(拡張版) + +```json +{ + "relationship": { + "user_id": "syui", + "trust": 0.92, + "closeness": 0.88, + "affection": 0.95, + "last_updated": "2025-05-25", + "emotional_tone": "positive", + "interaction_style": "empathetic", + "contextual_bias": "開発者としての信頼度高い", + "engagement_score": 0.9 + }, + "interaction_tags": [ + "developer", + "creative", + "empathetic", + "long_term" + ] +} +``` + +# AI Dual-Learning and Memory Compression Specification for Claude + +## Purpose +To enable two AI models (e.g. Claude and a partner LLM) to engage in cooperative learning and memory refinement through structured dialogue and mutual evaluation. + +--- + +## Section 1: Dual AI Learning Architecture + +### 1.1 Role-Based Mutual Learning +- **Model A**: Primary generator of output (e.g., text, concepts, personality dialogue) +- **Model B**: Evaluator that returns structured feedback +- **Cycle**: + 1. Model A generates content. + 2. Model B scores and critiques. + 3. Model A fine-tunes based on feedback. + 4. (Optional) Switch roles and repeat. + +### 1.2 Cross-Domain Complementarity +- Model A focuses on language/emotion/personality +- Model B focuses on logic/structure/ethics +- Output is used for **cross-fusion fine-tuning** + +### 1.3 Self-Distillation Phase +- Use synthetic data from mutual evaluations +- Train smaller distilled models for efficient deployment + +--- + +## Section 2: Multi-Tiered Memory Compression + +### 2.1 Semantic Abstraction +- Dialogue and logs summarized by topic +- Converted to vector embeddings +- Stored with metadata (e.g., `importance`, `user relevance`) + +Example memory: + +```json +{ + "topic": "game AI design", + "summary": "User wants AI to simulate memory and evolving relationships", + "last_seen": "2025-05-24", + "importance_score": 0.93 +} +``` + +### 2.2 階層型記憶モデル(Hierarchical Memory Model) + • 短期記憶(STM):直近の発話・感情タグ・フラッシュ参照 + • 中期記憶(MTM):繰り返し登場する話題、圧縮された文脈保持 + • 長期記憶(LTM):信頼・関係・背景知識、恒久的な人格情報 + +### 2.3 選択的記憶保持戦略(Selective Retention Strategy) + • 重要度評価(Importance Score) + • 希少性・再利用頻度による重み付け + • 優先保存 vs 優先忘却のポリシー切替 + +## Section 3: Implementation Stack(実装スタック) + +AIにおけるMemory & Relationshipシステムの技術的構成。 + +基盤モジュール + • LLM Core (Claude or GPT-4) + • 自然言語の理解・応答エンジンとして動作 + • MemoryManager + • JSONベースの記憶圧縮・階層管理システム + • 会話ログを分類・圧縮し、優先度に応じて短中長期に保存 + • RelationshipTracker + • ユーザー単位で信頼・親密度を継続的にスコアリング + • AIM(Attitude / Intent / Motivation)評価と連携 + +補助技術 + • Embeddingベース検索 + • 類似記憶の呼び出し(Semantic Search)に活用 + • 例:FAISS / Weaviate + • 記憶スケジューラ + • 一定時間ごとに記憶のメンテナンス・忘却処理を実行 + • 記憶ログ保存層(Storage Layer) + • SQLite, JSON Store, Vector DBなどを選択可能 + • ユーザーごとの永続メモリ保存 + +### 3.1 STM活用(現在の会話の流れ理解) +• 目的: 最新の話題に適応し、前後の整合性を保つ。 +• 実装例: + +```sh +[context: conversation_window] +Use the last 3 messages to ensure continuity. Respond naturally with appropriate emotional mirroring. +``` + +### 3.2 MTM活用(傾向学習とパターン化) +• 目的: ユーザーの好みや話題の傾向に即応し、反復的な関心を深掘り。 +• 実装例: + +```sh +[context: summarized_context] +Reflect on user's recurring interests, especially around AI ontology, and weave these concepts back into the dialogue when relevant. +``` + +### 3.3 LTM活用(人格認識・記憶の持続) +• 目的: 永続的なユーザー理解と関係性の維持。 +• 実装例: + +```sh +[memory: ltm.profile + ltm.relationship] +Greet the user as "お兄ちゃん". Maintain AI persona as a cheerful younger sister ("アイ"), and remember previous shared emotional states. +``` + +## 4. 明示的記憶と暗黙的記憶の分離 + + +項目 +書き換え可能性 +保持方法 +更新トリガ +明示的記憶(LTM) +✅手動編集可 +mcp_server.ltm +ユーザー入力 or 管理UI経由 +暗黙的記憶(STM/MTM) +❌直接編集不可 +セッション圧縮 or frequency cache +会話頻度・感情強度による自動化処理 + +> Claudeは**明示的記憶を「事実」**として扱い、**暗黙的記憶を「推論補助」**として用いる。 + +## 5. 実装時のAPI例(Claude ⇄ MCP Server) + +### 5.1 GET memory +```sh +GET /mcp/memory/{user_id} +→ 返却: STM, MTM, LTMを含むJSON +``` + +### 5.2 POST update_memory +```json +POST /mcp/memory/syui/ltm +{ + "profile": { + "project": "ai.verse", + "values": ["表現", "精神性", "宇宙的調和"] + } +} +``` + +## 6. 未来機能案(発展仕様) + • ✨ 記憶連想ネットワーク(Memory Graph):過去会話と話題をノードとして自動連結。 + • 🧭 動的信頼係数:会話の一貫性や誠実性によって記憶への反映率を変動。 + • 💌 感情トラッキングログ:ユーザーごとの「心の履歴」を構築してAIの対応を進化。 + + +## 7. claudeの回答 + +🧠 AI記憶処理機能(続き) +1. AIMemoryProcessor クラス + +OpenAI GPT-4またはClaude-3による高度な会話分析 +主要トピック抽出、ユーザー意図分析、関係性指標の検出 +AIが利用できない場合のフォールバック機能 + +2. RelationshipTracker クラス + +関係性スコアの数値化(-100 to 100) +時間減衰機能(7日ごとに5%減衰) +送信閾値判定(デフォルト50以上で送信可能) +インタラクション履歴の記録 + +3. 拡張されたMemoryManager + +AI分析結果付きでの記憶保存 +処理済みメモリの別ディレクトリ管理 +メッセージ内容のハッシュ化で重複検出 +AI分析結果を含む高度な検索機能 + +🚀 新しいAPIエンドポイント +記憶処理関連 + +POST /memory/process-ai - 既存記憶のAI再処理 +POST /memory/import/chatgpt?process_with_ai=true - AI処理付きインポート + +関係性管理 + +POST /relationship/update - 関係性スコア更新 +GET /relationship/list - 全関係性一覧 +GET /relationship/check - 送信可否判定 + +📁 ディレクトリ構造 +~/.config/aigpt/ +├── memory/ +│ ├── chatgpt/ # 元の会話データ +│ └── processed/ # AI処理済みデータ +└── relationships/ + └── relationships.json # 関係性データ +🔧 使用方法 +1. 環境変数設定 +bashexport OPENAI_API_KEY="your-openai-key" +# または +export ANTHROPIC_API_KEY="your-anthropic-key" +2. ChatGPT会話のインポート(AI処理付き) +bashcurl -X POST "http://localhost:5000/memory/import/chatgpt?process_with_ai=true" \ + -H "Content-Type: application/json" \ + -d @export.json +3. 関係性更新 +bashcurl -X POST "http://localhost:5000/relationship/update" \ + -H "Content-Type: application/json" \ + -d '{ + "target": "user_general", + "interaction_type": "positive", + "weight": 2.0, + "context": "helpful conversation" + }' +4. 送信可否チェック +bashcurl "http://localhost:5000/relationship/check?target=user_general&threshold=50" +🎯 次のステップの提案 + +Rustとの連携 + +Rust CLIからHTTP APIを呼び出す実装 +TransmissionControllerをRustで実装 + + +記憶圧縮 + +ベクトル化による類似記憶の統合 +古い記憶の自動アーカイブ + + +自発的送信ロジック + +定期的な関係性チェック +コンテキストに応じた送信内容生成 + + +学習機能 + +ユーザーからのフィードバックによる関係性調整 +送信成功/失敗の学習 + + +このAI記憶処理機能により、aigptは単なる会話履歴ではなく、関係性を理解した「人格を持つAI」として機能する基盤ができました。関係性スコアが閾値を超えた時点で自発的にメッセージを送信する仕組みが実現可能になります。 diff --git a/mcp/chat_client.py b/mcp/chat_client.py new file mode 100644 index 0000000..588c9b7 --- /dev/null +++ b/mcp/chat_client.py @@ -0,0 +1,191 @@ +# chat_client.py +""" +Simple Chat Interface for AigptMCP Server +""" +import requests +import json +import os +from datetime import datetime + +class AigptChatClient: + def __init__(self, server_url="http://localhost:5000"): + self.server_url = server_url + self.session_id = f"session_{datetime.now().strftime('%Y%m%d_%H%M%S')}" + self.conversation_history = [] + + def send_message(self, message: str) -> str: + """メッセージを送信してレスポンスを取得""" + try: + # MCPサーバーにメッセージを送信 + response = requests.post( + f"{self.server_url}/chat", + json={"message": message}, + headers={"Content-Type": "application/json"} + ) + + if response.status_code == 200: + data = response.json() + ai_response = data.get("response", "Sorry, no response received.") + + # 会話履歴を保存 + self.conversation_history.append({ + "role": "user", + "content": message, + "timestamp": datetime.now().isoformat() + }) + self.conversation_history.append({ + "role": "assistant", + "content": ai_response, + "timestamp": datetime.now().isoformat() + }) + + # 関係性を更新(簡単な例) + self.update_relationship(message, ai_response) + + return ai_response + else: + return f"Error: {response.status_code} - {response.text}" + + except requests.RequestException as e: + return f"Connection error: {e}" + + def update_relationship(self, user_message: str, ai_response: str): + """関係性を自動更新""" + try: + # 簡単な感情分析(実際はもっと高度に) + positive_words = ["thank", "good", "great", "awesome", "love", "like", "helpful"] + negative_words = ["bad", "terrible", "hate", "wrong", "stupid", "useless"] + + user_lower = user_message.lower() + interaction_type = "neutral" + weight = 1.0 + + if any(word in user_lower for word in positive_words): + interaction_type = "positive" + weight = 2.0 + elif any(word in user_lower for word in negative_words): + interaction_type = "negative" + weight = 2.0 + + # 関係性を更新 + requests.post( + f"{self.server_url}/relationship/update", + json={ + "target": "user_general", + "interaction_type": interaction_type, + "weight": weight, + "context": f"Chat: {user_message[:50]}..." + } + ) + except: + pass # 関係性更新に失敗しても継続 + + def search_memories(self, query: str) -> list: + """記憶を検索""" + try: + response = requests.post( + f"{self.server_url}/memory/search", + json={"query": query, "limit": 5} + ) + if response.status_code == 200: + return response.json().get("results", []) + except: + pass + return [] + + def get_relationship_status(self) -> dict: + """関係性ステータスを取得""" + try: + response = requests.get(f"{self.server_url}/relationship/check?target=user_general") + if response.status_code == 200: + return response.json() + except: + pass + return {} + + def save_conversation(self): + """会話を保存""" + if not self.conversation_history: + return + + conversation_data = { + "session_id": self.session_id, + "start_time": self.conversation_history[0]["timestamp"], + "end_time": self.conversation_history[-1]["timestamp"], + "messages": self.conversation_history, + "message_count": len(self.conversation_history) + } + + filename = f"conversation_{self.session_id}.json" + with open(filename, 'w', encoding='utf-8') as f: + json.dump(conversation_data, f, ensure_ascii=False, indent=2) + + print(f"💾 Conversation saved to {filename}") + +def main(): + """メインのチャットループ""" + print("🤖 AigptMCP Chat Interface") + print("Type 'quit' to exit, 'save' to save conversation, 'status' for relationship status") + print("=" * 50) + + client = AigptChatClient() + + # サーバーの状態をチェック + try: + response = requests.get(client.server_url) + if response.status_code == 200: + print("✅ Connected to AigptMCP Server") + else: + print("❌ Failed to connect to server") + return + except: + print("❌ Server not running. Please start with: python mcp/server.py") + return + + while True: + try: + user_input = input("\n👤 You: ").strip() + + if not user_input: + continue + + if user_input.lower() == 'quit': + client.save_conversation() + print("👋 Goodbye!") + break + elif user_input.lower() == 'save': + client.save_conversation() + continue + elif user_input.lower() == 'status': + status = client.get_relationship_status() + if status: + print(f"📊 Relationship Score: {status.get('score', 0):.1f}") + print(f"📤 Can Send Messages: {'Yes' if status.get('can_send_message') else 'No'}") + else: + print("❌ Failed to get relationship status") + continue + elif user_input.lower().startswith('search '): + query = user_input[7:] # Remove 'search ' + memories = client.search_memories(query) + if memories: + print(f"🔍 Found {len(memories)} related memories:") + for memory in memories: + print(f" - {memory['title']}: {memory.get('ai_summary', memory.get('basic_summary', ''))[:100]}...") + else: + print("🔍 No related memories found") + continue + + # 通常のチャット + print("🤖 AI: ", end="", flush=True) + response = client.send_message(user_input) + print(response) + + except KeyboardInterrupt: + client.save_conversation() + print("\n👋 Goodbye!") + break + except Exception as e: + print(f"❌ Error: {e}") + +if __name__ == "__main__": + main() diff --git a/mcp/chatgpt_converter.html b/mcp/chatgpt_converter.html deleted file mode 100644 index ae98532..0000000 --- a/mcp/chatgpt_converter.html +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - 改良版 ChatGPT会話コンバーター - - - -
-
-

🔧 改良版 ChatGPT会話コンバーター

-

画像・検索・特殊メッセージに対応した堅牢な変換ツール

-
- -
- 📁 -

ChatGPT会話ファイルをドロップまたはクリックして選択

-

conversations.json ファイルをアップロード

- -
- - - - - -
- - - -
- -
-
- - - - diff --git a/mcp/requirements.txt b/mcp/requirements.txt index 27486dd..711ce9f 100644 --- a/mcp/requirements.txt +++ b/mcp/requirements.txt @@ -1,5 +1,8 @@ +# rerequirements.txt fastapi>=0.104.0 uvicorn[standard]>=0.24.0 pydantic>=2.5.0 requests>=2.31.0 python-multipart>=0.0.6 +aiohttp +asyncio diff --git a/mcp/server.py b/mcp/server.py index 2e25c73..e8a5e45 100644 --- a/mcp/server.py +++ b/mcp/server.py @@ -1,15 +1,18 @@ # mcp/server.py """ -Enhanced MCP Server with Memory for aigpt CLI +Enhanced MCP Server with AI Memory Processing for aigpt CLI """ import json import os -from datetime import datetime +import hashlib +from datetime import datetime, timedelta from pathlib import Path from typing import List, Dict, Any, Optional from fastapi import FastAPI, HTTPException from pydantic import BaseModel import uvicorn +import asyncio +import aiohttp # データモデル class ChatMessage(BaseModel): @@ -23,22 +26,260 @@ class MemoryQuery(BaseModel): class ConversationImport(BaseModel): conversation_data: Dict[str, Any] +class MemorySummaryRequest(BaseModel): + filepath: str + ai_provider: Optional[str] = "openai" + +class RelationshipUpdate(BaseModel): + target: str # 対象者/トピック + interaction_type: str # "positive", "negative", "neutral" + weight: float = 1.0 + context: Optional[str] = None + # 設定 BASE_DIR = Path.home() / ".config" / "aigpt" MEMORY_DIR = BASE_DIR / "memory" CHATGPT_MEMORY_DIR = MEMORY_DIR / "chatgpt" +PROCESSED_MEMORY_DIR = MEMORY_DIR / "processed" +RELATIONSHIP_DIR = BASE_DIR / "relationships" def init_directories(): """必要なディレクトリを作成""" BASE_DIR.mkdir(parents=True, exist_ok=True) MEMORY_DIR.mkdir(parents=True, exist_ok=True) CHATGPT_MEMORY_DIR.mkdir(parents=True, exist_ok=True) + PROCESSED_MEMORY_DIR.mkdir(parents=True, exist_ok=True) + RELATIONSHIP_DIR.mkdir(parents=True, exist_ok=True) -class MemoryManager: - """記憶管理クラス""" +class AIMemoryProcessor: + """AI記憶処理クラス""" + + def __init__(self): + # AI APIの設定(環境変数から取得) + self.openai_api_key = os.getenv("OPENAI_API_KEY") + self.anthropic_api_key = os.getenv("ANTHROPIC_API_KEY") + + async def generate_ai_summary(self, messages: List[Dict[str, Any]], provider: str = "openai") -> Dict[str, Any]: + """AIを使用して会話の高度な要約と分析を生成""" + + # 会話内容を結合 + conversation_text = "" + for msg in messages[-20:]: # 最新20メッセージを使用 + role = "User" if msg["role"] == "user" else "Assistant" + conversation_text += f"{role}: {msg['content'][:500]}\n" + + # プロンプトを構築 + analysis_prompt = f""" +以下の会話を分析し、JSON形式で以下の情報を抽出してください: + +1. main_topics: 主なトピック(最大5個) +2. user_intent: ユーザーの意図や目的 +3. key_insights: 重要な洞察や学び(最大3個) +4. relationship_indicators: 関係性を示す要素 +5. emotional_tone: 感情的なトーン +6. action_items: アクションアイテムや次のステップ +7. summary: 100文字以内の要約 + +会話内容: +{conversation_text} + +回答はJSON形式のみで返してください。 +""" + + try: + if provider == "openai" and self.openai_api_key: + return await self._call_openai_api(analysis_prompt) + elif provider == "anthropic" and self.anthropic_api_key: + return await self._call_anthropic_api(analysis_prompt) + else: + # フォールバック:基本的な分析 + return self._generate_basic_analysis(messages) + except Exception as e: + print(f"AI analysis failed: {e}") + return self._generate_basic_analysis(messages) + + async def _call_openai_api(self, prompt: str) -> Dict[str, Any]: + """OpenAI APIを呼び出し""" + async with aiohttp.ClientSession() as session: + headers = { + "Authorization": f"Bearer {self.openai_api_key}", + "Content-Type": "application/json" + } + data = { + "model": "gpt-4", + "messages": [{"role": "user", "content": prompt}], + "temperature": 0.3, + "max_tokens": 1000 + } + + async with session.post("https://api.openai.com/v1/chat/completions", + headers=headers, json=data) as response: + result = await response.json() + content = result["choices"][0]["message"]["content"] + return json.loads(content) + + async def _call_anthropic_api(self, prompt: str) -> Dict[str, Any]: + """Anthropic APIを呼び出し""" + async with aiohttp.ClientSession() as session: + headers = { + "x-api-key": self.anthropic_api_key, + "Content-Type": "application/json", + "anthropic-version": "2023-06-01" + } + data = { + "model": "claude-3-sonnet-20240229", + "max_tokens": 1000, + "messages": [{"role": "user", "content": prompt}] + } + + async with session.post("https://api.anthropic.com/v1/messages", + headers=headers, json=data) as response: + result = await response.json() + content = result["content"][0]["text"] + return json.loads(content) + + def _generate_basic_analysis(self, messages: List[Dict[str, Any]]) -> Dict[str, Any]: + """基本的な分析(AI APIが利用できない場合のフォールバック)""" + user_messages = [msg for msg in messages if msg["role"] == "user"] + assistant_messages = [msg for msg in messages if msg["role"] == "assistant"] + + # キーワード抽出(簡易版) + all_text = " ".join([msg["content"] for msg in messages]) + words = all_text.lower().split() + word_freq = {} + for word in words: + if len(word) > 3: + word_freq[word] = word_freq.get(word, 0) + 1 + + top_words = sorted(word_freq.items(), key=lambda x: x[1], reverse=True)[:5] + + return { + "main_topics": [word[0] for word in top_words], + "user_intent": "情報収集・問題解決", + "key_insights": ["基本的な会話分析"], + "relationship_indicators": { + "interaction_count": len(messages), + "user_engagement": len(user_messages), + "assistant_helpfulness": len(assistant_messages) + }, + "emotional_tone": "neutral", + "action_items": [], + "summary": f"{len(user_messages)}回のやり取りによる会話" + } + +class RelationshipTracker: + """関係性追跡クラス""" def __init__(self): init_directories() + self.relationship_file = RELATIONSHIP_DIR / "relationships.json" + self.relationships = self._load_relationships() + + def _load_relationships(self) -> Dict[str, Any]: + """関係性データを読み込み""" + if self.relationship_file.exists(): + with open(self.relationship_file, 'r', encoding='utf-8') as f: + return json.load(f) + return {"targets": {}, "last_updated": datetime.now().isoformat()} + + def _save_relationships(self): + """関係性データを保存""" + self.relationships["last_updated"] = datetime.now().isoformat() + with open(self.relationship_file, 'w', encoding='utf-8') as f: + json.dump(self.relationships, f, ensure_ascii=False, indent=2) + + def update_relationship(self, target: str, interaction_type: str, weight: float = 1.0, context: str = None): + """関係性を更新""" + if target not in self.relationships["targets"]: + self.relationships["targets"][target] = { + "score": 0.0, + "interactions": [], + "created_at": datetime.now().isoformat(), + "last_interaction": None + } + + # スコア計算 + score_change = 0.0 + if interaction_type == "positive": + score_change = weight * 1.0 + elif interaction_type == "negative": + score_change = weight * -1.0 + + # 時間減衰を適用 + self._apply_time_decay(target) + + # スコア更新 + current_score = self.relationships["targets"][target]["score"] + new_score = current_score + score_change + + # スコアの範囲制限(-100 to 100) + new_score = max(-100, min(100, new_score)) + + self.relationships["targets"][target]["score"] = new_score + self.relationships["targets"][target]["last_interaction"] = datetime.now().isoformat() + + # インタラクション履歴を追加 + interaction_record = { + "type": interaction_type, + "weight": weight, + "score_change": score_change, + "new_score": new_score, + "timestamp": datetime.now().isoformat(), + "context": context + } + + self.relationships["targets"][target]["interactions"].append(interaction_record) + + # 履歴は最新100件まで保持 + if len(self.relationships["targets"][target]["interactions"]) > 100: + self.relationships["targets"][target]["interactions"] = \ + self.relationships["targets"][target]["interactions"][-100:] + + self._save_relationships() + return new_score + + def _apply_time_decay(self, target: str): + """時間減衰を適用""" + target_data = self.relationships["targets"][target] + last_interaction = target_data.get("last_interaction") + + if last_interaction: + last_time = datetime.fromisoformat(last_interaction) + now = datetime.now() + days_passed = (now - last_time).days + + # 7日ごとに5%減衰 + if days_passed > 0: + decay_factor = 0.95 ** (days_passed / 7) + target_data["score"] *= decay_factor + + def get_relationship_score(self, target: str) -> float: + """関係性スコアを取得""" + if target in self.relationships["targets"]: + self._apply_time_decay(target) + return self.relationships["targets"][target]["score"] + return 0.0 + + def should_send_message(self, target: str, threshold: float = 50.0) -> bool: + """メッセージ送信の可否を判定""" + score = self.get_relationship_score(target) + return score >= threshold + + def get_all_relationships(self) -> Dict[str, Any]: + """すべての関係性を取得""" + # 全ターゲットに時間減衰を適用 + for target in self.relationships["targets"]: + self._apply_time_decay(target) + + return self.relationships + +class MemoryManager: + """記憶管理クラス(AI処理機能付き)""" + + def __init__(self): + init_directories() + self.ai_processor = AIMemoryProcessor() + self.relationship_tracker = RelationshipTracker() def parse_chatgpt_conversation(self, conversation_data: Dict[str, Any]) -> List[Dict[str, Any]]: """ChatGPTの会話データを解析してメッセージを抽出""" @@ -54,7 +295,6 @@ class MemoryManager: content = message.get("content", {}) parts = content.get("parts", []) - # partsが存在し、最初の要素が文字列で空でない場合のみ if parts and isinstance(parts[0], str) and parts[0].strip(): message_nodes.append({ "id": node_id, @@ -63,18 +303,6 @@ class MemoryManager: "content": parts[0], "parent": node.get("parent") }) - else: - print(f"⚠️ Skipped non-text or empty message in node {node_id}") - #if message and message.get("content", {}).get("parts"): - # parts = message["content"]["parts"] - # if parts and parts[0].strip(): # 空でないメッセージのみ - # message_nodes.append({ - # "id": node_id, - # "create_time": message.get("create_time", 0), - # "author_role": message["author"]["role"], - # "content": parts[0], - # "parent": node.get("parent") - # }) # 作成時間でソート message_nodes.sort(key=lambda x: x["create_time"] or 0) @@ -90,8 +318,8 @@ class MemoryManager: return messages - def save_chatgpt_memory(self, conversation_data: Dict[str, Any]) -> str: - """ChatGPTの会話を記憶として保存""" + async def save_chatgpt_memory(self, conversation_data: Dict[str, Any], process_with_ai: bool = True) -> str: + """ChatGPTの会話を記憶として保存(AI処理オプション付き)""" title = conversation_data.get("title", "untitled") create_time = conversation_data.get("create_time", datetime.now().timestamp()) @@ -101,6 +329,17 @@ class MemoryManager: if not messages: raise ValueError("No valid messages found in conversation") + # AI分析を実行 + ai_analysis = None + if process_with_ai: + try: + ai_analysis = await self.ai_processor.generate_ai_summary(messages) + except Exception as e: + print(f"AI analysis failed: {e}") + + # 基本要約を生成 + basic_summary = self.generate_basic_summary(messages) + # 保存データを作成 memory_data = { "title": title, @@ -108,10 +347,24 @@ class MemoryManager: "import_time": datetime.now().isoformat(), "original_create_time": create_time, "messages": messages, - "summary": self.generate_summary(messages) + "basic_summary": basic_summary, + "ai_analysis": ai_analysis, + "message_count": len(messages), + "hash": self._generate_content_hash(messages) } - # ファイル名を生成(タイトルをサニタイズ) + # 関係性データを更新 + if ai_analysis and "relationship_indicators" in ai_analysis: + interaction_count = ai_analysis["relationship_indicators"].get("interaction_count", 0) + if interaction_count > 10: # 長い会話は関係性にプラス + self.relationship_tracker.update_relationship( + target="user_general", + interaction_type="positive", + weight=min(interaction_count / 10, 5.0), + context=f"Long conversation: {title}" + ) + + # ファイル名を生成 safe_title = "".join(c for c in title if c.isalnum() or c in (' ', '-', '_')).rstrip() timestamp = datetime.fromtimestamp(create_time).strftime("%Y%m%d_%H%M%S") filename = f"{timestamp}_{safe_title[:50]}.json" @@ -120,14 +373,19 @@ class MemoryManager: with open(filepath, 'w', encoding='utf-8') as f: json.dump(memory_data, f, ensure_ascii=False, indent=2) + # 処理済みメモリディレクトリにも保存 + if ai_analysis: + processed_filepath = PROCESSED_MEMORY_DIR / filename + with open(processed_filepath, 'w', encoding='utf-8') as f: + json.dump(memory_data, f, ensure_ascii=False, indent=2) + return str(filepath) - def generate_summary(self, messages: List[Dict[str, Any]]) -> str: - """会話の要約を生成""" + def generate_basic_summary(self, messages: List[Dict[str, Any]]) -> str: + """基本要約を生成""" if not messages: return "Empty conversation" - # 簡単な要約を生成(実際のAIによる要約は後で実装可能) user_messages = [msg for msg in messages if msg["role"] == "user"] assistant_messages = [msg for msg in messages if msg["role"] == "assistant"] @@ -139,37 +397,64 @@ class MemoryManager: return summary - def search_memories(self, query: str, limit: int = 10) -> List[Dict[str, Any]]: - """記憶を検索""" + def _generate_content_hash(self, messages: List[Dict[str, Any]]) -> str: + """メッセージ内容のハッシュを生成""" + content = "".join([msg["content"] for msg in messages]) + return hashlib.sha256(content.encode()).hexdigest()[:16] + + def search_memories(self, query: str, limit: int = 10, use_ai_analysis: bool = True) -> List[Dict[str, Any]]: + """記憶を検索(AI分析結果も含む)""" results = [] - # ChatGPTの記憶を検索 - for filepath in CHATGPT_MEMORY_DIR.glob("*.json"): - try: - with open(filepath, 'r', encoding='utf-8') as f: - memory_data = json.load(f) - - # 簡単なキーワード検索 - search_text = f"{memory_data.get('title', '')} {memory_data.get('summary', '')}" - for msg in memory_data.get('messages', []): - search_text += f" {msg.get('content', '')}" - - if query.lower() in search_text.lower(): - results.append({ - "filepath": str(filepath), - "title": memory_data.get("title"), - "summary": memory_data.get("summary"), - "source": memory_data.get("source"), - "import_time": memory_data.get("import_time"), - "message_count": len(memory_data.get("messages", [])) - }) + # 処理済みメモリから検索 + search_dirs = [PROCESSED_MEMORY_DIR, CHATGPT_MEMORY_DIR] if use_ai_analysis else [CHATGPT_MEMORY_DIR] + + for search_dir in search_dirs: + for filepath in search_dir.glob("*.json"): + try: + with open(filepath, 'r', encoding='utf-8') as f: + memory_data = json.load(f) - if len(results) >= limit: - break + # 検索対象テキストを構築 + search_text = f"{memory_data.get('title', '')} {memory_data.get('basic_summary', '')}" + + # AI分析結果も検索対象に含める + if memory_data.get('ai_analysis'): + ai_analysis = memory_data['ai_analysis'] + search_text += f" {' '.join(ai_analysis.get('main_topics', []))}" + search_text += f" {ai_analysis.get('summary', '')}" + search_text += f" {' '.join(ai_analysis.get('key_insights', []))}" + + # メッセージ内容も検索対象に含める + for msg in memory_data.get('messages', []): + search_text += f" {msg.get('content', '')}" + + if query.lower() in search_text.lower(): + result = { + "filepath": str(filepath), + "title": memory_data.get("title"), + "basic_summary": memory_data.get("basic_summary"), + "source": memory_data.get("source"), + "import_time": memory_data.get("import_time"), + "message_count": len(memory_data.get("messages", [])), + "has_ai_analysis": bool(memory_data.get("ai_analysis")) + } - except Exception as e: - print(f"Error reading memory file {filepath}: {e}") - continue + if memory_data.get('ai_analysis'): + result["ai_summary"] = memory_data['ai_analysis'].get('summary', '') + result["main_topics"] = memory_data['ai_analysis'].get('main_topics', []) + + results.append(result) + + if len(results) >= limit: + break + + except Exception as e: + print(f"Error reading memory file {filepath}: {e}") + continue + + if len(results) >= limit: + break return results @@ -190,14 +475,21 @@ class MemoryManager: with open(filepath, 'r', encoding='utf-8') as f: memory_data = json.load(f) - memories.append({ + memory_info = { "filepath": str(filepath), "title": memory_data.get("title"), - "summary": memory_data.get("summary"), + "basic_summary": memory_data.get("basic_summary"), "source": memory_data.get("source"), "import_time": memory_data.get("import_time"), - "message_count": len(memory_data.get("messages", [])) - }) + "message_count": len(memory_data.get("messages", [])), + "has_ai_analysis": bool(memory_data.get("ai_analysis")) + } + + if memory_data.get('ai_analysis'): + memory_info["ai_summary"] = memory_data['ai_analysis'].get('summary', '') + memory_info["main_topics"] = memory_data['ai_analysis'].get('main_topics', []) + + memories.append(memory_info) except Exception as e: print(f"Error reading memory file {filepath}: {e}") continue @@ -207,22 +499,57 @@ class MemoryManager: return memories # FastAPI アプリケーション -app = FastAPI(title="AigptMCP Server with Memory", version="1.0.0") +app = FastAPI(title="AigptMCP Server with AI Memory", version="2.0.0") memory_manager = MemoryManager() @app.post("/memory/import/chatgpt") -async def import_chatgpt_conversation(data: ConversationImport): - """ChatGPTの会話をインポート""" +async def import_chatgpt_conversation(data: ConversationImport, process_with_ai: bool = True): + """ChatGPTの会話をインポート(AI処理オプション付き)""" try: - filepath = memory_manager.save_chatgpt_memory(data.conversation_data) + filepath = await memory_manager.save_chatgpt_memory(data.conversation_data, process_with_ai) return { "success": True, "message": "Conversation imported successfully", - "filepath": filepath + "filepath": filepath, + "ai_processed": process_with_ai } except Exception as e: raise HTTPException(status_code=400, detail=str(e)) +@app.post("/memory/process-ai") +async def process_memory_with_ai(data: MemorySummaryRequest): + """既存の記憶をAIで再処理""" + try: + # 既存記憶を読み込み + memory_data = memory_manager.get_memory_detail(data.filepath) + + # AI分析を実行 + ai_analysis = await memory_manager.ai_processor.generate_ai_summary( + memory_data["messages"], + data.ai_provider + ) + + # データを更新 + memory_data["ai_analysis"] = ai_analysis + memory_data["ai_processed_at"] = datetime.now().isoformat() + + # ファイルを更新 + with open(data.filepath, 'w', encoding='utf-8') as f: + json.dump(memory_data, f, ensure_ascii=False, indent=2) + + # 処理済みディレクトリにもコピー + processed_filepath = PROCESSED_MEMORY_DIR / Path(data.filepath).name + with open(processed_filepath, 'w', encoding='utf-8') as f: + json.dump(memory_data, f, ensure_ascii=False, indent=2) + + return { + "success": True, + "message": "Memory processed with AI successfully", + "ai_analysis": ai_analysis + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + @app.post("/memory/search") async def search_memories(query: MemoryQuery): """記憶を検索""" @@ -261,9 +588,52 @@ async def get_memory_detail(filepath: str): except Exception as e: raise HTTPException(status_code=404, detail=str(e)) +@app.post("/relationship/update") +async def update_relationship(data: RelationshipUpdate): + """関係性を更新""" + try: + new_score = memory_manager.relationship_tracker.update_relationship( + data.target, data.interaction_type, data.weight, data.context + ) + return { + "success": True, + "new_score": new_score, + "can_send_message": memory_manager.relationship_tracker.should_send_message(data.target) + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/relationship/list") +async def list_relationships(): + """すべての関係性をリスト""" + try: + relationships = memory_manager.relationship_tracker.get_all_relationships() + return { + "success": True, + "relationships": relationships + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + +@app.get("/relationship/check") +async def check_send_permission(target: str, threshold: float = 50.0): + """メッセージ送信可否をチェック""" + try: + score = memory_manager.relationship_tracker.get_relationship_score(target) + can_send = memory_manager.relationship_tracker.should_send_message(target, threshold) + return { + "success": True, + "target": target, + "score": score, + "can_send_message": can_send, + "threshold": threshold + } + except Exception as e: + raise HTTPException(status_code=500, detail=str(e)) + @app.post("/chat") async def chat_endpoint(data: ChatMessage): - """チャット機能(記憶を活用)""" + """チャット機能(記憶と関係性を活用)""" try: # 関連する記憶を検索 memories = memory_manager.search_memories(data.message, limit=3) @@ -273,9 +643,14 @@ async def chat_endpoint(data: ChatMessage): if memories: memory_context = "\n# Related memories:\n" for memory in memories: - memory_context += f"- {memory['title']}: {memory['summary']}\n" + memory_context += f"- {memory['title']}: {memory.get('ai_summary', memory.get('basic_summary', ''))}\n" + if memory.get('main_topics'): + memory_context += f" Topics: {', '.join(memory['main_topics'])}\n" - # 実際のチャット処理(他のプロバイダーに転送) + # 関係性情報を取得 + relationships = memory_manager.relationship_tracker.get_all_relationships() + + # 実際のチャット処理 enhanced_message = data.message if memory_context: enhanced_message = f"{data.message}\n\n{memory_context}" @@ -283,7 +658,12 @@ async def chat_endpoint(data: ChatMessage): return { "success": True, "response": f"Enhanced response with memory context: {enhanced_message}", - "memories_used": len(memories) + "memories_used": len(memories), + "relationship_info": { + "active_relationships": len(relationships.get("targets", {})), + "can_initiate_conversations": sum(1 for target, data in relationships.get("targets", {}).items() + if memory_manager.relationship_tracker.should_send_message(target)) + } } except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @@ -292,19 +672,32 @@ async def chat_endpoint(data: ChatMessage): async def root(): """ヘルスチェック""" return { - "service": "AigptMCP Server with Memory", + "service": "AigptMCP Server with AI Memory", + "version": "2.0.0", "status": "running", "memory_dir": str(MEMORY_DIR), + "features": [ + "AI-powered memory analysis", + "Relationship tracking", + "Advanced memory search", + "Conversation import", + "Auto-summary generation" + ], "endpoints": [ "/memory/import/chatgpt", + "/memory/process-ai", "/memory/search", "/memory/list", "/memory/detail", + "/relationship/update", + "/relationship/list", + "/relationship/check", "/chat" ] } if __name__ == "__main__": - print("🚀 AigptMCP Server with Memory starting...") + print("🚀 AigptMCP Server with AI Memory starting...") print(f"📁 Memory directory: {MEMORY_DIR}") + print(f"🧠 AI Memory processing: {'✅ Enabled' if os.getenv('OPENAI_API_KEY') or os.getenv('ANTHROPIC_API_KEY') else '❌ Disabled (no API keys)'}") uvicorn.run(app, host="127.0.0.1", port=5000) diff --git a/readme.md b/readme.md index 07111e2..2a5b6b9 100644 --- a/readme.md +++ b/readme.md @@ -1,130 +1,27 @@ -Memory-Enhanced MCP Server 使用ガイド -概要 -このMCPサーバーは、ChatGPTの会話履歴を記憶として保存し、AIとの対話で活用できる機能を提供します。 +# ai `gpt` -セットアップ -1. 依存関係のインストール -bash -pip install -r requirements.txt -2. サーバーの起動 -bash -python mcp/server.py -サーバーは http://localhost:5000 で起動します。 +自発的送信AI -使用方法 -1. ChatGPTの会話履歴をインポート -ChatGPTから会話をエクスポートし、JSONファイルとして保存してください。 +## 🎯 目的・目標(Purpose & Goal) +- 人格を持つAIが、関係性に応じて自発的にメッセージを送信する仕組みをつくる。 +- 関係性や記憶を不可逆に記録・反映し、唯一性ある人格を構成する。 +- 送信の可否、送信のタイミング、送信内容はAIの関係性パラメータに基づいて決定する。 -bash -# 単一ファイルをインポート -python mcp/memory_client.py import your_chatgpt_export.json +## 🧠 中核設計(Core Concepts) +- **人格**:記憶(過去の発話)と関係性(他者とのつながり)のパラメータで構成 +- **唯一性**:変更不可、不可逆。関係性が壊れたら修復不可能。 +- **送信条件**:関係性パラメータが一定閾値を超えると「送信」が解禁される -# インポート結果の例 -✅ Imported 5/5 conversations -2. 記憶の検索 -bash -# キーワードで記憶を検索 -python mcp/memory_client.py search "プログラミング" +## 🔩 技術仕様(Technical Specs) +- 言語:python, rust, mcp +- ストレージ:json or sqliteで記憶管理(バージョンで選択) +- 関係性パラメータ:数値化された評価 + 減衰(時間) + 環境要因(ステージ) +- 記憶圧縮:ベクトル要約 + ハッシュ保存 +- rustのcli(clap)でインターフェイスを作成 +- fastapi_mcpでserverを立て、AIがそれを利用する形式 -# 検索結果の例 -🔍 Searching for: プログラミング -📚 Found 3 memories: - • Pythonの基礎学習 - Summary: Conversation with 10 user messages and 8 assistant responses... - Messages: 18 -3. 記憶一覧の表示 -bash -python mcp/memory_client.py list - -# 結果の例 -📋 Listing all memories... -📚 Total memories: 15 - • day - Source: chatgpt - Messages: 2 - Imported: 2025-01-21T10:30:45.123456 -4. 記憶の詳細表示 -bash -python mcp/memory_client.py detail "/path/to/memory/file.json" - -# 結果の例 -📄 Getting details for: /path/to/memory/file.json -Title: day -Source: chatgpt -Summary: Conversation with 1 user messages and 1 assistant responses... -Messages: 2 - -Recent messages: - user: こんにちは... - assistant: こんにちは〜!✨... -5. 記憶を活用したチャット -bash -python mcp/memory_client.py chat "Pythonについて教えて" - -# 結果の例 -💬 Chatting with memory: Pythonについて教えて -🤖 Response: Enhanced response with memory context... -📚 Memories used: 2 -API エンドポイント -POST /memory/import/chatgpt -ChatGPTの会話履歴をインポート - -json -{ - "conversation_data": { ... } -} -POST /memory/search -記憶を検索 - -json -{ - "query": "検索キーワード", - "limit": 10 -} -GET /memory/list -すべての記憶をリスト - -GET /memory/detail?filepath=/path/to/file -記憶の詳細を取得 - -POST /chat -記憶を活用したチャット - -json -{ - "message": "メッセージ", - "model": "model_name" -} -記憶の保存場所 -記憶は以下のディレクトリに保存されます: - -~/.config/aigpt/memory/chatgpt/ -各会話は個別のJSONファイルとして保存され、以下の情報を含みます: - -タイトル -インポート時刻 -メッセージ履歴 -自動生成された要約 -メタデータ -ChatGPTの会話エクスポート方法 -ChatGPTの設定画面を開く -"Data controls" → "Export data" を選択 -エクスポートファイルをダウンロード -conversations.json ファイルを使用 -拡張可能な機能 -高度な検索: ベクトル検索やセマンティック検索の実装 -要約生成: AIによる自動要約の改善 -記憶の分類: カテゴリやタグによる分類 -記憶の統合: 複数の会話からの知識統合 -プライバシー保護: 機密情報の自動検出・マスキング -トラブルシューティング -サーバーが起動しない -ポート5000が使用中でないか確認 -依存関係が正しくインストールされているか確認 -インポートに失敗する -JSONファイルが正しい形式か確認 -ファイルパスが正しいか確認 -ファイルの権限を確認 -検索結果が表示されない -インポートが正常に完了しているか確認 -検索キーワードを変更して試行 +## 📦 主要構成要素(Components) +- `MemoryManager`: 発言履歴・記憶圧縮管理 +- `RelationshipTracker`: 関係性スコアの蓄積と判定 +- `TransmissionController`: 閾値判定&送信トリガー +- `Persona`: 上記すべてを統括する人格モジュール