- deepseek-v4-flash su opencode/go come modello primario - big-pickle su opencode/zen come fallback (gratuito) - Fallback automatico su censura "User Safety" o errore HTTP - Aggiornati .env, config.py, start.sh, docker-compose.yml
This commit is contained in:
1 parent
ffeb199ef5
commit
90ba835868
4 files changed
+38
-10
No files matched your search
+4
-2
@@ -14,8 +14,10 @@ services:
|
||||
- DCC_OPENROUTER_MODEL=${DCC_OPENROUTER_MODEL:-openrouter/free}
|
||||
- DCC_OLLAMA_URL=${DCC_OLLAMA_URL:-http://192.168.0.50:11434}
|
||||
- DCC_OLLAMA_MODEL=${DCC_OLLAMA_MODEL:-gemma2:9b}
|
||||
- DCC_LOCAL_URL=${DCC_LOCAL_URL:-https://opencode.ai/zen/v1}
|
||||
- DCC_LOCAL_URL=${DCC_LOCAL_URL:-https://opencode.ai/zen/go/v1}
|
||||
- DCC_LOCAL_KEY=${DCC_LOCAL_KEY:-}
|
||||
- DCC_LOCAL_MODEL=${DCC_LOCAL_MODEL:-big-pickle}
|
||||
- DCC_LOCAL_MODEL=${DCC_LOCAL_MODEL:-deepseek-v4-flash}
|
||||
- DCC_LOCAL_FALLBACK_URL=${DCC_LOCAL_FALLBACK_URL:-https://opencode.ai/zen/v1}
|
||||
- DCC_LOCAL_FALLBACK_MODEL=${DCC_LOCAL_FALLBACK_MODEL:-big-pickle}
|
||||
- DCC_LLM_TIMEOUT=${DCC_LLM_TIMEOUT:-120}
|
||||
restart: unless-stopped
|
||||
@@ -18,19 +18,23 @@ class ProviderConfig:
|
||||
local_base_url: str = "https://opencode.ai/zen/go/v1"
|
||||
local_api_key: str = ""
|
||||
local_model: str = "deepseek-v4-flash"
|
||||
local_fallback_url: str = "https://opencode.ai/zen/v1"
|
||||
local_fallback_model: str = "big-pickle"
|
||||
timeout: int = 120
|
||||
|
||||
|
||||
def load_from_env() -> ProviderConfig:
|
||||
return ProviderConfig(
|
||||
kind=os.getenv("DCC_LLM_PROVIDER", "openrouter"), # type: ignore
|
||||
kind=os.getenv("DCC_LLM_PROVIDER", "local"), # type: ignore
|
||||
ollama_base_url=os.getenv("DCC_OLLAMA_URL", "http://192.168.0.50:11434"),
|
||||
ollama_model=os.getenv("DCC_OLLAMA_MODEL", "gemma2:9b"),
|
||||
openrouter_api_key=os.getenv("DCC_OPENROUTER_KEY", os.getenv("OPENROUTER_API_KEY", "")),
|
||||
openrouter_model=os.getenv("DCC_OPENROUTER_MODEL", "openrouter/free"),
|
||||
openrouter_free_fallback=os.getenv("DCC_OR_FREE_FALLBACK", "1") == "1",
|
||||
local_base_url=os.getenv("DCC_LOCAL_URL", "http://192.168.0.240/v1"),
|
||||
local_base_url=os.getenv("DCC_LOCAL_URL", "https://opencode.ai/zen/v1"),
|
||||
local_api_key=os.getenv("DCC_LOCAL_KEY", ""),
|
||||
local_model=os.getenv("DCC_LOCAL_MODEL", "big-pickle"),
|
||||
timeout=int(os.getenv("DCC_LLM_TIMEOUT", "60")),
|
||||
local_fallback_url=os.getenv("DCC_LOCAL_FALLBACK_URL", "https://opencode.ai/zen/go/v1"),
|
||||
local_fallback_model=os.getenv("DCC_LOCAL_FALLBACK_MODEL", "deepseek-v4-flash"),
|
||||
timeout=int(os.getenv("DCC_LLM_TIMEOUT", "120")),
|
||||
)
|
||||
+25
-5
@@ -84,13 +84,15 @@ class OpenRouterProvider(LLMProvider):
|
||||
|
||||
|
||||
class LocalProvider(LLMProvider):
|
||||
def __init__(self, base_url: str, model: str, api_key: str = "", timeout: int = 60):
|
||||
def __init__(self, base_url: str, model: str, api_key: str = "",
|
||||
timeout: int = 60, fallbacks: list[tuple[str, str]] | None = None):
|
||||
self.base_url = base_url.rstrip("/")
|
||||
self.model = model
|
||||
self.api_key = api_key
|
||||
self.timeout = timeout
|
||||
self.fallbacks = fallbacks or []
|
||||
|
||||
def ask(self, prompt: str, system: str = "") -> str:
|
||||
def _call(self, base_url: str, model: str, prompt: str, system: str) -> str:
|
||||
messages = []
|
||||
if system:
|
||||
messages.append({"role": "system", "content": system})
|
||||
@@ -100,10 +102,10 @@ class LocalProvider(LLMProvider):
|
||||
if self.api_key:
|
||||
headers["Authorization"] = f"Bearer {self.api_key}"
|
||||
|
||||
body = {"model": self.model, "messages": messages, "stream": False}
|
||||
body = {"model": model, "messages": messages, "stream": False}
|
||||
|
||||
resp = httpx.post(
|
||||
f"{self.base_url}/chat/completions",
|
||||
f"{base_url}/chat/completions",
|
||||
json=body,
|
||||
headers=headers,
|
||||
timeout=self.timeout,
|
||||
@@ -112,6 +114,21 @@ class LocalProvider(LLMProvider):
|
||||
data = resp.json()
|
||||
return data["choices"][0]["message"]["content"]
|
||||
|
||||
def ask(self, prompt: str, system: str = "") -> str:
|
||||
candidates = [(self.base_url, self.model)] + self.fallbacks
|
||||
last_err = None
|
||||
for base_url, model in candidates:
|
||||
try:
|
||||
text = self._call(base_url, model, prompt, system)
|
||||
# Rileva risposte di censura del modello gratuito
|
||||
if "User Safety" in text and "safe" in text.lower():
|
||||
raise ValueError(f"Modello '{model}' ha censurato la risposta: {text[:60]}")
|
||||
return text
|
||||
except Exception as e:
|
||||
last_err = e
|
||||
continue
|
||||
raise last_err # type: ignore
|
||||
|
||||
|
||||
_registry: dict[str, Any] = {
|
||||
"ollama": OllamaProvider,
|
||||
@@ -136,6 +153,9 @@ def create_provider(cfg: ProviderConfig | None = None) -> LLMProvider:
|
||||
raise ValueError("DCC_OPENROUTER_KEY non configurata")
|
||||
return cls(key, cfg.openrouter_model, cfg.timeout, cfg.openrouter_free_fallback)
|
||||
elif cfg.kind == "local":
|
||||
return cls(cfg.local_base_url, cfg.local_model, cfg.local_api_key, cfg.timeout)
|
||||
fallbacks = []
|
||||
if cfg.local_fallback_url and cfg.local_fallback_model:
|
||||
fallbacks.append((cfg.local_fallback_url, cfg.local_fallback_model))
|
||||
return cls(cfg.local_base_url, cfg.local_model, cfg.local_api_key, cfg.timeout, fallbacks=fallbacks)
|
||||
else:
|
||||
raise ValueError(f"Provider non implementato: {cfg.kind}")
|
||||
@@ -19,6 +19,8 @@ export DCC_OLLAMA_MODEL="${DCC_OLLAMA_MODEL:-gemma2:9b}"
|
||||
export DCC_LOCAL_URL="${DCC_LOCAL_URL:-https://opencode.ai/zen/go/v1}"
|
||||
export DCC_LOCAL_KEY="${DCC_LOCAL_KEY:-}"
|
||||
export DCC_LOCAL_MODEL="${DCC_LOCAL_MODEL:-deepseek-v4-flash}"
|
||||
export DCC_LOCAL_FALLBACK_URL="${DCC_LOCAL_FALLBACK_URL:-https://opencode.ai/zen/v1}"
|
||||
export DCC_LOCAL_FALLBACK_MODEL="${DCC_LOCAL_FALLBACK_MODEL:-big-pickle}"
|
||||
|
||||
# ── create data dir ────────────────────────────────────────────────
|
||||
mkdir -p data
|
||||
|
||||
Reference in new issue
Block a user