diff --git a/mcp/scripts/ask.py b/mcp/scripts/ask.py index b4819fd..524cf87 100644 --- a/mcp/scripts/ask.py +++ b/mcp/scripts/ask.py @@ -60,18 +60,19 @@ def call_mcp(cfg, message: str): return response.json().get("output", {}).get("response", "❓ 応答が取得できませんでした") def call_openai(cfg, message: str): + # ツール定義 tools = [ { "type": "function", "function": { - "name": "memory", # MCPツール名と一致させる - "description": "AIが記憶ログを参照するツールです", + "name": "memory", + "description": "記憶を検索する", "parameters": { "type": "object", "properties": { "query": { "type": "string", - "description": "探している記憶に関するキーワードや質問" + "description": "検索する語句" } }, "required": ["query"] @@ -80,15 +81,15 @@ def call_openai(cfg, message: str): } ] + # 最初のメッセージ送信 payload = { "model": cfg["model"], "messages": [ - {"role": "system", "content": "あなたはAIで、必要に応じて記憶検索ツール(memory)を使って過去の会話を参照することができます。"}, + {"role": "system", "content": "あなたはAIで、必要に応じてツールmemoryを使って記憶を検索します。"}, {"role": "user", "content": message} ], - "temperature": 0.7, - "tool_choice": "auto", # AIが自律的にツールを選ぶ - "tools": tools + "tools": tools, + "tool_choice": "auto" } headers = { @@ -96,25 +97,43 @@ def call_openai(cfg, message: str): "Content-Type": "application/json", } - response = requests.post(cfg["url"], headers=headers, json=payload) - response.raise_for_status() + res1 = requests.post(cfg["url"], headers=headers, json=payload) + res1.raise_for_status() + result = res1.json() - result = response.json() - - # AIがtool_callしたかチェック + # 🧠 tool_call されたか確認 if "tool_calls" in result["choices"][0]["message"]: tool_call = result["choices"][0]["message"]["tool_calls"][0] if tool_call["function"]["name"] == "memory": args = json.loads(tool_call["function"]["arguments"]) query = args.get("query", "") - # ここでMCP serverにPOSTする - memory_response = requests.post( - "http://127.0.0.1:5000/memory/search", # あらかじめ実装されたmemory検索用API - json={"query": query} - ).json() - return f"[Memory Tool]: {memory_response.get('result', 'なし')}" - - # 通常のテキスト応答 + print(f"🛠️ ツール実行: memory(query='{query}')") + + # MCPエンドポイントにPOST + memory_res = requests.post("http://127.0.0.1:5000/memory/search", json={"query": query}) + memory_json = memory_res.json() + tool_output = memory_json.get("result", "なし") + + # tool_outputをAIに返す + followup = { + "model": cfg["model"], + "messages": [ + {"role": "system", "content": "あなたはAIで、必要に応じてツールmemoryを使って記憶を検索します。"}, + {"role": "user", "content": message}, + {"role": "assistant", "tool_calls": result["choices"][0]["message"]["tool_calls"]}, + {"role": "tool", "tool_call_id": tool_call["id"], "name": "memory", "content": tool_output} + ] + } + print(tool_output) + print(cfg["model"]) + + res2 = requests.post(cfg["url"], headers=headers, json=followup) + res2.raise_for_status() + final_response = res2.json() + print(final_response) + return final_response["choices"][0]["message"]["content"] + + # ツール未使用 or 通常応答 return result["choices"][0]["message"]["content"] def call_ollama(cfg, message: str): @@ -127,7 +146,6 @@ def call_ollama(cfg, message: str): response = requests.post(cfg["url"], headers=headers, json=payload) response.raise_for_status() return response.json().get("response", "❌ 応答が取得できませんでした") - def main(): if len(sys.argv) < 2: print("Usage: ask.py 'your message'") diff --git a/mcp/scripts/memory_store.py b/mcp/scripts/memory_store.py index f85409b..889b15e 100644 --- a/mcp/scripts/memory_store.py +++ b/mcp/scripts/memory_store.py @@ -22,16 +22,29 @@ def save_message(sender, message): with open(path, "w") as f: json.dump(logs, f, indent=2, ensure_ascii=False) +#def search_memory(query: str): +# from glob import glob +# all_logs = [] +# for file_path in sorted(MEMORY_DIR.glob("*.json")): +# with open(file_path, "r") as f: +# logs = json.load(f) +# #matched = [entry for entry in logs if query in entry["message"]] +# matched = [entry for entry in logs if query.lower() in entry["message"].lower()] +# all_logs.extend(matched) +# return all_logs[-5:] # 最新5件だけ返す + def search_memory(query: str): from glob import glob all_logs = [] + pattern = re.compile(re.escape(query), re.IGNORECASE) + for file_path in sorted(MEMORY_DIR.glob("*.json")): with open(file_path, "r") as f: logs = json.load(f) - matched = [entry for entry in logs if query in entry["message"]] + matched = [entry for entry in logs if pattern.search(entry["message"])] all_logs.extend(matched) - return all_logs[-5:] # 最新5件だけ返す + return all_logs[-5:] # scripts/memory_store.py import json @@ -60,15 +73,31 @@ def save_message(sender, message): with open(path, "w") as f: json.dump(logs, f, indent=2, ensure_ascii=False) -# キーワードで過去のメモリを検索する(最新5件を返す) def search_memory(query: str): + from glob import glob all_logs = [] for file_path in sorted(MEMORY_DIR.glob("*.json")): - try: - with open(file_path, "r") as f: - logs = json.load(f) - matched = [entry for entry in logs if query.lower() in entry["message"].lower()] - all_logs.extend(matched) - except Exception as e: - print(f"⚠️ 読み込み失敗: {file_path} ({e})") - return all_logs[-5:] # 最新5件を返す + with open(file_path, "r") as f: + logs = json.load(f) + matched = [ + entry for entry in logs + if entry["sender"] == "user" and query in entry["message"] + ] + all_logs.extend(matched) + return all_logs[-5:] # 最新5件だけ返す +def search_memory(query: str): + from glob import glob + all_logs = [] + seen_messages = set() # すでに見たメッセージを保持 + + for file_path in sorted(MEMORY_DIR.glob("*.json")): + with open(file_path, "r") as f: + logs = json.load(f) + for entry in logs: + if entry["sender"] == "user" and query in entry["message"]: + # すでに同じメッセージが結果に含まれていなければ追加 + if entry["message"] not in seen_messages: + all_logs.append(entry) + seen_messages.add(entry["message"]) + + return all_logs[-5:] # 最新5件だけ返す diff --git a/mcp/scripts/server.py b/mcp/scripts/server.py index b570871..cb75a8b 100644 --- a/mcp/scripts/server.py +++ b/mcp/scripts/server.py @@ -1,9 +1,8 @@ # server.py -from fastapi import FastAPI +from fastapi import FastAPI, Body from fastapi_mcp import FastApiMCP from pydantic import BaseModel -#from memory_store import save_message, load_messages, search_memory -from memory_store import save_message, load_logs, search_memory +from memory_store import save_message, load_logs, search_memory as do_search_memory app = FastAPI() mcp = FastApiMCP(app, name="aigpt-agent", description="MCP Server for AI memory") @@ -43,11 +42,37 @@ async def ask_message(input: MemoryQuery): "response": f"🔎 記憶から {len(results)} 件ヒット:\n" + "\n".join([f"{r['sender']}: {r['message']}" for r in results]) } +## こちらはうまくいく +## curl -X POST http://127.0.0.1:5000/memory/search -H "Content-Type: application/json" -d '{"query": "昨日"}' +## {"result":"記憶の中から「昨日」に関するデータを返しました"} +#@app.post("/memory/search", operation_id="memory") +#async def search_memory(input: dict): +# query = input.get("query", "") +# results = do_search_memory(query) +# if not results: +# return {"result": "該当する記憶は見つかりませんでした"} +# return { +# "result": "記憶検索結果:\n" + "\n".join([f"{r['sender']}: {r['message']}" for r in results]) +# } +# +## こちらはうまくいかない +## curl -X POST http://127.0.0.1:5000/memory/search -H "Content-Type: application/json" -d '{"query": "昨日"}' +## Internal Server Error +#@app.post("/memory/search", operation_id="memory") +#async def memory_search(query: MemoryQuery): +# hits = search_memory(query.query) +# if not hits: +# return {"result": "🔍 記憶の中に該当する内容は見つかりませんでした。"} +# summary = "\n".join([f"{e['sender']}: {e['message']}" for e in hits]) +# return {"result": f"🔎 見つかった記憶:\n{summary}"} + @app.post("/memory/search", operation_id="memory") -async def search_memory(input: dict): - query = input.get("query", "") - # 適当なキーワード検索ロジックを追加(例: logs.jsonを検索) - return {"result": f"記憶の中から「{query}」に関するデータを返しました"} +async def memory_search(query: MemoryQuery): + hits = do_search_memory(query.query) # ←ここを修正 + if not hits: + return {"result": "🔍 記憶の中に該当する内容は見つかりませんでした。"} + summary = "\n".join([f"{e['sender']}: {e['message']}" for e in hits]) + return {"result": f"🔎 見つかった記憶:\n{summary}"} # --- MCP 初期化 --- mcp.mount() diff --git a/mcp/scripts/t.py b/mcp/scripts/t.py new file mode 100644 index 0000000..7797f65 --- /dev/null +++ b/mcp/scripts/t.py @@ -0,0 +1,20 @@ +from fastapi import FastAPI +from fastapi_mcp import FastApiMCP + +app = FastAPI() + +@app.get("/items/{item_id}", operation_id="get_item") +async def read_item(item_id: int): + return {"item_id": item_id, "name": f"Item {item_id}"} + +# MCPサーバを作成し、FastAPIアプリにマウント +mcp = FastApiMCP( + app, + name="My API MCP", + description="My API description" +) +mcp.mount() + +if __name__ == "__main__": + import uvicorn + uvicorn.run(app, host="0.0.0.0", port=8000)