mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-24 05:35:31 -04:00
e0ccf250a4
* feat(discovery): detect llama.cpp servers and label local providers Scan port 8080 (llama-server) and 11435 (APFEL) during discovery, fingerprint llama.cpp via its native /props endpoint, and label well-known local serving ports (8080 llama.cpp, 8000 vLLM, 1234 LM Studio, 11434 Ollama) consistently in both the Python provider helper and the JS endpoint UI. Adds a llama.cpp hint to the /setup slash command. * fix(discovery): don't infer the serving tool from the port alone Per review: vLLM, SGLang, llama.cpp and plain OpenAI-compatible servers all share 8000/8080, so labeling by port mislabels real setups (a vLLM box on 8080 shown as llama.cpp). Drop the port->tool assertions from _provider_label and providerLabel; the authoritative signal is the /props fingerprint done during discovery, which is unchanged. Loopback now reads a neutral 'local endpoint' / 'Local'. Tests updated to assert the neutral labels.
116 lines
5.1 KiB
Python
116 lines
5.1 KiB
Python
"""Provider classification from a base URL (REAL src.llm_core).
|
|
|
|
ROADMAP "Backend → more tests around ... provider setup" and "Provider
|
|
setup/probing audit for Anthropic, Gemini, Groq, xAI, OpenRouter, OpenAI, and
|
|
DeepSeek". `test_provider_endpoints.py` already pins URL/header *building*; this
|
|
module pins the two pieces of provider setup that decide WHICH provider an
|
|
endpoint is:
|
|
|
|
* `_detect_provider` — host-based provider identification (drives payload
|
|
shape, auth headers, and the /v1 collapse). The look-alike-host and
|
|
domain-in-path cases guard the hostname (not substring) matching.
|
|
* `_provider_label` — the human name shown in degraded-state messages.
|
|
|
|
Upstream-error formatting lives in `test_provider_classification_errors.py` and
|
|
the token-param quirk in `test_provider_classification_token_params.py`.
|
|
|
|
conftest.py stubs the heavy deps (sqlalchemy, src.database), so importing the
|
|
real module is side-effect free.
|
|
"""
|
|
import pytest
|
|
|
|
from src.llm_core import (
|
|
_detect_provider,
|
|
_provider_label,
|
|
)
|
|
|
|
|
|
# ── _detect_provider ──
|
|
# Matches on hostname (exact or subdomain), never substring, and falls back to
|
|
# the OpenAI-compatible default for everything it doesn't special-case.
|
|
|
|
class TestDetectProvider:
|
|
@pytest.mark.parametrize("url,expected", [
|
|
("https://api.anthropic.com", "anthropic"),
|
|
("https://api.anthropic.com/v1", "anthropic"),
|
|
("https://anthropic.com/v1", "anthropic"),
|
|
("https://openrouter.ai/api/v1", "openrouter"),
|
|
("https://api.groq.com/openai/v1", "groq"),
|
|
("https://integrate.api.nvidia.com/v1", "nvidia"),
|
|
("http://localhost:11434/api", "ollama"),
|
|
("https://ollama.com", "ollama"),
|
|
# xAI, DeepSeek and Gemini's OpenAI-compatible surface are NOT
|
|
# special-cased — they speak the OpenAI dialect, so the generic
|
|
# "openai" path is correct, not a missed provider.
|
|
("https://api.openai.com/v1", "openai"),
|
|
("https://api.x.ai/v1", "openai"),
|
|
("https://api.deepseek.com", "openai"),
|
|
("https://generativelanguage.googleapis.com/v1beta/openai", "openai"),
|
|
# Ollama's OpenAI-compatible /v1 surface is generic, not native ollama.
|
|
("http://localhost:11434/v1", "openai"),
|
|
])
|
|
def test_known_providers(self, url, expected):
|
|
assert _detect_provider(url) == expected
|
|
|
|
def test_lookalike_host_is_not_matched(self):
|
|
# Host merely *starts* with the provider domain as a label — a classic
|
|
# substring-match trap (anthropic.com.evil.example is not Anthropic).
|
|
assert _detect_provider("https://anthropic.com.evil.example/v1") == "openai"
|
|
|
|
def test_provider_domain_in_path_is_not_matched(self):
|
|
# The provider domain appears only in the path, not the host.
|
|
assert _detect_provider("https://proxy.example.com/anthropic.com/v1") == "openai"
|
|
|
|
def test_trailing_dot_host_still_matches(self):
|
|
# A fully-qualified host with a trailing dot is still that host.
|
|
assert _detect_provider("https://api.anthropic.com./v1") == "anthropic"
|
|
|
|
@pytest.mark.parametrize("url", ["", None, "not a url", "://broken"])
|
|
def test_unidentifiable_falls_back_to_openai(self, url):
|
|
assert _detect_provider(url) == "openai"
|
|
|
|
|
|
# ── _provider_label ──
|
|
# Human-friendly name used in error/degraded-state messages.
|
|
|
|
class TestProviderLabel:
|
|
@pytest.mark.parametrize("url,expected", [
|
|
("https://api.anthropic.com/v1", "Anthropic"),
|
|
("https://ollama.com", "Ollama Cloud"),
|
|
("https://api.x.ai/v1", "xAI"),
|
|
("https://api.openai.com/v1", "OpenAI"),
|
|
("https://openrouter.ai/api/v1", "OpenRouter"),
|
|
("https://api.groq.com/openai/v1", "Groq"),
|
|
("https://integrate.api.nvidia.com/v1", "NVIDIA"),
|
|
("https://api.mistral.ai/v1", "Mistral"),
|
|
("https://api.deepseek.com", "DeepSeek"),
|
|
("https://generativelanguage.googleapis.com/v1beta/openai", "Google"),
|
|
("https://api.together.xyz/v1", "Together"),
|
|
("https://api.together.ai/v1", "Together"),
|
|
("https://api.fireworks.ai/inference/v1", "Fireworks"),
|
|
("http://localhost:11434/api", "Ollama"),
|
|
])
|
|
def test_known_labels(self, url, expected):
|
|
assert _provider_label(url) == expected
|
|
|
|
@pytest.mark.parametrize("url", [
|
|
"http://localhost:8080/v1",
|
|
"http://127.0.0.1:8080/v1",
|
|
"http://localhost:8000/v1",
|
|
"http://localhost:1234/v1",
|
|
"http://localhost:9999/v1",
|
|
])
|
|
def test_local_non_ollama_endpoint(self, url):
|
|
# The serving tool is NOT inferred from the port: vLLM, SGLang, llama.cpp
|
|
# and plain OpenAI-compatible servers all share 8000/8080, so a port-only
|
|
# label would mislabel real setups. The tool is identified by /props
|
|
# fingerprinting during discovery; this helper stays neutral.
|
|
assert _provider_label(url) == "local endpoint"
|
|
|
|
def test_unknown_host_returns_host(self):
|
|
assert _provider_label("https://api.unknown-llm.example/v1") == "api.unknown-llm.example"
|
|
|
|
@pytest.mark.parametrize("url", ["", None])
|
|
def test_empty_returns_generic(self, url):
|
|
assert _provider_label(url) == "provider"
|