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.
110 lines
3.7 KiB
Python
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.",
|
|
)
|