Files
Celes Renata a72f336ad1 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.
2026-07-13 02:14:59 +00:00

110 lines
3.7 KiB
Python

"""Inference client factory with protocol alias resolution.
Replaces the legacy VLLMClient/OllamaClient fallback pattern with a
capability-aware routing layer. Unknown protocols ALWAYS fail closed —
they never silently fall back to Ollama.
Requirements: 2.2, 2.6
Design: Inference Gateway — profiles and capability probes
"""
from __future__ import annotations
import warnings
from services.shared.inference.clients.ollama_native import OllamaNativeClient
from services.shared.inference.clients.openai_compatible import OpenAICompatibleClient
from services.shared.inference.errors import InferenceError, InferenceErrorCategory
from services.shared.inference.models import InferenceTarget
# Backward-compatible protocol aliases.
# "vllm" is retained as a deprecated alias for "openai_chat".
# "ollama" is retained as an alias for "ollama_native".
PROTOCOL_ALIASES: dict[str, str] = {
"vllm": "openai_chat",
"ollama": "ollama_native",
}
# Canonical protocol names that the factory can instantiate.
KNOWN_PROTOCOLS: frozenset[str] = frozenset({
"openai_chat",
"ollama_native",
"specialist_http",
})
def resolve_protocol(provider_name: str) -> str:
"""Resolve a protocol name or alias to a canonical protocol.
Raises InferenceError(CAPABILITY_UNAVAILABLE) for unknown protocols.
Emits a deprecation warning for the deprecated "vllm" alias.
Args:
provider_name: Raw protocol/provider string (e.g. "vllm", "ollama_native").
Returns:
Canonical protocol string.
Raises:
InferenceError: If the protocol is unknown and cannot be resolved.
"""
normalized = provider_name.strip().lower()
# Check if it's already a known canonical protocol
if normalized in KNOWN_PROTOCOLS:
return normalized
# Check aliases
if normalized in PROTOCOL_ALIASES:
canonical = PROTOCOL_ALIASES[normalized]
if normalized == "vllm":
warnings.warn(
"Provider 'vllm' is deprecated. Use protocol 'openai_chat' instead. "
"The 'vllm' alias will be removed in a future version.",
DeprecationWarning,
stacklevel=2,
)
return canonical
# Unknown protocol — fail closed, NEVER fall back to Ollama
raise InferenceError(
InferenceErrorCategory.CAPABILITY_UNAVAILABLE,
f"Unknown protocol: {normalized!r}. "
f"Supported protocols: {sorted(KNOWN_PROTOCOLS)}. "
f"Supported aliases: {sorted(PROTOCOL_ALIASES.keys())}.",
)
def create_client(
target: InferenceTarget,
) -> OpenAICompatibleClient | OllamaNativeClient:
"""Create the appropriate inference client for the given target.
Routes based on the target's protocol field. If the protocol is an alias
(e.g. "vllm"), it is resolved first. Unknown protocols raise a typed
configuration error — they NEVER silently fall back to Ollama.
Args:
target: Fully resolved inference target with protocol, URL, etc.
Returns:
An OpenAICompatibleClient or OllamaNativeClient instance.
Raises:
InferenceError: If the protocol is unknown or unsupported.
"""
protocol = resolve_protocol(target.protocol)
if protocol == "openai_chat":
return OpenAICompatibleClient(target)
if protocol == "ollama_native":
return OllamaNativeClient(target)
# specialist_http is a valid protocol but has no client implementation yet
# (handled by a separate specialist service layer). Fail closed here.
raise InferenceError(
InferenceErrorCategory.CAPABILITY_UNAVAILABLE,
f"Protocol {protocol!r} is recognized but has no client implementation in this factory. "
f"Use the specialist HTTP service layer directly.",
)