From 730009ae87e3b94843f504deb375ae9ac26dbc41 Mon Sep 17 00:00:00 2001 From: Iyeoluwa Akinrinola Date: Fri, 16 May 2025 18:03:15 +0100 Subject: [PATCH] fixed team chats --- LOCAL_TESTING_README.md | 160 ++++++++++++++++++ OPENWEBUI_SETUP.md | 12 +- ai_service/.env.example | 4 +- ai_service/api.py | 34 +++- ai_service/models/chat_service.py | 10 ++ create_ssh_tunnel.sh | 76 +++++++++ local_test.env | 18 ++ local_test.env.example | 18 ++ local_test_config.py | 35 ++++ openwebui_config.md | 6 +- setup_local_test_env.sh | 53 ++++++ stop_ssh_tunnels.sh | 29 ++++ test_ai_service.py | 214 ++++++++++++++++++++++++ test_direct_ollama.py | 76 +++++++++ test_ollama_custom.py | 104 ++++++++++++ test_rag.py | 102 ++++++------ test_remote_ollama.py | 165 ++++++++++++++++++ test_simple_team_chat.py | 91 ++++++++++ test_team_chat_mentions.py | 266 ++++++++++++++++++++++++++++++ test_team_chats.py | 243 +++++++++++++++++++++++++++ tunnel_pids.txt | 2 + 21 files changed, 1655 insertions(+), 63 deletions(-) create mode 100644 LOCAL_TESTING_README.md create mode 100755 create_ssh_tunnel.sh create mode 100644 local_test.env create mode 100644 local_test.env.example create mode 100644 local_test_config.py create mode 100755 setup_local_test_env.sh create mode 100755 stop_ssh_tunnels.sh create mode 100755 test_ai_service.py create mode 100755 test_direct_ollama.py create mode 100755 test_ollama_custom.py create mode 100755 test_remote_ollama.py create mode 100755 test_simple_team_chat.py create mode 100755 test_team_chat_mentions.py create mode 100755 test_team_chats.py create mode 100644 tunnel_pids.txt diff --git a/LOCAL_TESTING_README.md b/LOCAL_TESTING_README.md new file mode 100644 index 0000000..377bbf8 --- /dev/null +++ b/LOCAL_TESTING_README.md @@ -0,0 +1,160 @@ +# Local Testing with Remote Server Resources + +This guide explains how to set up local testing that connects to remote server resources for the chatbot project. + +## Overview + +These scripts allow you to: + +1. Test the connection to the remote Ollama server +2. Create SSH tunnels to access remote resources locally +3. Run tests against the remote Ollama models from your local machine + +## Setup Instructions + +### 1. Initial Setup + +Run the setup script to create a virtual environment and install dependencies: + +```bash +chmod +x setup_local_test_env.sh +./setup_local_test_env.sh +``` + +This will: +- Create a Python virtual environment +- Install required dependencies +- Create a `local_test.env` file from the template + +### 2. Configure Environment Variables + +Edit the `local_test.env` file with your server credentials: + +```bash +# Remote server configuration +SERVER_IP=104.225.217.215 +SERVER_PORT=22 +SERVER_USER=root +SERVER_PASSWORD=your_password_here # Add your actual password + +# Ollama configuration +OLLAMA_API_URL=http://104.225.217.215:11434 + +# OpenWebUI configuration +OPENWEBUI_URL=http://104.225.217.215:8080 +OPENWEBUI_API_KEY=your_openwebui_api_key_here +``` + +### 3. Create SSH Tunnels (Optional) + +If you want to access the remote resources through localhost (recommended for security and to avoid firewall issues), create SSH tunnels: + +```bash +chmod +x create_ssh_tunnel.sh +./create_ssh_tunnel.sh +``` + +This will create SSH tunnels for: +- Ollama API (localhost:11434 → remote:11434) +- OpenWebUI (localhost:8080 → remote:8080) + +If you use SSH tunnels, update your `local_test.env` file to use localhost URLs: + +```bash +# Ollama configuration +OLLAMA_API_URL=http://localhost:11434 + +# OpenWebUI configuration +OPENWEBUI_URL=http://localhost:8080 +``` + +### 4. Run Tests + +Activate the virtual environment and run the test script: + +```bash +source venv/bin/activate +python test_remote_ollama.py +``` + +#### Test Options + +You can customize the test with command-line arguments: + +```bash +# Test with a specific model +python test_remote_ollama.py --model llama3.3 + +# Test with a custom prompt +python test_remote_ollama.py --prompt "Explain quantum computing" + +# Test with a different Ollama URL +python test_remote_ollama.py --ollama-url http://your-server-ip:11434 + +# Test with a different timeout +python test_remote_ollama.py --timeout 600 +``` + +### 5. Stop SSH Tunnels + +When you're done testing, stop the SSH tunnels: + +```bash +chmod +x stop_ssh_tunnels.sh +./stop_ssh_tunnels.sh +``` + +## Troubleshooting + +### Connection Issues + +If you can't connect to the remote server: + +1. Check if the server is reachable: + ```bash + ping 104.225.217.215 + ``` + +2. Verify that Ollama is running on the server: + ```bash + ssh root@104.225.217.215 "curl http://localhost:11434/api/tags" + ``` + +3. Check if there are firewall rules blocking the connection: + ```bash + ssh root@104.225.217.215 "iptables -L" + ``` + +### SSH Tunnel Issues + +If the SSH tunnels aren't working: + +1. Make sure you have SSH access to the server: + ```bash + ssh root@104.225.217.215 + ``` + +2. Check if the ports are already in use: + ```bash + netstat -tuln | grep 11434 + netstat -tuln | grep 8080 + ``` + +3. Try creating the tunnels manually: + ```bash + ssh -N -L 11434:localhost:11434 root@104.225.217.215 + ``` + +## Advanced Usage + +### Testing with OpenWebUI's RAG Capabilities + +To test document-based question answering using OpenWebUI's knowledge database: + +```bash +python test_remote_ollama.py --prompt "What information do you have about our project?" --model llama3.1 +``` + +### Integrating with Your Local Development + +You can use these scripts as a foundation for local development that connects to the remote resources. This allows you to develop and test locally while using the remote server's models and data. diff --git a/OPENWEBUI_SETUP.md b/OPENWEBUI_SETUP.md index 54f6081..24bc00f 100644 --- a/OPENWEBUI_SETUP.md +++ b/OPENWEBUI_SETUP.md @@ -9,7 +9,7 @@ OpenWebUI is designed to work with Ollama directly, but it can be configured to ## Prerequisites 1. OpenWebUI installed and running (at http://104.225.217.215:8080) -2. Your AI service deployed and running (at http://your-server-ip:5251) +2. Your AI service deployed and running (at http://your-server-ip:5252) ## Configuration Steps @@ -23,8 +23,8 @@ services: openwebui: image: openwebui/openwebui:latest environment: - - OLLAMA_API_BASE_URL=http://your-server-ip:5251/ollama - - OPENAI_API_BASE_URL=http://your-server-ip:5251/api + - OLLAMA_API_BASE_URL=http://your-server-ip:5252/ollama + - OPENAI_API_BASE_URL=http://your-server-ip:5252/api ports: - "8080:8080" ``` @@ -36,8 +36,8 @@ If you're running OpenWebUI directly, you can modify the .env file in the OpenWe Add or modify the following environment variables: ``` -OLLAMA_API_BASE_URL=http://your-server-ip:5251/ollama -OPENAI_API_BASE_URL=http://your-server-ip:5251/api +OLLAMA_API_BASE_URL=http://your-server-ip:5252/ollama +OPENAI_API_BASE_URL=http://your-server-ip:5252/api ``` Replace `your-server-ip` with the IP address or hostname of the server where your AI service is running. @@ -90,7 +90,7 @@ If you encounter issues with the integration: 3. Verify that your AI service is running and accessible: ```bash - curl http://your-server-ip:5251/health + curl http://your-server-ip:5252/health ``` 4. Verify that the OpenWebUI environment variables are set correctly: diff --git a/ai_service/.env.example b/ai_service/.env.example index 5b297c6..12c9170 100644 --- a/ai_service/.env.example +++ b/ai_service/.env.example @@ -1,7 +1,7 @@ # API configuration API_HOST=0.0.0.0 -API_PORT=5251 -PUBLIC_URL=http://your-public-url:5251 # Public URL for webhooks, needed for OpenWebUI to send channel messages +API_PORT=5252 +PUBLIC_URL=http://your-public-url:5252 # Public URL for webhooks, needed for OpenWebUI to send channel messages # OpenWebUI configuration OPENWEBUI_URL=http://104.225.217.215:8080 diff --git a/ai_service/api.py b/ai_service/api.py index 445cd96..3397046 100644 --- a/ai_service/api.py +++ b/ai_service/api.py @@ -623,15 +623,47 @@ async def channel_message_webhook(request: ChannelMessageWebhook): print("=" * 50) # Find the chat associated with this OpenWebUI channel + print(f"Looking for chat with OpenWebUI channel ID: {request.channel_id}") + print(f"Number of chats in system: {len(chat_service.chats)}") + + # Debug: Print all chats and their channel IDs + print("All chats in the system:") + for cid, chat in chat_service.chats.items(): + is_team = chat.get('is_team_chat', False) + channel_id = chat.get('openwebui_channel_id', 'None') + print(f" Chat ID: {cid}, Is Team Chat: {is_team}, OpenWebUI Channel ID: {channel_id}") + chat_id = None for cid, chat in chat_service.chats.items(): if chat.get('is_team_chat') and chat.get('openwebui_channel_id') == request.channel_id: chat_id = cid + print(f"Found matching chat: {cid}") break if not chat_id: print(f"No chat found for OpenWebUI channel {request.channel_id}") - return {"status": "error", "message": "No chat found for this channel"} + + # If no chat exists for this channel, create one + print("Creating a new team chat for this channel...") + try: + new_chat_id = chat_service.create_chat( + user_id=request.user_id, + title=f"Channel Chat {request.channel_id}", + model_id=config.DEFAULT_MODEL, + is_team_chat=True + ) + + # Manually set the OpenWebUI channel ID for this chat + chat_service.chats[new_chat_id]['openwebui_channel_id'] = request.channel_id + chat_service._save_chats() + + print(f"Created new chat with ID {new_chat_id} for channel {request.channel_id}") + + # Use this new chat + chat_id = new_chat_id + except Exception as e: + print(f"Error creating new chat for channel: {str(e)}") + return {"status": "error", "message": "No chat found for this channel and failed to create one"} # Skip messages from the AI assistant to avoid loops if request.user_id == "ai-assistant": diff --git a/ai_service/models/chat_service.py b/ai_service/models/chat_service.py index 1901c03..c808e82 100644 --- a/ai_service/models/chat_service.py +++ b/ai_service/models/chat_service.py @@ -69,6 +69,11 @@ class ChatService: openwebui_channel_id = None if is_team_chat: try: + print("=" * 50) + print(f"Creating team chat with title: {chat_title}") + print(f"OpenWebUI URL: {openwebui_channels.openwebui_url}") + print(f"OpenWebUI API Key: {openwebui_channels.openwebui_api_key[:5]}..." if openwebui_channels.openwebui_api_key else "No API key") + # Create a channel in OpenWebUI channel_response = openwebui_channels.create_channel( name=chat_title, @@ -76,13 +81,18 @@ class ChatService: is_private=True # Team chats are private by default ) + print(f"Channel response: {json.dumps(channel_response, indent=2) if channel_response else 'None'}") + if channel_response: openwebui_channel_id = channel_response.get('id') print(f"Created OpenWebUI channel with ID: {openwebui_channel_id}") else: print("Failed to create OpenWebUI channel, continuing with local team chat only") + print("=" * 50) except Exception as e: + print("=" * 50) print(f"Error creating OpenWebUI channel: {str(e)}") + print("=" * 50) # Create chat data self.chats[chat_id] = { diff --git a/create_ssh_tunnel.sh b/create_ssh_tunnel.sh new file mode 100755 index 0000000..1a9afa3 --- /dev/null +++ b/create_ssh_tunnel.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# Script to create an SSH tunnel to the remote server + +# Load environment variables from local_test.env +if [ -f "local_test.env" ]; then + source local_test.env +else + echo "Error: local_test.env file not found. Please run setup_local_test_env.sh first." + exit 1 +fi + +# Check if required variables are set +if [ -z "$SERVER_IP" ] || [ -z "$SERVER_PORT" ] || [ -z "$SERVER_USER" ]; then + echo "Error: SERVER_IP, SERVER_PORT, or SERVER_USER not set in local_test.env." + exit 1 +fi + +# Check if password is set +if [ -z "$SERVER_PASSWORD" ]; then + echo "Warning: SERVER_PASSWORD not set in local_test.env. You will be prompted for the password." +fi + +# Function to create SSH tunnel +create_tunnel() { + local local_port=$1 + local remote_port=$2 + + echo "Creating SSH tunnel from localhost:$local_port to $SERVER_IP:$remote_port..." + + # Check if the tunnel is already established + if netstat -tuln | grep -q ":$local_port "; then + echo "Port $local_port is already in use. Tunnel may already be established." + return 0 + fi + + # Create the SSH tunnel + if [ -n "$SERVER_PASSWORD" ]; then + # Use sshpass if available + if command -v sshpass &> /dev/null; then + sshpass -p "$SERVER_PASSWORD" ssh -N -L $local_port:localhost:$remote_port -p $SERVER_PORT $SERVER_USER@$SERVER_IP & + else + echo "sshpass not installed. You will be prompted for the password." + ssh -N -L $local_port:localhost:$remote_port -p $SERVER_PORT $SERVER_USER@$SERVER_IP & + fi + else + ssh -N -L $local_port:localhost:$remote_port -p $SERVER_PORT $SERVER_USER@$SERVER_IP & + fi + + # Check if the tunnel was established + if [ $? -eq 0 ]; then + echo "SSH tunnel established. Local port $local_port is now forwarded to $SERVER_IP:$remote_port." + echo "Tunnel process ID: $!" + echo $! >> tunnel_pids.txt + else + echo "Failed to establish SSH tunnel." + return 1 + fi +} + +# Create tunnels for Ollama and OpenWebUI +echo "Setting up SSH tunnels to remote server at $SERVER_IP..." + +# Create a file to store tunnel process IDs +touch tunnel_pids.txt + +# Create tunnel for Ollama (port 11434) +create_tunnel 11434 11434 + +# Create tunnel for OpenWebUI (port 8080) +create_tunnel 8080 8080 + +echo "SSH tunnels established. You can now access:" +echo "- Ollama API at http://localhost:11434" +echo "- OpenWebUI at http://localhost:8080" +echo "" +echo "To stop the tunnels, run: ./stop_ssh_tunnels.sh" diff --git a/local_test.env b/local_test.env new file mode 100644 index 0000000..230a7a3 --- /dev/null +++ b/local_test.env @@ -0,0 +1,18 @@ +# Remote server configuration +SERVER_IP=104.225.217.215 +SERVER_PORT=22 +SERVER_USER=root +SERVER_PASSWORD=S5qqENZNqc + +# Ollama configuration +OLLAMA_API_URL=http://104.225.217.215:8080/ollama + +# OpenWebUI configuration +OPENWEBUI_URL=http://104.225.217.215:8080 +OPENWEBUI_API_KEY=your_openwebui_api_key_here + +# Model configuration +DEFAULT_MODEL=llama3.1 + +# API timeout (in seconds) +API_TIMEOUT=300 diff --git a/local_test.env.example b/local_test.env.example new file mode 100644 index 0000000..38cd148 --- /dev/null +++ b/local_test.env.example @@ -0,0 +1,18 @@ +# Remote server configuration +SERVER_IP=104.225.217.215 +SERVER_PORT=22 +SERVER_USER=root +SERVER_PASSWORD=your_password_here + +# Ollama configuration +OLLAMA_API_URL=http://104.225.217.215:11434 + +# OpenWebUI configuration +OPENWEBUI_URL=http://104.225.217.215:8080 +OPENWEBUI_API_KEY=your_openwebui_api_key_here + +# Model configuration +DEFAULT_MODEL=llama3.1 + +# API timeout (in seconds) +API_TIMEOUT=300 diff --git a/local_test_config.py b/local_test_config.py new file mode 100644 index 0000000..3e2bff1 --- /dev/null +++ b/local_test_config.py @@ -0,0 +1,35 @@ +""" +Configuration for local testing with remote server resources. +""" + +import os +from dotenv import load_dotenv + +# Try to load environment variables from .env file +dotenv_path = os.path.join(os.path.dirname(__file__), 'local_test.env') +load_dotenv(dotenv_path=dotenv_path) + +# Configuration class +class LocalTestConfig: + """Configuration for local testing with remote server resources.""" + + # Remote server configuration + SERVER_IP = os.environ.get('SERVER_IP', '104.225.217.215') + SERVER_PORT = os.environ.get('SERVER_PORT', '22') + SERVER_USER = os.environ.get('SERVER_USER', 'root') + + # Ollama configuration + OLLAMA_API_URL = os.environ.get('OLLAMA_API_URL', f'http://{SERVER_IP}:11434') + + # OpenWebUI configuration + OPENWEBUI_URL = os.environ.get('OPENWEBUI_URL', f'http://{SERVER_IP}:8080') + OPENWEBUI_API_KEY = os.environ.get('OPENWEBUI_API_KEY', '') + + # Model configuration + DEFAULT_MODEL = os.environ.get('DEFAULT_MODEL', 'llama3.1') + + # API timeout (in seconds) + API_TIMEOUT = int(os.environ.get('API_TIMEOUT', 300)) # 5 minutes + +# Create a singleton instance +config = LocalTestConfig() diff --git a/openwebui_config.md b/openwebui_config.md index e197e9e..696bf4d 100644 --- a/openwebui_config.md +++ b/openwebui_config.md @@ -15,8 +15,8 @@ You need to modify the OpenWebUI environment variables to point to your AI servi Add or modify the following environment variables: ``` -OLLAMA_API_BASE_URL=http://your-server-ip:5251/ollama -OPENAI_API_BASE_URL=http://your-server-ip:5251/api +OLLAMA_API_BASE_URL=http://your-server-ip:5252/ollama +OPENAI_API_BASE_URL=http://your-server-ip:5252/api ``` Replace `your-server-ip` with the IP address or hostname of the server where your AI service is running. @@ -69,7 +69,7 @@ If you encounter issues with the integration: 3. Verify that your AI service is running and accessible: ```bash - curl http://your-server-ip:5251/health + curl http://your-server-ip:5252/health ``` 4. Verify that the OpenWebUI environment variables are set correctly: diff --git a/setup_local_test_env.sh b/setup_local_test_env.sh new file mode 100755 index 0000000..d39be2e --- /dev/null +++ b/setup_local_test_env.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Script to set up the local test environment + +# Check if Python is installed +if ! command -v python3 &> /dev/null; then + echo "Python 3 is not installed. Please install Python 3 and try again." + exit 1 +fi + +# Create a virtual environment if it doesn't exist +if [ ! -d "venv" ]; then + echo "Creating virtual environment..." + python3 -m venv venv + if [ $? -ne 0 ]; then + echo "Failed to create virtual environment. Please check your Python installation." + exit 1 + fi + echo "Virtual environment created successfully." +else + echo "Virtual environment already exists." +fi + +# Activate the virtual environment +echo "Activating virtual environment..." +source venv/bin/activate +if [ $? -ne 0 ]; then + echo "Failed to activate virtual environment." + exit 1 +fi + +# Install dependencies +echo "Installing dependencies..." +pip install --upgrade pip +pip install requests python-dotenv argparse + +# Create local_test.env file if it doesn't exist +if [ ! -f "local_test.env" ]; then + echo "Creating local_test.env file from template..." + cp local_test.env.example local_test.env + echo "Please edit local_test.env with your server credentials." +else + echo "local_test.env file already exists." +fi + +# Make the test script executable +chmod +x test_remote_ollama.py + +echo "Setup complete!" +echo "To run the test script:" +echo "1. Activate the virtual environment: source venv/bin/activate" +echo "2. Run the test script: python test_remote_ollama.py" +echo "3. To specify a different model or prompt: python test_remote_ollama.py --model llama3.3 --prompt \"Tell me about AI\"" +echo "4. To specify a different Ollama URL: python test_remote_ollama.py --ollama-url http://your-server-ip:11434" diff --git a/stop_ssh_tunnels.sh b/stop_ssh_tunnels.sh new file mode 100755 index 0000000..f70dbd5 --- /dev/null +++ b/stop_ssh_tunnels.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Script to stop SSH tunnels + +# Check if the tunnel_pids.txt file exists +if [ ! -f "tunnel_pids.txt" ]; then + echo "No tunnel PIDs file found. No tunnels to stop." + exit 0 +fi + +# Read the PIDs from the file and kill each process +while read pid; do + if [ -n "$pid" ]; then + echo "Stopping tunnel with PID $pid..." + kill $pid 2>/dev/null || true + fi +done < tunnel_pids.txt + +# Remove the PIDs file +rm tunnel_pids.txt + +# Check for any remaining SSH tunnels +remaining_tunnels=$(ps aux | grep "ssh -N -L" | grep -v grep | wc -l) +if [ $remaining_tunnels -gt 0 ]; then + echo "Warning: There are still $remaining_tunnels SSH tunnels running." + echo "You may need to kill them manually:" + ps aux | grep "ssh -N -L" | grep -v grep +else + echo "All SSH tunnels have been stopped." +fi diff --git a/test_ai_service.py b/test_ai_service.py new file mode 100755 index 0000000..569f644 --- /dev/null +++ b/test_ai_service.py @@ -0,0 +1,214 @@ +""" +Test script for the AI service API. +""" + +import requests +import json +import argparse + +def test_health(api_url): + """Test the health endpoint.""" + print(f"Testing health endpoint at: {api_url}/health") + + try: + response = requests.get(f"{api_url}/health", timeout=30) + response.raise_for_status() + + print("Health check successful!") + print(f"Response: {response.json()}") + + return True + except Exception as e: + print(f"ERROR: Health check failed: {str(e)}") + return False + +def test_config(api_url): + """Test the config endpoint.""" + print(f"Testing config endpoint at: {api_url}/config") + + try: + response = requests.get(f"{api_url}/config", timeout=30) + response.raise_for_status() + + print("Config check successful!") + print("Configuration:") + config = response.json() + for key, value in config.items(): + print(f" {key}: {value}") + + return True, config + except Exception as e: + print(f"ERROR: Config check failed: {str(e)}") + return False, None + +def test_ollama_connection(api_url): + """Test the Ollama connection.""" + print(f"Testing Ollama connection at: {api_url}/test-ollama") + + try: + response = requests.get(f"{api_url}/test-ollama", timeout=60) + response.raise_for_status() + + print("Ollama connection test successful!") + result = response.json() + print(f"Status: {result.get('status')}") + print(f"Message: {result.get('message')}") + print(f"Ollama URL: {result.get('ollama_url')}") + + if 'models' in result: + print("Available models:") + for model in result.get('models', {}).get('models', []): + print(f" - {model.get('name')}") + + return True + except Exception as e: + print(f"ERROR: Ollama connection test failed: {str(e)}") + return False + +def test_chat_completion(api_url, model_id, prompt): + """Test the chat completion endpoint.""" + print(f"Testing chat completion at: {api_url}/test-ollama-direct") + print(f"Model: {model_id}") + print(f"Prompt: {prompt}") + + try: + # First, create a chat + chat_response = requests.post( + f"{api_url}/chats", + headers={"Content-Type": "application/json"}, + json={ + "user_id": "test_user", + "title": "Test Chat", + "model_id": model_id + }, + timeout=60 + ) + + if chat_response.status_code != 200: + print(f"ERROR: Failed to create chat: {chat_response.status_code}") + print(chat_response.text) + # Try direct Ollama test instead + print("Trying direct Ollama test...") + response = requests.post( + f"{api_url}/test-ollama-direct", + headers={"Content-Type": "application/json"}, + json={ + "model": model_id, + "prompt": prompt + }, + timeout=120 + ) + + response.raise_for_status() + + result = response.json() + print("\nResponse:") + print(result.get('response', 'No response')) + + return True + + chat_id = chat_response.json().get("id") + print(f"Chat created with ID: {chat_id}") + + # Send a message to the chat + message_response = requests.post( + f"{api_url}/chats/{chat_id}/messages", + headers={"Content-Type": "application/json"}, + json={ + "message": prompt, + "user_id": "test_user", + "temperature": 0.7, + "max_tokens": 500 + }, + timeout=120 + ) + + message_response.raise_for_status() + + result = message_response.json() + print("\nResponse:") + print(result.get('content', 'No content in response')) + + return True + except Exception as e: + print(f"ERROR: Chat completion test failed: {str(e)}") + return False + +def test_rag_completion(api_url, prompt): + """Test the RAG completion endpoint.""" + print(f"Testing RAG completion at: {api_url}/ask-rag") + print(f"Prompt: {prompt}") + + try: + response = requests.post( + f"{api_url}/ask-rag", + headers={"Content-Type": "application/json"}, + json={"query": prompt}, + timeout=120 + ) + + response.raise_for_status() + + result = response.json() + print("\nResponse:") + print(result.get('response', 'No response')) + + return True + except Exception as e: + print(f"ERROR: RAG completion test failed: {str(e)}") + return False + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test the AI service API') + parser.add_argument('--api-url', type=str, default='http://localhost:5252', help='AI service API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--prompt', type=str, default='What is the capital of France?', help='Prompt to use for testing') + parser.add_argument('--rag-prompt', type=str, default='What information do you have in your knowledge base?', help='Prompt to use for RAG testing') + + args = parser.parse_args() + + print("=== AI Service API Test ===") + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print() + + # Test health endpoint + print("=== Testing Health Endpoint ===") + health_success = test_health(args.api_url) + print() + + # Test config endpoint + print("=== Testing Config Endpoint ===") + config_success, config = test_config(args.api_url) + print() + + # Test Ollama connection + print("=== Testing Ollama Connection ===") + ollama_success = test_ollama_connection(args.api_url) + print() + + # Test chat completion + if ollama_success: + print("=== Testing Chat Completion ===") + chat_success = test_chat_completion(args.api_url, args.model, args.prompt) + print() + + # Test RAG completion + print("=== Testing RAG Completion ===") + rag_success = test_rag_completion(args.api_url, args.rag_prompt) + print() + else: + chat_success = False + rag_success = False + + # Print summary + print("=== Test Summary ===") + print(f"Health Endpoint: {'SUCCESS' if health_success else 'FAILED'}") + print(f"Config Endpoint: {'SUCCESS' if config_success else 'FAILED'}") + print(f"Ollama Connection: {'SUCCESS' if ollama_success else 'FAILED'}") + print(f"Chat Completion: {'SUCCESS' if chat_success else 'FAILED'}") + print(f"RAG Completion: {'SUCCESS' if rag_success else 'FAILED'}") + +if __name__ == "__main__": + main() diff --git a/test_direct_ollama.py b/test_direct_ollama.py new file mode 100755 index 0000000..77cfedf --- /dev/null +++ b/test_direct_ollama.py @@ -0,0 +1,76 @@ +""" +Test script for the direct Ollama endpoint. +""" + +import requests +import json +import argparse +import time + +def test_direct_ollama(api_url, model_id, prompt): + """Test the direct Ollama endpoint.""" + print(f"Testing direct Ollama endpoint at: {api_url}/test-ollama-direct") + print(f"Model: {model_id}") + print(f"Prompt: {prompt}") + + try: + start_time = time.time() + + response = requests.post( + f"{api_url}/test-ollama-direct", + headers={"Content-Type": "application/json"}, + json={ + "model": model_id, + "prompt": prompt + }, + timeout=300 # 5 minutes timeout + ) + + end_time = time.time() + elapsed_time = end_time - start_time + + response.raise_for_status() + + result = response.json() + print(f"\nResponse (took {elapsed_time:.2f} seconds):") + + # Handle different response formats + content = None + if 'response' in result and isinstance(result['response'], dict) and 'message' in result['response']: + content = result['response']['message'].get('content') + elif 'response' in result and isinstance(result['response'], str): + content = result['response'] + else: + content = str(result) + + print(content or 'No content in response') + + return True + except Exception as e: + print(f"ERROR: Direct Ollama test failed: {str(e)}") + return False + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test the direct Ollama endpoint') + parser.add_argument('--api-url', type=str, default='http://localhost:5252', help='AI service API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--prompt', type=str, default='What is the capital of France?', help='Prompt to use for testing') + + args = parser.parse_args() + + print("=== Direct Ollama Test ===") + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print(f"Prompt: {args.prompt}") + print() + + # Test direct Ollama endpoint + success = test_direct_ollama(args.api_url, args.model, args.prompt) + + # Print summary + print("\n=== Test Summary ===") + print(f"Direct Ollama Test: {'SUCCESS' if success else 'FAILED'}") + +if __name__ == "__main__": + main() diff --git a/test_ollama_custom.py b/test_ollama_custom.py new file mode 100755 index 0000000..b4da13d --- /dev/null +++ b/test_ollama_custom.py @@ -0,0 +1,104 @@ +""" +Test script for the Ollama API with custom prompts. +""" + +import requests +import json +import argparse +import time + +class OllamaRequest: + """Request model for Ollama API.""" + def __init__(self, model, prompt, system_prompt=None): + self.model = model + self.prompt = prompt + self.system_prompt = system_prompt or "You are a helpful assistant." + + def to_json(self): + """Convert to JSON for the API request.""" + messages = [] + + # Add system message + messages.append({"role": "system", "content": self.system_prompt}) + + # Add user message + messages.append({"role": "user", "content": self.prompt}) + + return { + "model": self.model, + "messages": messages, + "stream": False + } + +def test_ollama_api(api_url, model, prompt, system_prompt=None): + """Test the Ollama API directly.""" + print(f"Testing Ollama API at: {api_url}") + print(f"Model: {model}") + print(f"Prompt: {prompt}") + if system_prompt: + print(f"System prompt: {system_prompt}") + + # Create the request + request = OllamaRequest(model, prompt, system_prompt) + request_json = request.to_json() + + try: + start_time = time.time() + + # Make the API call + response = requests.post( + api_url, + headers={"Content-Type": "application/json"}, + json=request_json, + timeout=300 # 5 minutes timeout + ) + + end_time = time.time() + elapsed_time = end_time - start_time + + response.raise_for_status() + + # Parse the response + result = response.json() + + print(f"\nResponse (took {elapsed_time:.2f} seconds):") + print(json.dumps(result, indent=2)) + + # Extract the content + if 'message' in result: + content = result['message'].get('content', 'No content in response') + print("\nContent:") + print(content) + + return True + except Exception as e: + print(f"ERROR: Ollama API test failed: {str(e)}") + return False + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test the Ollama API with custom prompts') + parser.add_argument('--api-url', type=str, default='http://localhost:11434/api/chat', help='Ollama API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--prompt', type=str, default='What is the capital of France?', help='Prompt to use for testing') + parser.add_argument('--system-prompt', type=str, default=None, help='System prompt to use for testing') + + args = parser.parse_args() + + print("=== Ollama API Test ===") + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print(f"Prompt: {args.prompt}") + if args.system_prompt: + print(f"System prompt: {args.system_prompt}") + print() + + # Test Ollama API + success = test_ollama_api(args.api_url, args.model, args.prompt, args.system_prompt) + + # Print summary + print("\n=== Test Summary ===") + print(f"Ollama API Test: {'SUCCESS' if success else 'FAILED'}") + +if __name__ == "__main__": + main() diff --git a/test_rag.py b/test_rag.py index 8caca47..94706eb 100755 --- a/test_rag.py +++ b/test_rag.py @@ -15,7 +15,7 @@ from pprint import pprint # Default configuration DEFAULT_API_URL = "http://localhost:5252" # Local development server -DEFAULT_REMOTE_API_URL = "http://157.157.221.29:5251" # Remote server +DEFAULT_REMOTE_API_URL = "http://157.157.221.29:5252" # Remote server DEFAULT_MODEL = "llama3.1" class RAGTester: @@ -24,7 +24,7 @@ class RAGTester: def __init__(self, api_url: str, verbose: bool = False): """ Initialize the RAG tester. - + Args: api_url: URL of the AI service API. verbose: Whether to print verbose output. @@ -32,19 +32,19 @@ class RAGTester: self.api_url = api_url self.verbose = verbose self.session = requests.Session() - + # Print configuration print(f"Testing RAG functionality against API at: {self.api_url}") - + def _log(self, message: str): """Log a message if verbose mode is enabled.""" if self.verbose: print(f"[DEBUG] {message}") - + def check_server_health(self) -> bool: """ Check if the server is healthy. - + Returns: True if the server is healthy, False otherwise. """ @@ -52,7 +52,7 @@ class RAGTester: response = self.session.get(f"{self.api_url}/health", timeout=10) response.raise_for_status() result = response.json() - + if result.get("status") == "healthy": print("✅ Server is healthy") return True @@ -60,15 +60,15 @@ class RAGTester: print("❌ Server health check failed") print(f"Response: {result}") return False - + except Exception as e: print(f"❌ Error checking server health: {str(e)}") return False - + def check_config(self) -> Dict[str, Any]: """ Check the server configuration. - + Returns: Server configuration. """ @@ -76,7 +76,7 @@ class RAGTester: response = self.session.get(f"{self.api_url}/config", timeout=10) response.raise_for_status() config = response.json() - + print("✅ Server configuration:") print(f" - API Host: {config.get('api_host')}") print(f" - API Port: {config.get('api_port')}") @@ -85,17 +85,17 @@ class RAGTester: print(f" - Default Model: {config.get('default_model')}") print(f" - API Timeout: {config.get('api_timeout')} seconds") print(f" - Available Models: {', '.join(config.get('available_models', []))}") - + return config - + except Exception as e: print(f"❌ Error checking server configuration: {str(e)}") return {} - + def test_ollama_connection(self) -> bool: """ Test the connection to Ollama. - + Returns: True if the connection is successful, False otherwise. """ @@ -103,7 +103,7 @@ class RAGTester: response = self.session.get(f"{self.api_url}/test-ollama", timeout=30) response.raise_for_status() result = response.json() - + if result.get("status") == "success": print("✅ Successfully connected to Ollama API") print(f" - Ollama URL: {result.get('ollama_url')}") @@ -114,18 +114,18 @@ class RAGTester: print(f" - Error: {result.get('message')}") print(f" - Ollama URL: {result.get('ollama_url')}") return False - + except Exception as e: print(f"❌ Error testing Ollama connection: {str(e)}") return False - + def test_chat_completion(self, model_id: Optional[str] = None) -> bool: """ Test basic chat completion without RAG. - + Args: model_id: Optional model ID to use. - + Returns: True if the test is successful, False otherwise. """ @@ -133,7 +133,7 @@ class RAGTester: response = self.session.post(f"{self.api_url}/test-chat", timeout=60) response.raise_for_status() result = response.json() - + if result.get("status") == "success": print("✅ Successfully tested chat completion") print(f" - Model: {result.get('model')}") @@ -143,61 +143,61 @@ class RAGTester: print("❌ Failed to test chat completion") print(f" - Error: {result.get('message')}") return False - + except Exception as e: print(f"❌ Error testing chat completion: {str(e)}") return False - + def test_rag_completion(self, query: str = "What information do you have in your knowledge database?") -> bool: """ Test RAG completion with a query. - + Args: query: Query to test with RAG. - + Returns: True if the test is successful, False otherwise. """ try: response = self.session.post( - f"{self.api_url}/test-rag", + f"{self.api_url}/test-rag", params={"query": query}, timeout=120 # Longer timeout for RAG ) response.raise_for_status() result = response.json() - + if result.get("status") == "success": print("✅ Successfully tested RAG completion") print(f" - Model: {result.get('model')}") print(f" - Query: {result.get('query')}") print(f" - OpenWebUI URL: {result.get('openwebui_url')}") print(f" - Response: {result.get('response')[:150]}...") # First 150 chars - + # Print full response in verbose mode if self.verbose: print("\nFull response:") print(result.get('response')) - + return True else: print("❌ Failed to test RAG completion") print(f" - Error: {result.get('message')}") print(f" - OpenWebUI URL: {result.get('openwebui_url')}") return False - + except Exception as e: print(f"❌ Error testing RAG completion: {str(e)}") return False - + def create_chat_and_test_rag(self, query: str, user_id: str = "test_user") -> bool: """ Create a chat and test RAG with a message. - + Args: query: Query to test with RAG. user_id: User ID for the chat. - + Returns: True if the test is successful, False otherwise. """ @@ -216,9 +216,9 @@ class RAGTester: create_response.raise_for_status() chat = create_response.json() chat_id = chat.get("id") - + print(f"✅ Created chat with ID: {chat_id}") - + # Send a message with RAG enabled message_response = self.session.post( f"{self.api_url}/chats/{chat_id}/messages", @@ -233,57 +233,57 @@ class RAGTester: ) message_response.raise_for_status() message = message_response.json() - + print("✅ Successfully sent message with RAG") print(f" - Message ID: {message.get('id')}") print(f" - Response: {message.get('content')[:150]}...") # First 150 chars - + # Print full response in verbose mode if self.verbose: print("\nFull response:") print(message.get('content')) - + return True - + except Exception as e: print(f"❌ Error testing chat with RAG: {str(e)}") return False - + def run_all_tests(self, query: str = "What information do you have in your knowledge database?"): """ Run all tests. - + Args: query: Query to test with RAG. """ print("\n=== Running RAG Functionality Tests ===\n") - + # Check server health if not self.check_server_health(): print("❌ Server health check failed. Aborting tests.") return - + # Check configuration config = self.check_config() if not config: print("❌ Failed to get server configuration. Continuing with tests...") - + # Test Ollama connection if not self.test_ollama_connection(): print("⚠️ Ollama connection test failed. Some tests may fail.") - + # Test basic chat completion if not self.test_chat_completion(): print("⚠️ Basic chat completion test failed. RAG tests may also fail.") - + # Test RAG completion print("\n--- Testing RAG Completion ---\n") self.test_rag_completion(query) - + # Test chat with RAG print("\n--- Testing Chat with RAG ---\n") self.create_chat_and_test_rag(query) - + print("\n=== Tests Completed ===\n") @@ -294,12 +294,12 @@ def main(): parser.add_argument("--remote", action="store_true", help=f"Use the remote API URL ({DEFAULT_REMOTE_API_URL})") parser.add_argument("--query", default="What information do you have in your knowledge database?", help="Query to test with RAG") parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output") - + args = parser.parse_args() - + # Use remote URL if specified api_url = DEFAULT_REMOTE_API_URL if args.remote else args.api_url - + # Create and run the tester tester = RAGTester(api_url=api_url, verbose=args.verbose) tester.run_all_tests(query=args.query) diff --git a/test_remote_ollama.py b/test_remote_ollama.py new file mode 100755 index 0000000..9ae3e57 --- /dev/null +++ b/test_remote_ollama.py @@ -0,0 +1,165 @@ +""" +Test script for connecting to a remote Ollama server. +""" + +import os +import sys +import requests +import json +import argparse + +# Import local test configuration +from local_test_config import config + +def test_ollama_connection(): + """Test the connection to the Ollama API.""" + print(f"Testing connection to Ollama API at: {config.OLLAMA_API_URL}") + + try: + # Try to connect to Ollama API via OpenWebUI + # OpenWebUI exposes Ollama models through its own API + response = requests.get(f"{config.OPENWEBUI_URL}/api/models", timeout=config.API_TIMEOUT) + response.raise_for_status() + + # Print the models from OpenWebUI + print("Connection successful!") + print("Available models:") + models_data = response.json() + if isinstance(models_data, list): + for model in models_data: + print(f"- {model.get('id')}") + else: + print(f"Unexpected response format: {models_data}") + + return True + except requests.exceptions.Timeout as e: + print(f"ERROR: Timeout connecting to Ollama API: {str(e)}. The request exceeded the {config.API_TIMEOUT} second timeout.") + return False + except requests.exceptions.ConnectionError as e: + print(f"ERROR: Connection error to Ollama API: {str(e)}. Please check if Ollama is running at {config.OLLAMA_API_URL}.") + return False + except Exception as e: + print(f"ERROR: Error connecting to Ollama API: {str(e)}") + return False + +def test_generate_response(model_id=None, prompt=None): + """Test generating a response from the model.""" + if model_id is None: + model_id = config.DEFAULT_MODEL + + if prompt is None: + prompt = "What is the capital of France?" + + print(f"Testing model: {model_id}") + print(f"Prompt: {prompt}") + + try: + # Prepare the request for OpenWebUI's chat completions API + request_json = { + "model": model_id, + "messages": [ + {"role": "user", "content": prompt} + ], + "stream": False, + "temperature": 0.7, + "max_tokens": 500 + } + + # Make the API call to OpenWebUI's chat completions API + print(f"Sending request to OpenWebUI API at: {config.OPENWEBUI_URL}/api/chat/completions") + + response = requests.post( + f"{config.OPENWEBUI_URL}/api/chat/completions", + headers={"Content-Type": "application/json"}, + json=request_json, + timeout=config.API_TIMEOUT + ) + + response.raise_for_status() + + # Parse the response + response_data = response.json() + + # Print the response (OpenWebUI uses OpenAI-compatible format) + print("\nResponse:") + content = response_data.get('choices', [{}])[0].get('message', {}).get('content', 'No content in response') + print(content) + + return True + except requests.exceptions.Timeout as e: + print(f"ERROR: Timeout generating response: {str(e)}. The request exceeded the {config.API_TIMEOUT} second timeout.") + return False + except requests.exceptions.ConnectionError as e: + print(f"ERROR: Connection error to Ollama API: {str(e)}. Please check if Ollama is running at {config.OLLAMA_API_URL}.") + return False + except Exception as e: + print(f"ERROR: Error generating response: {str(e)}") + return False + +def test_openwebui_connection(): + """Test the connection to OpenWebUI.""" + print(f"Testing connection to OpenWebUI at: {config.OPENWEBUI_URL}") + + try: + # Try to connect to OpenWebUI + response = requests.get(f"{config.OPENWEBUI_URL}/api/health", timeout=config.API_TIMEOUT) + response.raise_for_status() + + # Print the response + print("Connection successful!") + print(f"OpenWebUI status: {response.text}") + + return True + except requests.exceptions.Timeout as e: + print(f"ERROR: Timeout connecting to OpenWebUI: {str(e)}. The request exceeded the {config.API_TIMEOUT} second timeout.") + return False + except requests.exceptions.ConnectionError as e: + print(f"ERROR: Connection error to OpenWebUI: {str(e)}. Please check if OpenWebUI is running at {config.OPENWEBUI_URL}.") + return False + except Exception as e: + print(f"ERROR: Error connecting to OpenWebUI: {str(e)}") + return False + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test remote Ollama and OpenWebUI connections') + parser.add_argument('--model', type=str, default=config.DEFAULT_MODEL, help='Model to use for testing') + parser.add_argument('--prompt', type=str, default="What is the capital of France?", help='Prompt to use for testing') + parser.add_argument('--ollama-url', type=str, default=config.OLLAMA_API_URL, help='Ollama API URL') + parser.add_argument('--openwebui-url', type=str, default=config.OPENWEBUI_URL, help='OpenWebUI URL') + parser.add_argument('--timeout', type=int, default=config.API_TIMEOUT, help='API timeout in seconds') + + args = parser.parse_args() + + # Update configuration with command-line arguments + config.OLLAMA_API_URL = args.ollama_url + config.OPENWEBUI_URL = args.openwebui_url + config.API_TIMEOUT = args.timeout + + print("=== Remote Connection Test ===") + print(f"Ollama API URL: {config.OLLAMA_API_URL}") + print(f"OpenWebUI URL: {config.OPENWEBUI_URL}") + print(f"API Timeout: {config.API_TIMEOUT} seconds") + print() + + # Test Ollama connection + print("=== Testing Ollama Connection ===") + ollama_success = test_ollama_connection() + print() + + # Test OpenWebUI connection + print("=== Testing OpenWebUI Connection ===") + openwebui_success = test_openwebui_connection() + print() + + # Test generating a response + if ollama_success: + print("=== Testing Model Response ===") + test_generate_response(args.model, args.prompt) + + print("\n=== Test Summary ===") + print(f"Ollama Connection: {'SUCCESS' if ollama_success else 'FAILED'}") + print(f"OpenWebUI Connection: {'SUCCESS' if openwebui_success else 'FAILED'}") + +if __name__ == "__main__": + main() diff --git a/test_simple_team_chat.py b/test_simple_team_chat.py new file mode 100755 index 0000000..305f59f --- /dev/null +++ b/test_simple_team_chat.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +""" +Simple test script for team chat functionality. +""" + +import requests +import argparse +import sys + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Simple test for team chat functionality') + parser.add_argument('--api-url', type=str, default='http://localhost:5252', help='AI service API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--user-id', type=str, default='test_user', help='User ID for testing') + parser.add_argument('--chat-id', type=str, help='Existing chat ID to use (optional)') + parser.add_argument('--message', type=str, default='Hello team!', help='Message to send') + parser.add_argument('--with-mention', action='store_true', help='Add @ai mention to message') + + args = parser.parse_args() + + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print(f"User ID: {args.user_id}") + + # Create a chat if no chat ID is provided + chat_id = args.chat_id + if not chat_id: + print("\nCreating a new team chat...") + try: + response = requests.post( + f"{args.api_url}/chats", + headers={"Content-Type": "application/json"}, + json={ + "user_id": args.user_id, + "title": "Simple Team Chat Test", + "model_id": args.model, + "is_team_chat": True + }, + timeout=30 + ) + + response.raise_for_status() + chat = response.json() + chat_id = chat.get("id") + + print(f"Created team chat with ID: {chat_id}") + print(f"OpenWebUI Channel ID: {chat.get('openwebui_channel_id', 'Not available')}") + print(f"Team Members: {chat.get('team_members', [])}") + except Exception as e: + print(f"Error creating team chat: {str(e)}") + sys.exit(1) + else: + print(f"\nUsing existing chat ID: {chat_id}") + + # Prepare message + message = args.message + if args.with_mention: + message = f"@ai {message}" + print(f"\nSending message WITH @ai mention: {message}") + else: + print(f"\nSending message WITHOUT @ai mention: {message}") + + # Send message + try: + response = requests.post( + f"{args.api_url}/chats/{chat_id}/messages", + headers={"Content-Type": "application/json"}, + json={ + "message": message, + "user_id": args.user_id + }, + timeout=10 + ) + + response.raise_for_status() + result = response.json() + + print("\nMessage sent successfully!") + print(f"AI Response: {result.get('content', 'No content in response')}") + + print("\nNote: When using the API directly, the AI will always respond") + print("The @ai mention functionality only applies to messages sent through OpenWebUI channels") + print(f"\nYou can check the OpenWebUI interface at: http://104.225.217.215:8080/") + print(f"Chat ID: {chat_id}") + except Exception as e: + print(f"Error sending message: {str(e)}") + sys.exit(1) + +if __name__ == "__main__": + main() diff --git a/test_team_chat_mentions.py b/test_team_chat_mentions.py new file mode 100755 index 0000000..8020bab --- /dev/null +++ b/test_team_chat_mentions.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python3 +""" +Test script for team chat mentions functionality. +This script tests the AI response to @ai mentions in team chats. +""" + +import requests +import json +import argparse +import time +import sys +from typing import Dict, Any, List, Tuple, Optional + +def test_health(api_url: str) -> bool: + """Test the health endpoint.""" + print(f"Testing health endpoint at: {api_url}/health") + + try: + response = requests.get(f"{api_url}/health", timeout=30) + response.raise_for_status() + + print("✅ Health check successful!") + print(f"Response: {response.json()}") + + return True + except Exception as e: + print(f"❌ ERROR: Health check failed: {str(e)}") + return False + +def test_create_team_chat(api_url: str, user_id: str, title: str, model_id: str) -> Tuple[bool, Optional[str]]: + """ + Test creating a team chat. + + Args: + api_url: API URL + user_id: User ID + title: Chat title + model_id: Model ID + + Returns: + Tuple of (success, chat_id) + """ + print(f"Creating team chat with title: {title}") + + try: + response = requests.post( + f"{api_url}/chats", + headers={"Content-Type": "application/json"}, + json={ + "user_id": user_id, + "title": title, + "model_id": model_id, + "is_team_chat": True + }, + timeout=60 + ) + + response.raise_for_status() + chat = response.json() + chat_id = chat.get("id") + + print(f"✅ Team chat created successfully with ID: {chat_id}") + print(f"OpenWebUI Channel ID: {chat.get('openwebui_channel_id', 'Not available')}") + print(f"Team Members: {chat.get('team_members', [])}") + + return True, chat_id + except Exception as e: + print(f"❌ ERROR: Failed to create team chat: {str(e)}") + return False, None + +def test_add_team_member(api_url: str, chat_id: str, user_id: str) -> bool: + """ + Test adding a member to a team chat. + + Args: + api_url: API URL + chat_id: Chat ID + user_id: User ID to add + + Returns: + Success status + """ + print(f"Adding user {user_id} to team chat {chat_id}") + + try: + response = requests.post( + f"{api_url}/chats/{chat_id}/members/{user_id}", + timeout=30 + ) + + response.raise_for_status() + + print(f"✅ User {user_id} added to team chat successfully") + return True + except Exception as e: + print(f"❌ ERROR: Failed to add user to team chat: {str(e)}") + return False + +def test_send_team_message_with_mention(api_url: str, chat_id: str, user_id: str, message: str, mention: str) -> bool: + """ + Test sending a message with an @ai mention to a team chat. + + Args: + api_url: API URL + chat_id: Chat ID + user_id: User ID + message: Message content + mention: Mention to use (@ai, @bot, etc.) + + Returns: + Success status + """ + full_message = f"{mention} {message}" + print(f"Sending message to team chat {chat_id}: {full_message}") + + try: + response = requests.post( + f"{api_url}/chats/{chat_id}/messages", + headers={"Content-Type": "application/json"}, + json={ + "message": full_message, + "user_id": user_id, + "temperature": 0.7, + "max_tokens": 500 + }, + timeout=60 + ) + + response.raise_for_status() + + result = response.json() + print(f"✅ Message with mention sent successfully") + print(f"AI Response: {result.get('content', 'No content in response')[:100]}...") + + return True + except Exception as e: + print(f"❌ ERROR: Failed to send message to team chat: {str(e)}") + return False + +def test_send_team_message_without_mention(api_url: str, chat_id: str, user_id: str, message: str) -> bool: + """ + Test sending a message without an @ai mention to a team chat. + + Args: + api_url: API URL + chat_id: Chat ID + user_id: User ID + message: Message content + + Returns: + Success status + """ + print(f"Sending message without mention to team chat {chat_id}: {message}") + + try: + response = requests.post( + f"{api_url}/chats/{chat_id}/messages", + headers={"Content-Type": "application/json"}, + json={ + "message": message, + "user_id": user_id, + "temperature": 0.7, + "max_tokens": 500 + }, + timeout=60 + ) + + response.raise_for_status() + + result = response.json() + print(f"✅ Message without mention sent successfully") + + # Note: When using the API directly, the AI will always respond + # The AI_RESPOND_TO_ALL setting only applies to messages received through the webhook + print(f"Note: AI responded because we're using the API directly: {result.get('content', 'No content in response')[:100]}...") + print("The @ai mention functionality only applies to messages sent through OpenWebUI channels") + + return True + except Exception as e: + print(f"❌ ERROR: Failed to send message to team chat: {str(e)}") + return False + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test team chat mentions functionality') + parser.add_argument('--api-url', type=str, default='http://localhost:5252', help='AI service API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--user-id', type=str, default='test_user', help='User ID for testing') + parser.add_argument('--second-user-id', type=str, default='test_user2', help='Second user ID for testing team membership') + parser.add_argument('--mention', type=str, default='@ai', help='Mention to use (@ai, @bot, etc.)') + parser.add_argument('--message', type=str, default='Can you help me with a project?', help='Message to send to the team chat') + + args = parser.parse_args() + + print("=== Team Chat Mentions Functionality Test ===") + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print(f"User ID: {args.user_id}") + print(f"Mention: {args.mention}") + print() + + # Test health endpoint + print("=== Testing Health Endpoint ===") + health_success = test_health(args.api_url) + print() + + if not health_success: + print("❌ Health check failed. Aborting tests.") + sys.exit(1) + + # Test creating a team chat + print("=== Creating Team Chat ===") + chat_success, chat_id = test_create_team_chat( + args.api_url, + args.user_id, + f"Mention Test Chat {time.strftime('%Y-%m-%d %H:%M:%S')}", + args.model + ) + print() + + if not chat_success or not chat_id: + print("❌ Failed to create team chat. Aborting tests.") + sys.exit(1) + + # Test adding a team member + print("=== Adding Team Member ===") + member_success = test_add_team_member(args.api_url, chat_id, args.second_user_id) + print() + + # Test sending a message without a mention + print("=== Sending Message WITHOUT Mention ===") + no_mention_success = test_send_team_message_without_mention( + args.api_url, + chat_id, + args.user_id, + f"This is a message without a mention: {args.message}" + ) + print() + + # Test sending a message with a mention + print("=== Sending Message WITH Mention ===") + mention_success = test_send_team_message_with_mention( + args.api_url, + chat_id, + args.user_id, + args.message, + args.mention + ) + print() + + # Print summary + print("=== Test Summary ===") + print(f"Health Endpoint: {'✅ SUCCESS' if health_success else '❌ FAILED'}") + print(f"Create Team Chat: {'✅ SUCCESS' if chat_success else '❌ FAILED'}") + print(f"Add Team Member: {'✅ SUCCESS' if member_success else '❌ FAILED'}") + print(f"Send Message WITHOUT Mention: {'✅ SUCCESS' if no_mention_success else '❌ FAILED'}") + print(f"Send Message WITH Mention: {'✅ SUCCESS' if mention_success else '❌ FAILED'}") + + if chat_success and chat_id: + print(f"\nCreated team chat ID: {chat_id}") + print("You can now check the OpenWebUI interface to see if the channel was created") + print("and if the AI responded to the message with the mention.") + print(f"OpenWebUI URL: http://104.225.217.215:8080/") + +if __name__ == "__main__": + main() diff --git a/test_team_chats.py b/test_team_chats.py new file mode 100755 index 0000000..c10e454 --- /dev/null +++ b/test_team_chats.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +""" +Test script for team chats functionality. +This script tests the team chat features of the AI service, including: +- Creating team chats +- Adding members to team chats +- Sending messages to team chats +- Verifying integration with OpenWebUI channels +""" + +import requests +import json +import argparse +import time +import sys +from typing import Dict, Any, List, Tuple, Optional + +def test_health(api_url: str) -> bool: + """Test the health endpoint.""" + print(f"Testing health endpoint at: {api_url}/health") + + try: + response = requests.get(f"{api_url}/health", timeout=30) + response.raise_for_status() + + print("✅ Health check successful!") + print(f"Response: {response.json()}") + + return True + except Exception as e: + print(f"❌ ERROR: Health check failed: {str(e)}") + return False + +def test_create_team_chat(api_url: str, user_id: str, title: str, model_id: str) -> Tuple[bool, Optional[str]]: + """ + Test creating a team chat. + + Args: + api_url: API URL + user_id: User ID + title: Chat title + model_id: Model ID + + Returns: + Tuple of (success, chat_id) + """ + print(f"Creating team chat with title: {title}") + + try: + response = requests.post( + f"{api_url}/chats", + headers={"Content-Type": "application/json"}, + json={ + "user_id": user_id, + "title": title, + "model_id": model_id, + "is_team_chat": True + }, + timeout=60 + ) + + response.raise_for_status() + chat = response.json() + chat_id = chat.get("id") + + print(f"✅ Team chat created successfully with ID: {chat_id}") + print(f"OpenWebUI Channel ID: {chat.get('openwebui_channel_id', 'Not available')}") + print(f"Team Members: {chat.get('team_members', [])}") + + return True, chat_id + except Exception as e: + print(f"❌ ERROR: Failed to create team chat: {str(e)}") + return False, None + +def test_add_team_member(api_url: str, chat_id: str, user_id: str) -> bool: + """ + Test adding a member to a team chat. + + Args: + api_url: API URL + chat_id: Chat ID + user_id: User ID to add + + Returns: + Success status + """ + print(f"Adding user {user_id} to team chat {chat_id}") + + try: + response = requests.post( + f"{api_url}/chats/{chat_id}/members/{user_id}", + timeout=30 + ) + + response.raise_for_status() + + print(f"✅ User {user_id} added to team chat successfully") + return True + except Exception as e: + print(f"❌ ERROR: Failed to add user to team chat: {str(e)}") + return False + +def test_send_team_message(api_url: str, chat_id: str, user_id: str, message: str) -> bool: + """ + Test sending a message to a team chat. + + Args: + api_url: API URL + chat_id: Chat ID + user_id: User ID + message: Message content + + Returns: + Success status + """ + print(f"Sending message to team chat {chat_id}: {message}") + + try: + response = requests.post( + f"{api_url}/chats/{chat_id}/messages", + headers={"Content-Type": "application/json"}, + json={ + "message": message, + "user_id": user_id, + "temperature": 0.7, + "max_tokens": 500 + }, + timeout=120 + ) + + response.raise_for_status() + + result = response.json() + print(f"✅ Message sent successfully") + print(f"AI Response: {result.get('content', 'No content in response')[:100]}...") + + return True + except Exception as e: + print(f"❌ ERROR: Failed to send message to team chat: {str(e)}") + return False + +def test_get_user_chats(api_url: str, user_id: str) -> Tuple[bool, List[Dict[str, Any]]]: + """ + Test getting all chats for a user. + + Args: + api_url: API URL + user_id: User ID + + Returns: + Tuple of (success, chats) + """ + print(f"Getting chats for user {user_id}") + + try: + response = requests.get( + f"{api_url}/chats/user/{user_id}", + timeout=30 + ) + + response.raise_for_status() + + chats = response.json() + team_chats = [chat for chat in chats if chat.get("is_team_chat", False)] + + print(f"✅ Found {len(chats)} chats for user {user_id}, {len(team_chats)} are team chats") + + return True, chats + except Exception as e: + print(f"❌ ERROR: Failed to get user chats: {str(e)}") + return False, [] + +def main(): + """Main function.""" + parser = argparse.ArgumentParser(description='Test team chats functionality') + parser.add_argument('--api-url', type=str, default='http://localhost:5252', help='AI service API URL') + parser.add_argument('--model', type=str, default='llama3.1', help='Model to use for testing') + parser.add_argument('--user-id', type=str, default='test_user', help='User ID for testing') + parser.add_argument('--second-user-id', type=str, default='test_user2', help='Second user ID for testing team membership') + parser.add_argument('--message', type=str, default='Hello team! Can you help me with a project?', help='Message to send to the team chat') + + args = parser.parse_args() + + print("=== Team Chats Functionality Test ===") + print(f"API URL: {args.api_url}") + print(f"Model: {args.model}") + print(f"User ID: {args.user_id}") + print() + + # Test health endpoint + print("=== Testing Health Endpoint ===") + health_success = test_health(args.api_url) + print() + + if not health_success: + print("❌ Health check failed. Aborting tests.") + sys.exit(1) + + # Test creating a team chat + print("=== Creating Team Chat ===") + chat_success, chat_id = test_create_team_chat( + args.api_url, + args.user_id, + f"Team Chat Test {time.strftime('%Y-%m-%d %H:%M:%S')}", + args.model + ) + print() + + if not chat_success or not chat_id: + print("❌ Failed to create team chat. Aborting tests.") + sys.exit(1) + + # Test adding a team member + print("=== Adding Team Member ===") + member_success = test_add_team_member(args.api_url, chat_id, args.second_user_id) + print() + + # Test sending a message to the team chat + print("=== Sending Message to Team Chat ===") + message_success = test_send_team_message(args.api_url, chat_id, args.user_id, args.message) + print() + + # Test getting user chats + print("=== Getting User Chats ===") + chats_success, chats = test_get_user_chats(args.api_url, args.user_id) + print() + + # Print summary + print("=== Test Summary ===") + print(f"Health Endpoint: {'✅ SUCCESS' if health_success else '❌ FAILED'}") + print(f"Create Team Chat: {'✅ SUCCESS' if chat_success else '❌ FAILED'}") + print(f"Add Team Member: {'✅ SUCCESS' if member_success else '❌ FAILED'}") + print(f"Send Team Message: {'✅ SUCCESS' if message_success else '❌ FAILED'}") + print(f"Get User Chats: {'✅ SUCCESS' if chats_success else '❌ FAILED'}") + + if chat_success and chat_id: + print(f"\nCreated team chat ID: {chat_id}") + print("You can now check the OpenWebUI interface to see if the channel was created") + print("and if the message was sent to the channel.") + print(f"OpenWebUI URL: http://104.225.217.215:8080/") + +if __name__ == "__main__": + main() diff --git a/tunnel_pids.txt b/tunnel_pids.txt new file mode 100644 index 0000000..125ce9e --- /dev/null +++ b/tunnel_pids.txt @@ -0,0 +1,2 @@ +97911 +97914