Add reusable LLM parser profiles with multi-event extract.
Support kind=llm profiles (instruction/schema), optional multi-event posts via #eN URLs, and recover stale running/queued parse jobs after worker crashes. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+34
-8
@@ -15,6 +15,10 @@ class TelegramSourceConfig(BaseModel):
|
||||
extract_schema: dict[str, str] | None = None
|
||||
instruction: str | None = None
|
||||
heuristic_profile: dict | None = None
|
||||
# Post-extract gate for extract_mode=llm (empty = only is_event filter)
|
||||
required_fields: list[str] = Field(default_factory=list)
|
||||
# Split one post into N events when extract_mode=llm (opt-in)
|
||||
multi_event: bool = False
|
||||
sample_post: str | None = None # audit / re-generate; not required at runtime
|
||||
|
||||
@field_validator("channel")
|
||||
@@ -22,15 +26,37 @@ class TelegramSourceConfig(BaseModel):
|
||||
def strip_channel(cls, value: str) -> str:
|
||||
return value.strip()
|
||||
|
||||
@model_validator(mode="after")
|
||||
def profile_requires_rules(self) -> "TelegramSourceConfig":
|
||||
if self.extract_mode != "profile":
|
||||
return self
|
||||
if not self.heuristic_profile:
|
||||
raise ValueError("heuristic_profile required when extract_mode=profile")
|
||||
from contracts.heuristic_profile import HeuristicProfile
|
||||
@field_validator("required_fields")
|
||||
@classmethod
|
||||
def known_required(cls, value: list[str]) -> list[str]:
|
||||
from contracts.heuristic_profile import TARGET_FIELDS
|
||||
|
||||
HeuristicProfile.model_validate(self.heuristic_profile)
|
||||
seen: list[str] = []
|
||||
unknown: list[str] = []
|
||||
for name in value:
|
||||
if name not in TARGET_FIELDS:
|
||||
unknown.append(name)
|
||||
continue
|
||||
if name not in seen:
|
||||
seen.append(name)
|
||||
if unknown:
|
||||
raise ValueError(f"Unknown required_fields: {sorted(set(unknown))}")
|
||||
return seen
|
||||
|
||||
@model_validator(mode="after")
|
||||
def validate_extract_mode(self) -> "TelegramSourceConfig":
|
||||
if self.extract_mode == "profile":
|
||||
if not self.heuristic_profile:
|
||||
raise ValueError("heuristic_profile required when extract_mode=profile")
|
||||
from contracts.heuristic_profile import HeuristicProfile
|
||||
|
||||
HeuristicProfile.model_validate(self.heuristic_profile)
|
||||
elif self.extract_mode == "llm" and self.extract_schema is not None:
|
||||
from contracts.heuristic_profile import TARGET_FIELDS
|
||||
|
||||
unknown = set(self.extract_schema) - set(TARGET_FIELDS)
|
||||
if unknown:
|
||||
raise ValueError(f"Unknown extract_schema fields: {sorted(unknown)}")
|
||||
return self
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user