Initial commit: CI Agent competitive-intelligence monitoring app
FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
"""Task C: cross-source synthesis. Combines related signals from multiple
|
||||
documents/changes into a conclusion (e.g. "hiring battery engineers" +
|
||||
"filed a battery patent" + "announced a facility expansion" = "possible
|
||||
battery manufacturing initiative"), always with alternative explanations and
|
||||
an explicit accounting of what's still unknown.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.analysis.llm.base import LLMProvider
|
||||
from app.prompts.base import build_user_prompt
|
||||
|
||||
SYSTEM_PROMPT = (
|
||||
"You are a competitive intelligence analyst. Given a set of independently-extracted "
|
||||
"signals about a company, identify conclusions that multiple signals point toward "
|
||||
"together. Only draw a conclusion when the evidence actually supports it - state your "
|
||||
"confidence honestly, list plausible alternative explanations, and note what evidence "
|
||||
"would be needed to be more certain. Do not synthesize a conclusion from a single signal."
|
||||
)
|
||||
|
||||
|
||||
class SynthesizedConclusion(BaseModel):
|
||||
conclusion: str
|
||||
evidence_summary: list[str] = Field(default_factory=list)
|
||||
source_count: int = Field(ge=0)
|
||||
confidence: float = Field(ge=0.0, le=1.0)
|
||||
alternative_explanations: list[str] = Field(default_factory=list)
|
||||
missing_information: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class SynthesisResult(BaseModel):
|
||||
conclusions: list[SynthesizedConclusion] = Field(default_factory=list)
|
||||
|
||||
|
||||
async def synthesize_signals(
|
||||
llm: LLMProvider,
|
||||
*,
|
||||
company_name: str,
|
||||
monitoring_focus: str | None,
|
||||
signals: list[dict],
|
||||
) -> SynthesisResult:
|
||||
evidence = {
|
||||
"company_name": company_name,
|
||||
"monitoring_focus": monitoring_focus,
|
||||
"signals": signals,
|
||||
}
|
||||
user_prompt = build_user_prompt(
|
||||
"Identify conclusions supported by two or more of these signals together. Do not "
|
||||
"synthesize from a single signal alone.",
|
||||
evidence,
|
||||
)
|
||||
return await llm.generate_structured(SYSTEM_PROMPT, user_prompt, SynthesisResult)
|
||||
Reference in New Issue
Block a user