how to boot

import os
import sys
import uuid
import logging
from typing import Dict, List, Optional
from contextlib import asynccontextmanager

from fastapi import FastAPI, HTTPException, Form
from pydantic import BaseModel
from ollama import AsyncClient, ResponseError
import uvicorn

# Configure root logger for DEBUG output
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s %(name)s %(levelname)s %(message)s',
    stream=sys.stdout,
)

logger = logging.getLogger("uvicorn.error")

OLLAMA_API_URL = os.getenv("OLLAMA_API_URL", "http://localhost:11434")
DEFAULT_MODEL = "llama3.2"

app = FastAPI()

class Message(BaseModel):
    role: str
    content: str

class ChatRequest(BaseModel):
    model: Optional[str] = None
    message: str  # only the latest user message sent
    session_id: Optional[str] = None  # optional client-provided session id

# In-memory store for chat history keyed by session_id
# WARNING: ephemeral — lost on server restart
chat_histories: Dict[str, List[Dict[str, str]]] = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    client = AsyncClient(host=OLLAMA_API_URL)
    try:
        logger.debug(f"Attempting connection to Ollama API at {OLLAMA_API_URL} with model '{DEFAULT_MODEL}'")
        await client.chat(model=DEFAULT_MODEL, messages=[{"role": "user", "content": "ping"}], stream=False)
        logger.info(f"Connected to Ollama API at {OLLAMA_API_URL} with model '{DEFAULT_MODEL}' successfully")
    except Exception as e:
        logger.error(f"Failed to connect to Ollama API at {OLLAMA_API_URL} with model '{DEFAULT_MODEL}': {e}", exc_info=True)
    yield

app.router.lifespan_context = lifespan

@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
    model = request.model or DEFAULT_MODEL
    client = AsyncClient(host=OLLAMA_API_URL)

    # Obtain or create a session ID
    session_id = request.session_id or str(uuid.uuid4())
    if session_id not in chat_histories:
        chat_histories[session_id] = []

    # Append user's new message to the chat history
    chat_histories[session_id].append({"role": "user", "content": request.message})

    logger.debug(f"Session ID: {session_id}")
    logger.debug(f"Model: {model}")
    logger.debug(f"Current chat history ({len(chat_histories[session_id])} messages): {chat_histories[session_id]}")

    try:
        response = await client.chat(
            model=model,
            messages=chat_histories[session_id],
            stream=False,
        )

        assistant_message = response["message"]["content"]
        logger.debug(f"Assistant reply: {assistant_message}")

        # Append assistant reply to the chat history
        chat_histories[session_id].append({"role": "assistant", "content": assistant_message})

        return {
            "session_id": session_id,
            "reply": assistant_message,
        }

    except ResponseError as e:
        logger.error(f"Ollama ResponseError: {e.status_code} {e.content}")
        raise HTTPException(status_code=e.status_code, detail=e.content)

    except Exception as e:
        logger.error(f"Unexpected Ollama API error: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    # Replace 'your_script_name' with the actual filename if not 'main.py'
    uvicorn.run("your_script_name:app", host="0.0.0.0", port=8784, log_level="debug", reload=True)