fix memory mcp
This commit is contained in:
parent
2f27e10f62
commit
df128e5048
@ -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'")
|
||||
|
@ -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()]
|
||||
matched = [
|
||||
entry for entry in logs
|
||||
if entry["sender"] == "user" and query in entry["message"]
|
||||
]
|
||||
all_logs.extend(matched)
|
||||
except Exception as e:
|
||||
print(f"⚠️ 読み込み失敗: {file_path} ({e})")
|
||||
return all_logs[-5:] # 最新5件を返す
|
||||
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件だけ返す
|
||||
|
@ -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()
|
||||
|
20
mcp/scripts/t.py
Normal file
20
mcp/scripts/t.py
Normal file
@ -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)
|
Loading…
x
Reference in New Issue
Block a user