Maximize Qdrant utilization: richer memory payloads, filtered retrieval, and qdrant health in metrics API
This commit is contained in:
3
app.py
3
app.py
@@ -6,7 +6,7 @@ from datetime import datetime, timedelta
|
|||||||
import threading
|
import threading
|
||||||
from db import init_db, SessionLocal, BotDecision, TradeExecution, CuratedInsight
|
from db import init_db, SessionLocal, BotDecision, TradeExecution, CuratedInsight
|
||||||
from bot import start_scheduler, run_cycle, curate_cycle
|
from bot import start_scheduler, run_cycle, curate_cycle
|
||||||
from services import account_snapshot
|
from services import account_snapshot, qdrant_memory_health
|
||||||
|
|
||||||
app = FastAPI(title="alpaca-llm-bot-v1")
|
app = FastAPI(title="alpaca-llm-bot-v1")
|
||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
@@ -94,6 +94,7 @@ def api_metrics(hours: int = 72):
|
|||||||
"cumulativeNotional": t_values,
|
"cumulativeNotional": t_values,
|
||||||
},
|
},
|
||||||
"leaderboard": leaderboard,
|
"leaderboard": leaderboard,
|
||||||
|
"qdrant": qdrant_memory_health(),
|
||||||
}
|
}
|
||||||
finally:
|
finally:
|
||||||
db.close()
|
db.close()
|
||||||
|
|||||||
4
bot.py
4
bot.py
@@ -125,9 +125,11 @@ def run_cycle():
|
|||||||
|
|
||||||
# learning memory + notes + orchestration signal
|
# learning memory + notes + orchestration signal
|
||||||
qdrant_add_memory(symbol, f"{symbol} {decision['action']} conf={decision['confidence']} reason={decision['reason']}", {
|
qdrant_add_memory(symbol, f"{symbol} {decision['action']} conf={decision['confidence']} reason={decision['reason']}", {
|
||||||
|
"memory_type": "execution",
|
||||||
"status": drow.status,
|
"status": drow.status,
|
||||||
"action": decision["action"],
|
"action": decision["action"],
|
||||||
"confidence": decision["confidence"],
|
"confidence": decision["confidence"],
|
||||||
|
"outcome_score": 1 if ok else -1,
|
||||||
"ts": datetime.utcnow().isoformat(),
|
"ts": datetime.utcnow().isoformat(),
|
||||||
})
|
})
|
||||||
trilium_log(
|
trilium_log(
|
||||||
@@ -145,9 +147,11 @@ def run_cycle():
|
|||||||
|
|
||||||
# store non-trade decisions too for memory
|
# store non-trade decisions too for memory
|
||||||
qdrant_add_memory(symbol, f"{symbol} decision={decision['action']} conf={decision['confidence']} status={drow.status}", {
|
qdrant_add_memory(symbol, f"{symbol} decision={decision['action']} conf={decision['confidence']} status={drow.status}", {
|
||||||
|
"memory_type": "decision",
|
||||||
"status": drow.status,
|
"status": drow.status,
|
||||||
"action": decision["action"],
|
"action": decision["action"],
|
||||||
"confidence": decision["confidence"],
|
"confidence": decision["confidence"],
|
||||||
|
"outcome_score": 0 if drow.status in {"skipped", "risk_blocked"} else (-1 if drow.status=="failed" else 1),
|
||||||
"ts": datetime.utcnow().isoformat(),
|
"ts": datetime.utcnow().isoformat(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
49
services.py
49
services.py
@@ -34,8 +34,15 @@ def qdrant_add_memory(symbol: str, text: str, payload: dict):
|
|||||||
if not vec:
|
if not vec:
|
||||||
return False
|
return False
|
||||||
qdrant_ensure_collection(len(vec))
|
qdrant_ensure_collection(len(vec))
|
||||||
|
enriched = {
|
||||||
|
"symbol": symbol,
|
||||||
|
"text": text[:2000],
|
||||||
|
"memory_type": payload.get("memory_type", "decision"),
|
||||||
|
"created_at": int(time.time()),
|
||||||
|
**payload,
|
||||||
|
}
|
||||||
body = {
|
body = {
|
||||||
"points": [{"id": str(uuid.uuid4()), "vector": vec, "payload": {"symbol": symbol, "text": text[:2000], **payload}}]
|
"points": [{"id": str(uuid.uuid4()), "vector": vec, "payload": enriched}]
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
r = requests.put(f"{settings.qdrant_url}/collections/{settings.qdrant_collection}/points", json=body, timeout=15)
|
r = requests.put(f"{settings.qdrant_url}/collections/{settings.qdrant_collection}/points", json=body, timeout=15)
|
||||||
@@ -44,11 +51,21 @@ def qdrant_add_memory(symbol: str, text: str, payload: dict):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def qdrant_similar(symbol: str, query_text: str, limit: int = 5):
|
def qdrant_similar(symbol: str, query_text: str, limit: int = 8):
|
||||||
vec = _embed(query_text)
|
vec = _embed(query_text)
|
||||||
if not vec:
|
if not vec:
|
||||||
return []
|
return []
|
||||||
body = {"vector": vec, "limit": limit, "with_payload": True}
|
body = {
|
||||||
|
"vector": vec,
|
||||||
|
"limit": limit,
|
||||||
|
"with_payload": True,
|
||||||
|
"filter": {
|
||||||
|
"should": [
|
||||||
|
{"key": "symbol", "match": {"value": symbol}},
|
||||||
|
{"key": "memory_type", "match": {"value": "macro"}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
try:
|
try:
|
||||||
r = requests.post(f"{settings.qdrant_url}/collections/{settings.qdrant_collection}/points/search", json=body, timeout=15)
|
r = requests.post(f"{settings.qdrant_url}/collections/{settings.qdrant_collection}/points/search", json=body, timeout=15)
|
||||||
if not r.ok:
|
if not r.ok:
|
||||||
@@ -56,8 +73,14 @@ def qdrant_similar(symbol: str, query_text: str, limit: int = 5):
|
|||||||
out = []
|
out = []
|
||||||
for p in r.json().get("result", []):
|
for p in r.json().get("result", []):
|
||||||
pl = p.get("payload", {})
|
pl = p.get("payload", {})
|
||||||
if pl.get("symbol") in (symbol, None):
|
out.append({
|
||||||
out.append({"score": p.get("score", 0), "text": pl.get("text", ""), "status": pl.get("status", "")})
|
"score": p.get("score", 0),
|
||||||
|
"text": pl.get("text", ""),
|
||||||
|
"status": pl.get("status", ""),
|
||||||
|
"action": pl.get("action", ""),
|
||||||
|
"confidence": pl.get("confidence", None),
|
||||||
|
"outcome_score": pl.get("outcome_score", None),
|
||||||
|
})
|
||||||
return out
|
return out
|
||||||
except Exception:
|
except Exception:
|
||||||
return []
|
return []
|
||||||
@@ -233,6 +256,22 @@ def trilium_log(title: str, body: str):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def qdrant_memory_health():
|
||||||
|
try:
|
||||||
|
r = requests.get(f"{settings.qdrant_url}/collections/{settings.qdrant_collection}", timeout=10)
|
||||||
|
if not r.ok:
|
||||||
|
return {"ok": False, "status": r.status_code}
|
||||||
|
j = r.json().get("result", {})
|
||||||
|
return {
|
||||||
|
"ok": True,
|
||||||
|
"collection": settings.qdrant_collection,
|
||||||
|
"points_count": j.get("points_count"),
|
||||||
|
"indexed_vectors_count": j.get("indexed_vectors_count"),
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
return {"ok": False, "error": str(e)[:160]}
|
||||||
|
|
||||||
|
|
||||||
def n8n_emit(event: dict):
|
def n8n_emit(event: dict):
|
||||||
if not settings.n8n_webhook:
|
if not settings.n8n_webhook:
|
||||||
return False
|
return False
|
||||||
|
|||||||
Reference in New Issue
Block a user