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:
Celes Renata
2026-07-13 02:14:59 +00:00
parent 84634a365e
commit a72f336ad1
227 changed files with 50403 additions and 0 deletions
@@ -0,0 +1,20 @@
"""Legacy path deprecation tracking and cleanup management.
Tracks deprecated components (VLLMClient, v2 prompts, provider branching),
validates that all consumers have migrated, and provides safe removal
gating. Removal only proceeds after all downstream consumers read v3.
"""
from services.intelligence_pipeline_v3.deprecation.tracker import (
DeprecationEntry,
DeprecationStatus,
DeprecationTracker,
MigrationReport,
)
__all__ = [
"DeprecationEntry",
"DeprecationStatus",
"DeprecationTracker",
"MigrationReport",
]
@@ -0,0 +1,271 @@
"""Deprecation tracker for legacy pipeline components.
Manages the lifecycle of deprecated components: VLLMClient, v2 prompts,
provider branching, 8000-char truncation, environment/model defaults,
provider free-text fields, and the compatibility adapter.
Removal only happens after all downstream consumers read v3 natively,
validated by consumer audit.
"""
from __future__ import annotations
import enum
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any
from uuid import UUID, uuid4
class DeprecationStatus(str, enum.Enum):
"""Lifecycle status of a deprecated component."""
ACTIVE = "active" # Still in use
DEPRECATED = "deprecated" # Marked for removal, consumers migrating
MIGRATION_COMPLETE = "migration_complete" # All consumers migrated
REMOVED = "removed" # Code removed
ARCHIVED = "archived" # Final reports preserved
@dataclass
class DeprecationEntry:
"""A tracked deprecated component with migration status."""
entry_id: UUID
component_name: str
component_path: str # File/module path
status: DeprecationStatus
deprecated_at: datetime
reason: str
# Consumer tracking
known_consumers: list[str] = field(default_factory=list)
migrated_consumers: list[str] = field(default_factory=list)
# Removal gates
removal_approved: bool = False
removal_approver: str = ""
removed_at: datetime | None = None
# Migration tracking
replacement: str = "" # What replaces this component
migration_notes: str = ""
@classmethod
def create(
cls,
component_name: str,
component_path: str,
reason: str,
known_consumers: list[str] | None = None,
replacement: str = "",
) -> DeprecationEntry:
return cls(
entry_id=uuid4(),
component_name=component_name,
component_path=component_path,
status=DeprecationStatus.DEPRECATED,
deprecated_at=datetime.now(timezone.utc),
reason=reason,
known_consumers=known_consumers or [],
replacement=replacement,
)
@property
def migration_progress(self) -> float:
"""Fraction of consumers that have migrated (0.0-1.0)."""
if not self.known_consumers:
return 1.0
return len(self.migrated_consumers) / len(self.known_consumers)
@property
def all_consumers_migrated(self) -> bool:
"""Whether all known consumers have migrated."""
return set(self.known_consumers) <= set(self.migrated_consumers)
def mark_consumer_migrated(self, consumer: str) -> None:
"""Record that a consumer has migrated off this component."""
if consumer not in self.migrated_consumers:
self.migrated_consumers.append(consumer)
if self.all_consumers_migrated:
self.status = DeprecationStatus.MIGRATION_COMPLETE
def approve_removal(self, approver: str) -> bool:
"""Approve removal. Only valid if all consumers migrated.
Returns False if removal cannot be approved.
"""
if not self.all_consumers_migrated:
return False
self.removal_approved = True
self.removal_approver = approver
return True
def mark_removed(self) -> None:
"""Record that the component has been removed from code."""
self.status = DeprecationStatus.REMOVED
self.removed_at = datetime.now(timezone.utc)
def archive(self) -> None:
"""Archive after final migration reports preserved."""
self.status = DeprecationStatus.ARCHIVED
# Default deprecation entries for the v3 migration
DEFAULT_DEPRECATIONS: list[dict[str, Any]] = [
{
"component_name": "VLLMClient",
"component_path": "services/extractor/vllm_client.py",
"reason": "Replaced by OpenAICompatibleClient via inference gateway",
"known_consumers": [
"services/extractor/llm_factory.py",
"services/extractor/worker.py",
],
"replacement": "services/shared/inference/clients/openai_compatible.py",
},
{
"component_name": "v2_extraction_prompt",
"component_path": "services/extractor/prompts.py",
"reason": "Monolithic prompt replaced by staged specialist extraction",
"known_consumers": [
"services/extractor/worker.py",
],
"replacement": "services/intelligence_pipeline_v3/adjudication/",
},
{
"component_name": "provider_branching",
"component_path": "services/extractor/llm_factory.py",
"reason": "Duplicated if/else provider branching replaced by registry",
"known_consumers": [
"services/extractor/worker.py",
"services/recommendation/thesis_llm.py",
],
"replacement": "services/shared/inference/registry.py",
},
{
"component_name": "8000_char_truncation",
"component_path": "services/extractor/prompts.py",
"reason": "Truncation replaced by sentence-aware segmenter",
"known_consumers": [
"services/extractor/prompts.py",
],
"replacement": "services/intelligence_pipeline_v3/segmenter/",
},
{
"component_name": "compatibility_adapter",
"component_path": "services/intelligence_pipeline_v3/compatibility/",
"reason": "Temporary adapter removed after all consumers read v3 natively",
"known_consumers": [
"services/aggregation/worker.py",
"services/recommendation/",
"services/query_api/",
],
"replacement": "Direct v3 intelligence records",
},
]
@dataclass
class MigrationReport:
"""Summary report of the deprecation/migration status."""
generated_at: datetime
total_components: int = 0
deprecated: int = 0
migration_complete: int = 0
removed: int = 0
blocked_removals: list[str] = field(default_factory=list)
@classmethod
def generate(cls, entries: list[DeprecationEntry]) -> MigrationReport:
report = cls(
generated_at=datetime.now(timezone.utc),
total_components=len(entries),
)
for entry in entries:
if entry.status == DeprecationStatus.DEPRECATED:
report.deprecated += 1
if not entry.all_consumers_migrated:
remaining = set(entry.known_consumers) - set(
entry.migrated_consumers
)
report.blocked_removals.append(
f"{entry.component_name}: waiting on {list(remaining)}"
)
elif entry.status == DeprecationStatus.MIGRATION_COMPLETE:
report.migration_complete += 1
elif entry.status in (
DeprecationStatus.REMOVED,
DeprecationStatus.ARCHIVED,
):
report.removed += 1
return report
def to_dict(self) -> dict[str, Any]:
return {
"generated_at": self.generated_at.isoformat(),
"total_components": self.total_components,
"deprecated": self.deprecated,
"migration_complete": self.migration_complete,
"removed": self.removed,
"blocked_removals": self.blocked_removals,
}
@dataclass
class DeprecationTracker:
"""Tracks all deprecated components and their migration status.
Enforces that removal only happens after all consumers migrate
and with explicit approval.
"""
_entries: dict[str, DeprecationEntry] = field(default_factory=dict)
def add(self, entry: DeprecationEntry) -> None:
"""Register a deprecated component."""
self._entries[entry.component_name] = entry
def get(self, component_name: str) -> DeprecationEntry | None:
return self._entries.get(component_name)
def mark_migrated(self, component_name: str, consumer: str) -> bool:
"""Record a consumer migration. Returns False if component not found."""
entry = self._entries.get(component_name)
if entry is None:
return False
entry.mark_consumer_migrated(consumer)
return True
def can_remove(self, component_name: str) -> bool:
"""Check if a component can be safely removed."""
entry = self._entries.get(component_name)
if entry is None:
return False
return entry.all_consumers_migrated and entry.removal_approved
def approve_removal(self, component_name: str, approver: str) -> bool:
"""Approve removal of a component."""
entry = self._entries.get(component_name)
if entry is None:
return False
return entry.approve_removal(approver)
def generate_report(self) -> MigrationReport:
"""Generate a migration status report."""
return MigrationReport.generate(list(self._entries.values()))
@property
def all_entries(self) -> list[DeprecationEntry]:
return list(self._entries.values())
@property
def pending_removals(self) -> list[DeprecationEntry]:
"""Entries that are ready for removal (migrated + approved)."""
return [
e
for e in self._entries.values()
if e.all_consumers_migrated
and e.removal_approved
and e.status != DeprecationStatus.REMOVED
]