Files
loogle-scripts/services/loogle-mcp/scripts/test_gitea_rag_p3.py
T

131 lines
4.4 KiB
Python
Executable File

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Test P3: RAG semantico su file Gitea indicizzati."""
from __future__ import annotations
import json
import os
import sys
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if ROOT not in sys.path:
sys.path.insert(0, ROOT)
def _load_dotenv() -> None:
env_path = os.path.join(ROOT, ".env")
if not os.path.isfile(env_path):
return
with open(env_path, encoding="utf-8") as fh:
for line in fh:
line = line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, _, value = line.partition("=")
key = key.strip()
if key and key not in os.environ:
os.environ[key] = value.strip().strip("'").strip('"')
def _configure_paths() -> str:
in_container = os.path.isfile("/.dockerenv") or (
os.path.isdir("/data") and os.access("/data", os.W_OK)
)
if in_container:
os.environ.setdefault("MCP_DB", "/data/loogle_mcp.db")
os.environ.setdefault("MCP_VECTOR_FALLBACK", "/data/vector_fallback.db")
return "container"
os.environ["MCP_DB"] = "/tmp/loogle_mcp_p3_test.db"
os.environ["MCP_VECTOR_FALLBACK"] = "/tmp/loogle_mcp_p3_vectors.db"
return "host"
def main() -> int:
_load_dotenv()
mode = _configure_paths()
print(f"mode={mode} db={os.environ['MCP_DB']} vector={os.environ['MCP_VECTOR_FALLBACK']}")
from app.db import get_conn, init_db
from app.knowledge import gitea_indexer
from app.mcp import tools
init_db()
if not get_conn().execute(
"SELECT 1 FROM sqlite_master WHERE name='indexed_gitea_files'"
).fetchone():
raise RuntimeError("tabella indexed_gitea_files assente")
if not os.environ.get("GITEA_API_TOKEN_DANIELE", "").strip():
print("SKIP: GITEA_API_TOKEN_DANIELE assente")
return 1
repo = "daniele/rete"
existing = gitea_indexer.list_indexed_files(limit=5, repo=repo)
stats = gitea_indexer.index_stats()
if len(existing) < 1 or stats.get("qdrant_points", 0) < 1:
index_result = gitea_indexer.index_repo(
repo,
username="daniele",
force=True,
max_files=1,
)
print("index", json.dumps(index_result, ensure_ascii=False))
else:
print("index_skip", "already", len(existing), "files")
files = gitea_indexer.list_indexed_files(limit=5, repo=repo)
if not files:
raise RuntimeError("indexed_gitea_files vuota")
print("indexed_sample", [f["path"] for f in files[:3]])
claims = {"sub": "daniele", "scope": "knowledge:read gitea:read admin", "admin": "admin"}
for query in ("failover tier-b", "runbook"):
hits = gitea_indexer.search_gitea_knowledge("daniele", query, limit=5, is_admin=True)
if not hits:
raise RuntimeError(f"search_gitea_knowledge senza risultati per: {query}")
top = hits[0]
print(
f"search_ok[{query}]",
top.get("path") or top.get("title"),
round(float(top.get("score", 0)), 3),
)
tool_out = tools.call_tool(
"search_gitea_knowledge",
{"query": "failover", "limit": 5},
claims,
)
if not json.loads(tool_out["content"][0]["text"]).get("results"):
raise RuntimeError("tool search_gitea_knowledge vuoto")
unified = tools.call_tool(
"search_knowledge",
{"query": "FAILOVER CENSIMENTO documenti servizi", "limit": 12},
claims,
)
unified_payload = json.loads(unified["content"][0]["text"])
results = unified_payload.get("results") or []
sources = set()
for r in results:
if r.get("repo"):
sources.add("gitea")
elif r.get("source"):
sources.add(r["source"])
else:
sources.add("paperless")
print("search_knowledge_sources", sorted(sources))
if "gitea" not in sources:
raise RuntimeError("search_knowledge non include risultati Gitea")
list_tool = tools.call_tool("list_gitea_indexed_files", {"repo": repo, "limit": 5}, claims)
if json.loads(list_tool["content"][0]["text"]).get("count", 0) <= 0:
raise RuntimeError("list_gitea_indexed_files vuoto")
print("OK P3: search + unified + list (reindex opzionale via tool reindex_gitea_repo)")
return 0
if __name__ == "__main__":
raise SystemExit(main())