import httpx import logging logger = logging.getLogger(__name__) def generate(prompt: str, system: str, config: dict) -> str: host = config.get("ollama_host", "192.168.2.10") port = config.get("ollama_port", 11434) model = config.get("ollama_model", "llama3.1") timeout = config.get("response_timeout_seconds", 30) num_predict = config.get("ollama_num_predict", 120) num_ctx = config.get("ollama_num_ctx", 2048) temperature = config.get("ollama_temperature", 0.7) max_length = config.get("max_response_length", 400) url = f"http://{host}:{port}/api/generate" payload = { "model": model, "system": system, "prompt": prompt, "stream": False, "options": { "temperature": temperature, "num_predict": num_predict, "num_ctx": num_ctx, }, } logger.debug(f"[LLM] POST {url} model={model} prompt_len={len(prompt)}") try: response = httpx.post(url, json=payload, timeout=timeout) response.raise_for_status() text = response.json().get("response", "").strip() if len(text) > max_length: text = text[:max_length].rsplit(" ", 1)[0] + "…" logger.debug(f"[LLM] Response ({len(text)} chars): {text[:80]}") return text except httpx.TimeoutException: logger.error(f"[LLM] Timeout after {timeout}s") raise TimeoutError(f"Ollama did not respond within {timeout}s") except Exception as e: logger.error(f"[LLM] Request failed: {e}") raise def build_prompt( user_message: str, nick: str, persistent_history: list[dict], context_buffer: list[str], ) -> str: parts = [] if persistent_history: parts.append("--- Past conversation with this user ---") for ex in persistent_history: parts.append(f"User: {ex['user']}") parts.append(f"Assistant: {ex['assistant']}") parts.append("--- End of past conversation ---") if context_buffer: parts.append("--- Recent channel activity ---") parts.extend(context_buffer) parts.append("--- End of channel activity ---") parts.append(f"{nick} asks: {user_message}") return "\n".join(parts)