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.
114 lines
3.3 KiB
Python
114 lines
3.3 KiB
Python
"""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
|