feat: Phase 2 — RAG integration in Requirements + DSFA Draft
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 35s
CI / test-python-backend-compliance (push) Successful in 26s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 35s
CI / test-python-backend-compliance (push) Successful in 26s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
Add legal context enrichment from Qdrant vector corpus to the two highest-priority modules (Requirements AI assistant and DSFA drafting engine). Go SDK: - Add SearchCollection() with collection override + whitelist validation - Refactor Search() to delegate to shared searchInternal() Python backend: - New ComplianceRAGClient proxying POST /sdk/v1/rag/search (error-tolerant) - AI assistant: enrich interpret_requirement() and suggest_controls() with RAG - Requirements API: add ?include_legal_context=true query parameter Admin (Next.js): - Extract shared queryRAG() utility from chat route - Inject RAG legal context into v1 and v2 draft pipelines Tests for all three layers (Go, Python, TypeScript shared utility). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -177,8 +177,12 @@ async def get_regulation_requirements(
|
||||
|
||||
|
||||
@router.get("/requirements/{requirement_id}")
|
||||
async def get_requirement(requirement_id: str, db: Session = Depends(get_db)):
|
||||
"""Get a specific requirement by ID."""
|
||||
async def get_requirement(
|
||||
requirement_id: str,
|
||||
include_legal_context: bool = Query(False, description="Include RAG legal context"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""Get a specific requirement by ID, optionally with RAG legal context."""
|
||||
from ..db.models import RequirementDB, RegulationDB
|
||||
|
||||
requirement = db.query(RequirementDB).filter(RequirementDB.id == requirement_id).first()
|
||||
@@ -187,7 +191,7 @@ async def get_requirement(requirement_id: str, db: Session = Depends(get_db)):
|
||||
|
||||
regulation = db.query(RegulationDB).filter(RegulationDB.id == requirement.regulation_id).first()
|
||||
|
||||
return {
|
||||
result = {
|
||||
"id": requirement.id,
|
||||
"regulation_id": requirement.regulation_id,
|
||||
"regulation_code": regulation.code if regulation else None,
|
||||
@@ -214,6 +218,33 @@ async def get_requirement(requirement_id: str, db: Session = Depends(get_db)):
|
||||
"source_section": requirement.source_section,
|
||||
}
|
||||
|
||||
if include_legal_context:
|
||||
try:
|
||||
from ..services.rag_client import get_rag_client
|
||||
from ..services.ai_compliance_assistant import AIComplianceAssistant
|
||||
|
||||
rag = get_rag_client()
|
||||
assistant = AIComplianceAssistant()
|
||||
query = f"{requirement.title} {requirement.article or ''}"
|
||||
collection = assistant._collection_for_regulation(regulation.code if regulation else "")
|
||||
rag_results = await rag.search(query, collection=collection, top_k=3)
|
||||
result["legal_context"] = [
|
||||
{
|
||||
"text": r.text,
|
||||
"regulation_code": r.regulation_code,
|
||||
"regulation_short": r.regulation_short,
|
||||
"article": r.article,
|
||||
"score": r.score,
|
||||
"source_url": r.source_url,
|
||||
}
|
||||
for r in rag_results
|
||||
]
|
||||
except Exception as e:
|
||||
logger.warning("Failed to fetch legal context for %s: %s", requirement_id, e)
|
||||
result["legal_context"] = []
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@router.get("/requirements", response_model=PaginatedRequirementResponse)
|
||||
async def list_requirements_paginated(
|
||||
|
||||
Reference in New Issue
Block a user