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 B: fact and signal extraction. Pulls discrete, evidence-anchored
|
||||
signals (hiring, partnerships, leadership, financial, etc.) out of a single
|
||||
document - the atomic units Task C (synthesis) and Task D (report
|
||||
generation) later combine."""
|
||||
|
||||
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 extracting discrete factual signals from a "
|
||||
"single document. Extract only what the text actually states or clearly implies - never "
|
||||
"add outside knowledge. Every signal must include the exact passage that supports it."
|
||||
)
|
||||
|
||||
_SIGNAL_TYPES = (
|
||||
"event, entity, date, location, product, leadership, partnership, hiring, investment, "
|
||||
"manufacturing, technology, financial, regulatory, sentiment"
|
||||
)
|
||||
|
||||
|
||||
class ExtractedSignal(BaseModel):
|
||||
signal_type: str = Field(description=f"One of: {_SIGNAL_TYPES}")
|
||||
description: str
|
||||
supporting_passage: str = Field(description="The exact quote from the document backing this")
|
||||
date: str | None = None
|
||||
entities: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ExtractionResult(BaseModel):
|
||||
signals: list[ExtractedSignal] = Field(default_factory=list)
|
||||
|
||||
|
||||
async def extract_signals(
|
||||
llm: LLMProvider,
|
||||
*,
|
||||
document_title: str | None,
|
||||
document_url: str,
|
||||
document_text: str,
|
||||
) -> ExtractionResult:
|
||||
evidence = {
|
||||
"document_title": document_title,
|
||||
"document_url": document_url,
|
||||
"document_text": document_text[:6000],
|
||||
}
|
||||
user_prompt = build_user_prompt(
|
||||
"Extract every discrete factual signal from this document, each anchored to its "
|
||||
"exact supporting passage.",
|
||||
evidence,
|
||||
)
|
||||
return await llm.generate_structured(SYSTEM_PROMPT, user_prompt, ExtractionResult)
|
||||
Reference in New Issue
Block a user