| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- from fastapi import FastAPI, Request
- from fastapi.responses import JSONResponse
- from mem0 import Memory
- app = FastAPI()
- config = {
- "llm": {
- "provider": "groq",
- "config": {
- "model": "llama-3.1-8b-instant",
- "temperature": 0.1,
- "max_tokens": 1500
- }
- },
- "vector_store": {
- "provider": "chroma",
- "config": {
- "host": "192.168.0.200",
- "port": 8001,
- "collection_name": "openclaw_mem"
- }
- },
- "embedder": {
- "provider": "ollama",
- "config": {
- "model": "nomic-embed-text",
- "ollama_base_url": "http://192.168.0.200:11434"
- }
- }
- }
- memory = Memory.from_config(config)
- # Patch Chroma empty-filter crash (mem0 sometimes calls search with {} filters)
- orig_search = memory.vector_store.search
- def is_effectively_empty(filters):
- if not filters:
- return True
- if filters == {"AND": []} or filters == {"OR": []}:
- return True
- return False
- NOOP_WHERE = {"$and": [
- {"user_id": {"$ne": ""}},
- {"user_id": {"$ne": ""}}
- ]}
- def safe_search(query, vectors, limit=10, filters=None):
- if is_effectively_empty(filters):
- return memory.vector_store.collection.query(
- query_embeddings=vectors,
- n_results=limit,
- where=NOOP_WHERE
- )
- try:
- return orig_search(query=query, vectors=vectors, limit=limit, filters=filters)
- except Exception as e:
- if "Expected where" in str(e):
- return memory.vector_store.collection.query(
- query_embeddings=vectors,
- n_results=limit,
- where=NOOP_WHERE
- )
- raise
- memory.vector_store.search = safe_search
- @app.post("/memories")
- async def add_memory(req: Request):
- data = await req.json()
- text = data.get("text")
- user_id = data.get("userId") or data.get("user_id") or "default"
- if not text:
- return JSONResponse({"error": "Empty 'text' field"}, status_code=400)
- result = memory.add(text, user_id=user_id)
- print("add_memory:", {"user_id": user_id, "text": text[:80], "result": result})
- return result
- @app.post("/memories/search")
- async def search(req: Request):
- data = await req.json()
- query = (data.get("query") or "").strip()
- user_id = data.get("userId") or data.get("user_id") or "default"
- if not query:
- return {"results": []}
- try:
- result = memory.search(query, user_id=user_id)
- except Exception:
- # fallback: get_all + simple text filter
- all_res = memory.get_all(user_id=user_id)
- if isinstance(all_res, dict):
- items = all_res.get("results", [])
- elif isinstance(all_res, list):
- items = all_res
- else:
- items = []
- q = query.lower()
- items = [r for r in items if q in (r.get("memory", "").lower())]
- result = {"results": items}
- print("search:", {"user_id": user_id, "query": query, "count": len(result.get("results", []))})
- limit = int(data.get("limit", 5))
- items = result.get("results", [])
- items = sorted(items, key=lambda r: r.get("score", float("inf")))[:limit]
- result = {"results": items}
- print("search:", {"user_id": user_id, "query": query, "count": len(result.get("results", []))})
- return result
- @app.delete("/memories")
- async def delete(req: Request):
- data = await req.json()
- return memory.delete(data.get("filter", {}))
- @app.post("/memories/recent")
- async def recent(req: Request):
- data = await req.json()
- user_id = data.get("userId") or data.get("user_id") or "default"
- if not user_id:
- return JSONResponse({"error":"Missing userId"}, status_code=400)
- print("recent payload:", data, "user_id:", user_id)
- limit = int(data.get("limit", 5))
- try:
- results = memory.get_all(user_id=user_id)
- except Exception:
- results = memory.search(query="*", user_id=user_id)
- items = results.get("results", [])
- items = sorted(items, key=lambda r: r.get("created_at", ""), reverse=True)
- return {"results": items[:limit]}
|