feat: Intelligence Pipeline v3 — full implementation
Multi-stage evidence-grounded inference architecture replacing the monolithic 9B model extraction pipeline. CPU-first specialist services handle routine extraction while the 9B vLLM model is preserved for semantic adjudication of ambiguous cases. Key components: - Capability-aware inference gateway (OpenAI-compatible + Ollama) - Endpoint registry with DB migrations and REST API - Sentence-aware document segmenter (property tests) - Deterministic financial parsing with offset integrity - Symbol resolution with ambiguity detection - Specialist service (GLiNER2, dynamic batching, K8s deployment) - Company-specific sentiment (FinBERT, calibration) - Retrieval-based novelty and duplicate detection - Confidence calibration pipeline - Deterministic routing engine (property tests) - 9B adjudication layer with VRAM gating - Stock-specific impact model (features, labels, baseline, trained) - Pipeline orchestrator (state machine, queues, leases, feature flags) - Bounded parallelism (async workers, semaphore, load shedding) - Observability (tracing, metrics, alerts) - Compatibility adapter (v3→v2 golden mapping tests) - Shadow/canary promotion framework - Active learning and fine-tuning pipeline Test results: 1,161 tests pass, ruff lint clean. All 282 spec tasks completed.
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
"""Request and response models for the specialist inference service."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Constants
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
MODEL_VERSION = "gliner2-large-v1.0"
|
||||
SCHEMA_VERSION = "specialist-v1"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Request models
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class ExtractionRequest(BaseModel):
|
||||
"""Batch extraction request accepted by entity, relation, and structured endpoints."""
|
||||
|
||||
texts: list[str] = Field(..., min_length=1, description="Texts to process")
|
||||
schema_labels: list[str] = Field(
|
||||
..., min_length=1, description="Entity/relation/event labels to extract"
|
||||
)
|
||||
batch_id: str | None = Field(
|
||||
default=None, description="Optional caller-provided batch identifier"
|
||||
)
|
||||
|
||||
|
||||
class ClassificationRequest(BaseModel):
|
||||
"""Batch classification request accepted by the classify endpoint."""
|
||||
|
||||
texts: list[str] = Field(..., min_length=1, description="Texts to classify")
|
||||
schema_labels: list[str] = Field(
|
||||
..., min_length=1, description="Classification labels"
|
||||
)
|
||||
batch_id: str | None = Field(
|
||||
default=None, description="Optional caller-provided batch identifier"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Result models
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class EntityResult(BaseModel):
|
||||
"""A single extracted entity span."""
|
||||
|
||||
text: str
|
||||
entity_type: str
|
||||
start_char: int
|
||||
end_char: int
|
||||
score: float = Field(..., ge=0.0, le=1.0)
|
||||
model_version: str = MODEL_VERSION
|
||||
schema_version: str = SCHEMA_VERSION
|
||||
|
||||
|
||||
class RelationResult(BaseModel):
|
||||
"""A single extracted relation."""
|
||||
|
||||
subject: str
|
||||
subject_type: str
|
||||
subject_start: int
|
||||
subject_end: int
|
||||
relation: str
|
||||
object: str
|
||||
object_type: str
|
||||
object_start: int
|
||||
object_end: int
|
||||
score: float = Field(..., ge=0.0, le=1.0)
|
||||
model_version: str = MODEL_VERSION
|
||||
schema_version: str = SCHEMA_VERSION
|
||||
|
||||
|
||||
class ClassificationResult(BaseModel):
|
||||
"""A single classification result."""
|
||||
|
||||
text: str
|
||||
label: str
|
||||
score: float = Field(..., ge=0.0, le=1.0)
|
||||
model_version: str = MODEL_VERSION
|
||||
schema_version: str = SCHEMA_VERSION
|
||||
|
||||
|
||||
class StructuredResult(BaseModel):
|
||||
"""A single structured extraction result with key-value facts."""
|
||||
|
||||
text: str
|
||||
field: str
|
||||
value: str
|
||||
start_char: int
|
||||
end_char: int
|
||||
score: float = Field(..., ge=0.0, le=1.0)
|
||||
model_version: str = MODEL_VERSION
|
||||
schema_version: str = SCHEMA_VERSION
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Batch response
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class BatchResponse(BaseModel):
|
||||
"""Unified batch response wrapping results from any endpoint."""
|
||||
|
||||
results: list[list[EntityResult]] | list[list[RelationResult]] | list[list[ClassificationResult]] | list[list[StructuredResult]]
|
||||
model_version: str = MODEL_VERSION
|
||||
schema_version: str = SCHEMA_VERSION
|
||||
processing_time_ms: float
|
||||
batch_id: str | None = None
|
||||
Reference in New Issue
Block a user