diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..03d3bde Binary files /dev/null and b/.DS_Store differ diff --git a/ai_service/api.py b/ai_service/api.py index 8c7f472..a05d250 100644 --- a/ai_service/api.py +++ b/ai_service/api.py @@ -11,6 +11,7 @@ from typing import List, Optional from ai_service.models.model_service import model_service from ai_service.models.chat_service import chat_service from ai_service.openwebui_api import router as openwebui_router +from ai_service.config import config # Create FastAPI app app = FastAPI( @@ -107,6 +108,52 @@ async def health_check(): """ return {"status": "healthy"} +@app.get("/test-ollama") +async def test_ollama_connection(): + """ + Test the connection to the Ollama API. + + Returns: + Connection status and available models from Ollama. + """ + import requests + + try: + # Try to connect to Ollama API + response = requests.get(f"{config.OLLAMA_API_URL}/api/tags", timeout=5) + response.raise_for_status() + + # Return the models from Ollama + return { + "status": "success", + "message": "Successfully connected to Ollama API", + "ollama_url": config.OLLAMA_API_URL, + "models": response.json() + } + except Exception as e: + return { + "status": "error", + "message": f"Failed to connect to Ollama API: {str(e)}", + "ollama_url": config.OLLAMA_API_URL + } + +@app.get("/config") +async def get_config(): + """ + Get the current configuration. + + Returns: + Current configuration settings. + """ + return { + "api_host": config.API_HOST, + "api_port": config.API_PORT, + "openwebui_url": config.OPENWEBUI_URL, + "ollama_api_url": config.OLLAMA_API_URL, + "default_model": config.DEFAULT_MODEL, + "available_models": list(model_service.AVAILABLE_MODELS.keys()) + } + # Model endpoints @@ -118,7 +165,10 @@ async def get_available_models(): Returns: List of model information. """ - return model_service.get_available_models() + models = model_service.get_available_models() + # Debug log + print(f"API models: {models}") + return models @app.get("/models/{model_id}", response_model=ModelInfo) async def get_model_info(model_id: str): diff --git a/ai_service/config.py b/ai_service/config.py index f0cd7fc..b9f3c8f 100644 --- a/ai_service/config.py +++ b/ai_service/config.py @@ -22,7 +22,7 @@ class Config: OPENWEBUI_API_KEY = os.environ.get('OPENWEBUI_API_KEY', '') # Ollama configuration - OLLAMA_API_URL = os.environ.get('OLLAMA_API_URL', 'http://104.225.217.215:11434') + OLLAMA_API_URL = os.environ.get('OLLAMA_API_URL', 'http://127.0.0.1:11434') DEFAULT_MODEL = os.environ.get('DEFAULT_MODEL', 'llama3.1') # Document processing diff --git a/ai_service/models/model_service.py b/ai_service/models/model_service.py index 61e108a..7f91804 100644 --- a/ai_service/models/model_service.py +++ b/ai_service/models/model_service.py @@ -3,6 +3,7 @@ Service for model management and interaction. """ import requests +import json from typing import List, Dict, Any, Optional from ai_service.config import config @@ -68,6 +69,21 @@ class ModelService: } models.append(model_data) + # Debug log + print(f"Model service models: {models}") + + # Ensure we're returning a non-empty list + if not models: + # Return a default model if none are found + return [{ + 'id': 'llama3.1', + 'name': 'Llama 3 (8B)', + 'description': 'Meta Llama 3 8B model via Ollama', + 'provider': 'ollama', + 'max_tokens': 8192, + 'is_default': True + }] + return models def get_model_info(self, model_id: str) -> Optional[Dict[str, Any]]: @@ -106,8 +122,17 @@ class ModelService: Returns: Generated response. """ + # Debug configuration information + print(f"ModelService configuration:") + print(f" - Ollama API URL: {self.ollama_api_url}") + print(f" - OpenWebUI URL: {self.openwebui_url}") + print(f" - Default model: {self.default_model}") + print(f" - Requested model: {model_id}") + print(f" - Using RAG: {use_rag}") + if model_id not in self.AVAILABLE_MODELS: model_id = self.default_model + print(f" - Model not found, using default: {model_id}") # Ensure we're using a valid model # (model_id is already validated above) @@ -158,6 +183,11 @@ class ModelService: if self.openwebui_api_key: headers["Authorization"] = f"Bearer {self.openwebui_api_key}" + # Debug logs + print(f"Sending RAG request to OpenWebUI at: {self.openwebui_url}/api/chat/completions") + print(f"OpenWebUI request: {json.dumps(openwebui_request, indent=2)}") + print(f"Headers: {headers}") + # OpenWebUI API endpoint is /api/chat/completions response = requests.post( f"{self.openwebui_url}/api/chat/completions", @@ -213,6 +243,9 @@ class ModelService: headers = {"Content-Type": "application/json"} # Direct Ollama API call + print(f"Sending request to Ollama API at: {self.ollama_api_url}/api/chat") + print(f"Request JSON: {json.dumps(request_json, indent=2)}") + response = requests.post( f"{self.ollama_api_url}/api/chat", headers={"Content-Type": "application/json"}, diff --git a/ai_service/openwebui_api.py b/ai_service/openwebui_api.py index 3b5801e..6cdeaed 100644 --- a/ai_service/openwebui_api.py +++ b/ai_service/openwebui_api.py @@ -23,7 +23,7 @@ async def get_models(): Get available models in OpenWebUI-compatible format. """ models = model_service.get_available_models() - + # Convert to OpenWebUI format openwebui_models = [] for model in models: @@ -36,7 +36,23 @@ async def get_models(): "root": model["id"], "parent": None }) - + + # Debug log + print(f"OpenWebUI models: {json.dumps(openwebui_models, indent=2)}") + + # Ensure we're returning a properly formatted list + if not openwebui_models: + # Return at least one default model if none are found + return [{ + "id": "llama3.1", + "object": "model", + "created": int(time.time()), + "owned_by": "user", + "permission": [], + "root": "llama3.1", + "parent": None + }] + return openwebui_models # Chat completions endpoint (OpenAI-compatible) @@ -47,7 +63,7 @@ async def chat_completions(request: Request): """ # Parse request body body = await request.json() - + # Extract parameters model_id = body.get("model", "llama3.1") messages = body.get("messages", []) @@ -58,26 +74,26 @@ async def chat_completions(request: Request): frequency_penalty = body.get("frequency_penalty") presence_penalty = body.get("presence_penalty") stop = body.get("stop") - + # Create a unique chat ID chat_id = str(uuid.uuid4()) - + # Create a user ID (in a real implementation, this would come from authentication) user_id = "openwebui-user" - + # Create a new chat chat_service.create_chat(user_id=user_id, title="API Chat", model_id=model_id) - + # Extract the user's message (last user message in the array) user_message = None for msg in reversed(messages): if msg.get("role") == "user": user_message = msg.get("content") break - + if not user_message: raise HTTPException(status_code=400, detail="No user message found") - + # Get chat response response = chat_service.get_chat_response( chat_id=chat_id, @@ -90,10 +106,10 @@ async def chat_completions(request: Request): presence_penalty=presence_penalty, stop_sequences=stop if isinstance(stop, list) else [stop] if stop else None ) - + # Format response in OpenAI-compatible format completion_id = f"chatcmpl-{str(uuid.uuid4())[:8]}" - + openai_response = { "id": completion_id, "object": "chat.completion", @@ -115,16 +131,16 @@ async def chat_completions(request: Request): "total_tokens": -1 } } - + # Handle streaming if requested if stream: async def generate_stream(): # Yield the response in the SSE format yield f"data: {json.dumps(openai_response)}\n\n" yield "data: [DONE]\n\n" - + return StreamingResponse(generate_stream(), media_type="text/event-stream") - + return openai_response # Health check endpoint @@ -143,27 +159,27 @@ async def ollama_generate(request: Request): """ # Parse request body body = await request.json() - + # Extract parameters model_id = body.get("model", "llama3.1") prompt = body.get("prompt", "") - + # Create a unique chat ID chat_id = str(uuid.uuid4()) - + # Create a user ID (in a real implementation, this would come from authentication) user_id = "openwebui-user" - + # Create a new chat chat_service.create_chat(user_id=user_id, title="API Chat", model_id=model_id) - + # Get chat response response = chat_service.get_chat_response( chat_id=chat_id, message=prompt, user_id=user_id ) - + # Format response in Ollama-compatible format ollama_response = { "model": model_id, @@ -171,5 +187,5 @@ async def ollama_generate(request: Request): "response": response.get("content", ""), "done": True } - + return ollama_response