feat: add Python core and infra functions — PWA, geocoding, POI matching
Nuevas funciones Python: build_guide_prompt, generate_pwa_manifest, generate_service_worker, match_pois_to_interests (core), nominatim_reverse_geocode, ollama_chat, overpass_nearby_pois (infra). Incluye tests unitarios. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""Envía una solicitud de chat completion a Ollama (API local compatible con OpenAI)."""
|
||||
|
||||
import json
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
from typing import Any
|
||||
|
||||
|
||||
def ollama_chat(
|
||||
messages: list[dict],
|
||||
model: str = "llama3.1:8b",
|
||||
base_url: str = "http://localhost:11434",
|
||||
temperature: float = 0.7,
|
||||
max_tokens: int = 1024,
|
||||
) -> dict:
|
||||
"""Envía una solicitud de chat completion a Ollama.
|
||||
|
||||
Args:
|
||||
messages: Lista de mensajes con formato {"role": "system"|"user"|"assistant", "content": str}.
|
||||
model: Nombre del modelo Ollama a usar.
|
||||
base_url: URL base de la instancia Ollama.
|
||||
temperature: Temperatura de generación (0.0 - 1.0).
|
||||
max_tokens: Número máximo de tokens a generar.
|
||||
|
||||
Returns:
|
||||
Dict con content, model, total_duration_ms y eval_count.
|
||||
|
||||
Raises:
|
||||
RuntimeError: Si Ollama no está corriendo o retorna error HTTP.
|
||||
"""
|
||||
url = f"{base_url}/api/chat"
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": messages,
|
||||
"stream": False,
|
||||
"options": {
|
||||
"temperature": temperature,
|
||||
"num_predict": max_tokens,
|
||||
},
|
||||
}
|
||||
body = json.dumps(payload).encode("utf-8")
|
||||
req = urllib.request.Request(
|
||||
url,
|
||||
data=body,
|
||||
headers={"Content-Type": "application/json"},
|
||||
method="POST",
|
||||
)
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=60) as resp:
|
||||
raw = resp.read()
|
||||
except urllib.error.URLError as exc:
|
||||
reason = str(exc.reason) if hasattr(exc, "reason") else str(exc)
|
||||
if "connection refused" in reason.lower() or "111" in reason:
|
||||
raise RuntimeError(f"Ollama no está corriendo en {base_url}") from exc
|
||||
raise RuntimeError(f"Error de conexión con Ollama: {reason}") from exc
|
||||
except urllib.error.HTTPError as exc:
|
||||
raise RuntimeError(f"Ollama retornó HTTP {exc.code}: {exc.reason}") from exc
|
||||
|
||||
response: dict[str, Any] = json.loads(raw)
|
||||
content: str = response["message"]["content"]
|
||||
total_duration_ns: int = response.get("total_duration", 0)
|
||||
total_duration_ms: int = int(total_duration_ns / 1_000_000)
|
||||
eval_count: int = response.get("eval_count", 0)
|
||||
|
||||
return {
|
||||
"content": content,
|
||||
"model": response.get("model", model),
|
||||
"total_duration_ms": total_duration_ms,
|
||||
"eval_count": eval_count,
|
||||
}
|
||||
Reference in New Issue
Block a user