feat(rag): Phase 1 — rewrite build_card_text to natural-language format (#137)
* feat(rag): Phase 1 — rewrite build_card_text to natural-language format * feat(rag): Phase 2 — Forge-enriched ChromaDB RAG store (2a–2e) Phase 2a: Forge lazy import guard (_try_import_forge_lookup) Phase 2b: _build_document appends Forge trigger/replacement/static/keyword tags Phase 2c: _build_metadata adds has_trigger, has_replacement, has_static, trigger_modes fields Phase 2d: query_cards extended with require_trigger, require_replacement, require_static params + ChromaDB where clause support Phase 2e: get_rag_stats reports forge_enriched and forge_coverage; _write_build_meta tracks coverage; build loop counts enriched cards * feat(rag): Phase 3 — add mtgrules second ChromaDB collection Adds build_rules_index() and query_rules() operating on a separate 'mtgrules' ChromaDB collection. Chunks MagicCompRules.txt by rule-number boundaries, embeds each chunk, and exposes semantic search. Completely independent from the mtg_oracle card collection. * feat(coach): Phase 4 — behavior-aware RAG + rules context in coach_service Phase 4a: run_coaching_session uses dual RAG query - Primary: commander synergy (n=10) - Secondary: require_replacement=True for graveyard/protection cards (n=5) - Deduplicates by name before merging Phase 4b: query_rules() fetches 3 Commander rules chunks to ground the prompt - Passed as rules_context kwarg to build_user_prompt() * feat(rag): Phase 5 — add /api/rag/build-rules and /api/rag/query-rules endpoints
This commit is contained in:
1 parent
ac536999eb
commit
aefd0cace6
4 files changed
+387
-190
No files matched your search
@@ -119,3 +119,53 @@ async def rag_status_detail():
|
||||
except Exception as exc:
|
||||
log.exception("RAG status check failed")
|
||||
return {"status": "error", "error": str(exc)}
|
||||
|
||||
|
||||
# ── Phase 5: Rules RAG endpoints ───────────────────────────────────────────
|
||||
class RulesBuildRequest(BaseModel):
|
||||
rules_path: str = Field(
|
||||
...,
|
||||
description="Absolute or repo-relative path to MagicCompRules.txt",
|
||||
)
|
||||
chunk_size: int = Field(400, ge=100, le=2000, description="Approx characters per chunk")
|
||||
|
||||
|
||||
@router.post("/api/rag/build-rules")
|
||||
async def rag_build_rules(body: RulesBuildRequest):
|
||||
"""
|
||||
Build the mtgrules ChromaDB collection from the MTG Comprehensive Rules text file.
|
||||
|
||||
Download MagicCompRules.txt from https://magic.wizards.com/en/rules and pass the
|
||||
local path as `rules_path`. This is a one-time or yearly operation.
|
||||
"""
|
||||
try:
|
||||
from services.rag_store import build_rules_index
|
||||
stats = build_rules_index(body.rules_path, chunk_size=body.chunk_size)
|
||||
return {"status": "ok", **stats}
|
||||
except FileNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc))
|
||||
except Exception as exc:
|
||||
log.exception("Rules RAG build failed")
|
||||
raise HTTPException(status_code=500, detail=str(exc))
|
||||
|
||||
|
||||
@router.get("/api/rag/query-rules")
|
||||
async def rag_query_rules(
|
||||
q: str,
|
||||
n: int = 5,
|
||||
):
|
||||
"""
|
||||
Semantic search over the MTG Comprehensive Rules (mtgrules collection).
|
||||
|
||||
Args:
|
||||
q: Natural-language rules question, e.g. "Does Teferi stop split second?"
|
||||
n: Number of rule chunks to return (default 5, max 20).
|
||||
|
||||
Returns list of {rule_id, text, distance}.
|
||||
"""
|
||||
try:
|
||||
from services.rag_store import query_rules
|
||||
return {"results": query_rules(q, n_results=min(n, 20))}
|
||||
except Exception as exc:
|
||||
log.exception("Rules RAG query failed")
|
||||
raise HTTPException(status_code=500, detail=str(exc))
|
||||
Reference in new issue
Block a user