feat(clustering): persistent enrichment cache in task_enrichments table
Each unique task title is now enriched by LiteLLM once and cached in the DB. Subsequent agent compute cycles (every 12h) fetch the cache before calling ml-serving; only new titles hit the tip-generator. - DB: task_enrichments(content_hash PK, description, model, created_at) - TS: fetchEnrichmentCache / persistEnrichments helpers in agent-outputs.ts; enrichment_cache passed in compute request, new_enrichments persisted from response - Python: AgentComputeRequest.enrichment_cache / AgentComputeResponse.new_enrichments; AgentInput.enrichment_cache; _enrich_batch returns (descriptions, new_entries); cluster_tasks returns (clusters, new_enrichments) - FocusAreaAgent stashes new_enrichments in signals_snapshot under _new_enrichments; compute_agent endpoint pops it before storing the snapshot Closes part of #129 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -196,6 +196,9 @@ class AgentComputeRequest(BaseModel):
|
||||
now_iso: Optional[str] = None # ISO 8601; defaults to utcnow
|
||||
# Per-agent prefs from user_preferences (merged: user source overrides inferred).
|
||||
agent_prefs: dict = {}
|
||||
# Pre-fetched enrichment cache: {content_hash -> description}. Avoids re-calling
|
||||
# LiteLLM for task titles already expanded in a prior compute cycle.
|
||||
enrichment_cache: dict[str, str] = {}
|
||||
|
||||
|
||||
class AgentComputeResponse(BaseModel):
|
||||
@@ -206,6 +209,8 @@ class AgentComputeResponse(BaseModel):
|
||||
computed_at: str
|
||||
expires_at: str
|
||||
agent_version: str
|
||||
# New enrichments generated during this compute cycle; caller persists to DB.
|
||||
new_enrichments: dict[str, str] = {}
|
||||
|
||||
|
||||
class AgentInferRequest(BaseModel):
|
||||
@@ -314,6 +319,7 @@ async def compute_agent(agent_id: str, req: AgentComputeRequest) -> AgentCompute
|
||||
feedback_history=req.feedback_history,
|
||||
now=now,
|
||||
agent_prefs=req.agent_prefs,
|
||||
enrichment_cache=req.enrichment_cache,
|
||||
)
|
||||
try:
|
||||
output = agent.compute(inp)
|
||||
@@ -321,6 +327,8 @@ async def compute_agent(agent_id: str, req: AgentComputeRequest) -> AgentCompute
|
||||
log.error("agent_compute_failed", agent_id=agent_id, user_id=req.user_id, error=str(exc))
|
||||
raise HTTPException(status_code=500, detail=f"Agent compute failed: {exc}")
|
||||
|
||||
new_enrichments: dict[str, str] = output.signals_snapshot.pop("_new_enrichments", {})
|
||||
|
||||
log.info("agent_computed", agent_id=agent_id, user_id=req.user_id, expires_at=output.expires_at)
|
||||
span = _start_span(
|
||||
f"compute:{agent_id}",
|
||||
@@ -339,6 +347,7 @@ async def compute_agent(agent_id: str, req: AgentComputeRequest) -> AgentCompute
|
||||
computed_at=output.computed_at,
|
||||
expires_at=output.expires_at,
|
||||
agent_version=output.agent_version,
|
||||
new_enrichments=new_enrichments,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user