feat: enhance HTTP API examples with retry logic and automatic user creation

Major improvements to HTTP API examples:

- Add intelligent retry logic for fetching research results (up to 2 minutes)
- Implement automatic user creation for out-of-the-box functionality
- Fix API endpoint usage (/api/start_research instead of /research/api/start)
- Add proper CSRF token handling and authentication flow
- Create comprehensive documentation with environment variable configuration
- Add progress monitoring and detailed status reporting
- Include remote Ollama and SearXNG configuration examples
- Provide multiple example scripts for different use cases
- Use pathlib.Path instead of os.path for modern Python practice

Examples now work completely out of the box without manual user setup
and include proper error handling and user guidance throughout the process.
This commit is contained in:
LearningCircuit
2025-10-31 23:48:01 +01:00
parent ccd809dbe3
commit ddcd962a7e
5 changed files with 758 additions and 334 deletions

View File

@@ -17,7 +17,7 @@ Since LDR v2.0, all API access requires authentication due to per-user encrypted
- `retriever_usage_example.py` - Using LangChain retrievers with LDR
- **`http/`** - HTTP REST API usage (requires running server)
- `working_api_example.py` - ✅ **WORKING EXAMPLE** - Tested and ready to use
- `simple_working_example.py` - ✅ **BEST WORKING EXAMPLE** - Clean, tested, and ready to use
- `simple_http_example.py` - Quick start example (needs updating for auth)
- `http_api_examples.py` - Comprehensive examples including batch processing
@@ -45,21 +45,40 @@ with get_user_db_session(username="your_username", password="your_password") as
### HTTP API (REST)
First, start the server:
**🎯 Quick Start - Works Completely Out of the Box!**
Our tested working example requires zero manual setup:
```bash
# 1. Start the server
python -m local_deep_research.web.app
# 2. Run the working example (creates user automatically!)
python examples/api_usage/http/simple_working_example.py
# 3. Done! ✅ No other steps required
```
Then authenticate and use the API:
The example will:
- ✅ Create a unique test user automatically
- ✅ Test authentication with proper CSRF handling
- ✅ Execute a research query using the correct API endpoint
- ✅ Provide credentials for manual testing (if desired)
- ✅ Show results with direct links to view them
**📋 Manual API Usage:**
If you want to integrate the API into your own code:
```python
import requests
from bs4 import BeautifulSoup
# Create session for cookie persistence
session = requests.Session()
# Login - get CSRF token first
login_page = session.get("http://localhost:5000/auth/login")
from bs4 import BeautifulSoup
soup = BeautifulSoup(login_page.text, 'html.parser')
csrf_input = soup.find('input', {'name': 'csrf_token'})
login_csrf = csrf_input.get('value')
@@ -86,6 +105,12 @@ response = session.post(
print(response.json())
```
**⚠️ Important Notes:**
- Use the correct endpoint: `/api/start_research` (not `/research/api/start`)
- Login with form data (not JSON)
- Handle CSRF tokens properly
- User must be created through web interface first
## Which API Should I Use?
- **Programmatic API**: Use when integrating LDR into your Python application

View File

@@ -0,0 +1,209 @@
# HTTP API Examples
This directory contains working examples for using the LDR HTTP API with authentication.
## 🚀 Quick Start
### 1. Start the LDR Server
```bash
# Option 1: Direct startup
python -m local_deep_research.web.app
# Option 2: Use the restart script (recommended)
bash scripts/dev/restart_server.sh
# Option 3: Docker compose
docker-compose up -d
```
### 2. Run the Simple Working Example
```bash
# This example works completely out of the box!
python simple_working_example.py
```
## 📁 Available Examples
### 🎯 `simple_working_example.py` - BEST FOR STARTING
-**Works completely out of the box**
-**Automatic user creation** (no manual setup needed)
-**Correct API endpoints** and authentication
-**Tested and verified** to work
- ⏱️ **Runtime:** 2-10 minutes (research processing time)
**Perfect for:** First-time users, testing if API works, quick demos
### 📚 `simple_http_example.py` - LEARNING GUIDE
-**Automatic user creation**
- 📊 **Multiple API examples** (research, settings, history)
- 🔍 **Progress monitoring** with status updates
- ⏱️ **Runtime:** 3-15 minutes (more comprehensive testing)
**Perfect for:** Learning different API endpoints, understanding the full API surface
### 🚀 `http_api_examples.py` - ADVANCED CLIENT
- 🔧 **Reusable client class** for integration
- 📈 **Advanced features** (batch processing, polling)
- 🎛️ **Comprehensive patterns** for production use
- ⏱️ **Runtime:** 5-30 minutes (extensive testing)
**Perfect for:** Building applications, production integration, advanced use cases
### 🛠️ `curl_examples.sh` - SHELL/CURL EXAMPLES
- 🔧 **Command-line examples** using curl
- 📝 **Shell script format** for automation
- 🔤 **Pure HTTP requests** (no Python needed)
**Perfect for:** Testing from command line, integration with other tools
## ⚙️ Configuration
### Environment Variables
You can configure the LDR service endpoints using environment variables:
```bash
# For local Ollama (default)
export LDR_LLM_OLLAMA_URL=http://localhost:11434
# For remote Ollama server
export LDR_LLM_OLLAMA_URL=http://192.168.178.66:11434
# For Docker compose service names
export LDR_LLM_OLLAMA_URL=http://ollama:11434
# For Docker with host networking
export LDR_LLM_OLLAMA_URL=http://host.docker.internal:11434
```
### Docker Compose
In your `docker-compose.yml`, you can set the Ollama URL:
```yaml
services:
ldr:
environment:
# For service name (recommended for docker-compose)
- LDR_LLM_OLLAMA_URL=http://ollama:11434
# For remote Ollama instance
# - LDR_LLM_OLLAMA_URL=http://192.168.178.66:11434
# For host machine Ollama
# - LDR_LLM_OLLAMA_URL=http://host.docker.internal:11434
```
### Common Network Scenarios
| Scenario | Environment Variable | When to Use |
|----------|---------------------|-------------|
| **Local Ollama** | `http://localhost:11434` | Running Ollama on same machine |
| **Remote Ollama** | `http://IP:11434` | Ollama on different server |
| **Docker Compose** | `http://ollama:11434` | Using docker-compose service names |
| **Docker Host** | `http://host.docker.internal:11434` | Docker container accessing host Ollama |
## 🔍 Monitoring Progress
### Server Logs
```bash
# Monitor real-time progress
tail -f /tmp/ldr_server.log
# Check recent logs
tail -20 /tmp/ldr_server.log
```
### Web Interface
- **Research Results:** http://localhost:5000/results/{research_id}
- **Settings:** http://localhost:5000/settings
- **History:** http://localhost:5000/history
## 🚨 Troubleshooting
### Common Issues
**❌ "Cannot connect to server"**
```bash
# Start the server first
python -m local_deep_research.web.app
# or
bash scripts/dev/restart_server.sh
```
**❌ "Authentication failed"**
- The examples create users automatically, so this shouldn't happen
- If it does, check that the server is running correctly
**❌ "Research failed"**
```bash
# Check server logs for details
tail -f /tmp/ldr_server.log
# Common issues:
# - Ollama not running or wrong URL
# - Model not available in Ollama
# - Network connectivity issues
```
**❌ "No output from script"**
- Scripts may take 2-10 minutes to complete research
- Monitor progress in server logs
- Check if research started successfully
### Model Configuration
Make sure your Ollama has the required models:
```bash
# List available models
ollama list
# Pull a model if needed
ollama pull gemma3:12b
ollama pull llama3
ollama pull mistral
```
## 📚 What Each Example Demonstrates
### simple_working_example.py
- ✅ User creation and authentication
- ✅ Basic research request
- ✅ Proper CSRF token handling
- ✅ Result URL generation
### simple_http_example.py
- ✅ All of the above PLUS:
- ✅ Settings management
- ✅ Research history
- ✅ Progress polling
- ✅ Multiple research examples
### http_api_examples.py
- ✅ All of the above PLUS:
- ✅ Batch processing
- ✅ Advanced polling strategies
- ✅ Error handling patterns
- ✅ Production-ready client class
### curl_examples.sh
- ✅ Pure HTTP requests
- ✅ Command-line integration
- ✅ No dependencies needed
## 🎯 Recommended Usage Path
1. **Start with `simple_working_example.py`** - Verify everything works
2. **Try `simple_http_example.py`** - Learn the API surface
3. **Use `http_api_examples.py`** - Build your application
4. **Reference `curl_examples.sh`** - For command-line integration
## 🔗 Related Documentation
- [Main API Documentation](../README.md)
- [API Quick Start](../../docs/api-quickstart.md)
- [Docker Configuration](../../../docker-compose.yml)
- [Troubleshooting Guide](../../docs/TROUBLESHOOTING.md)

View File

@@ -1,28 +1,102 @@
#!/usr/bin/env python3
"""
Simple HTTP API Example for Local Deep Research v2.0+
Simple HTTP API Example for Local Deep Research v1.0+
This example shows how to use the LDR API with authentication.
Requires LDR v2.0+ with authentication features.
Works completely out of the box with automatic user creation.
"""
import requests
import time
import sys
from bs4 import BeautifulSoup
from pathlib import Path
# Add the src directory to Python path for programmatic user creation
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
from local_deep_research.database.encrypted_db import DatabaseManager
from local_deep_research.database.models import User
from local_deep_research.database.auth_db import get_auth_db_session
# Configuration
API_URL = "http://localhost:5000"
USERNAME = "your_username" # Change this!
PASSWORD = "your_password" # Change this!
def create_test_user():
"""Create a test user programmatically."""
username = f"testuser_{int(time.time())}"
password = "testpassword123"
print(f"Creating test user: {username}")
try:
# Create user in auth database
auth_db = get_auth_db_session()
new_user = User(username=username)
auth_db.add(new_user)
auth_db.commit()
auth_db.close()
# Create encrypted database for user
db_manager = DatabaseManager()
db_manager.create_user_database(username, password)
print(f"✅ User created successfully: {username}")
return username, password
except Exception as e:
print(f"❌ Failed to create user: {e}")
return None, None
def main():
print("=== LDR HTTP API Example ===")
print("🎯 This example works completely out of the box!\n")
print("⚠️ IMPORTANT NOTES:")
print(" • This script may take several minutes to complete")
print(" • Research progress can be monitored in the server logs")
print(" • Server logs are available at: /tmp/ldr_server.log")
print(
" • Use 'tail -f /tmp/ldr_server.log' to monitor progress in real-time"
)
print(" • Results will be available at the URL shown when complete\n")
# Check if server is running
try:
response = requests.get(f"{API_URL}/", timeout=5)
if response.status_code != 200:
print("❌ Server is not responding correctly")
print("\n📋 HOW TO START THE SERVER:")
print(" • Option 1: python -m local_deep_research.web.app")
print(
" • Option 2: bash scripts/dev/restart_server.sh (recommended)"
)
print(
" • Note: restart_server.sh will kill existing server process"
)
sys.exit(1)
print("✅ Server is running")
except Exception:
print(
"❌ Cannot connect to server. Please make sure it's running on http://localhost:5000"
)
print("\n📋 HOW TO START THE SERVER:")
print(" • Option 1: python -m local_deep_research.web.app")
print(" • Option 2: bash scripts/dev/restart_server.sh (recommended)")
print(" • Note: restart_server.sh will kill existing server process")
sys.exit(1)
# Create test user automatically
username, password = create_test_user()
if not username:
print("❌ Failed to create test user")
sys.exit(1)
# Create a session to persist cookies
session = requests.Session()
print("=== LDR HTTP API Example ===")
print(f"Connecting to: {API_URL}")
print(f"\nTesting with user: {username}")
# Step 1: Login
print("\n1. Authenticating...")
@@ -41,8 +115,8 @@ def main():
login_response = session.post(
f"{API_URL}/auth/login",
data={
"username": USERNAME,
"password": PASSWORD,
"username": username,
"password": password,
"csrf_token": login_csrf,
},
allow_redirects=False,
@@ -52,8 +126,6 @@ def main():
print(f"❌ Login failed: {login_response.text}")
print("\nPlease ensure:")
print("- The server is running: python -m local_deep_research.web.app")
print("- You have created an account through the web interface")
print("- You have updated USERNAME and PASSWORD in this script")
sys.exit(1)
print("✅ Login successful")
@@ -65,8 +137,16 @@ def main():
headers = {"X-CSRF-Token": csrf_token}
print("✅ CSRF token obtained")
# Initialize research_id to None
research_id = None
# Example 1: Quick Summary (using the start endpoint)
print("\n=== Example 1: Quick Summary ===")
print(
"📝 This example demonstrates starting a research query and polling for results"
)
print("⏱️ This typically takes 1-3 minutes to complete\n")
research_request = {
"query": "What is machine learning?",
"model": None, # Will use default from settings
@@ -76,6 +156,7 @@ def main():
}
# Start research - CORRECT ENDPOINT
print("🚀 Starting research...")
start_response = session.post(
f"{API_URL}/api/start_research", json=research_request, headers=headers
)
@@ -86,28 +167,71 @@ def main():
research_data = start_response.json()
research_id = research_data["research_id"]
print(f"✅ Research started with ID: {research_id}")
print("✅ Research started successfully!")
print(f"🆔 Research ID: {research_id}")
print("📊 Monitor progress in server logs: tail -f /tmp/ldr_server.log")
print(f"🌐 Results will be available at: {API_URL}/results/{research_id}\n")
# Poll for results
print("\nWaiting for results...")
while True:
print("Waiting for research to complete...")
print(
"⚠️ NOTE: This will poll for up to 3 minutes to ensure research completes"
)
print(
" If it fails, the research may still be running - check the results URL\n"
)
poll_count = 0
max_polls = 18 # Maximum 3 minutes (18 * 10 seconds)
while poll_count < max_polls:
status_response = session.get(
f"{API_URL}/research/api/research/{research_id}/status"
f"{API_URL}/api/research/{research_id}/status"
)
if status_response.status_code == 200:
status = status_response.json()
print(f" Status: {status.get('status', 'unknown')}")
current_status = status.get("status", "unknown")
progress = status.get("progress", 0)
if status.get("status") == "completed":
poll_count += 1
elapsed_time = poll_count * 10 # 10 seconds per poll
print(
f" Check {poll_count} ({elapsed_time}s): Status = {current_status} (Progress: {progress}%)"
)
if current_status == "completed":
print("🎉 Research completed successfully!")
break
elif status.get("status") == "failed":
elif current_status == "failed":
print(
f"❌ Research failed: {status.get('error', 'Unknown error')}"
)
print(
"📋 Check server logs for details: tail -f /tmp/ldr_server.log"
)
sys.exit(1)
elif current_status in ["queued", "in_progress"]:
# Continue polling
pass
else:
print(f"⚠️ Unexpected status: {current_status}")
time.sleep(2)
else:
print(
f"⚠️ Status check failed with code: {status_response.status_code}"
)
time.sleep(10) # Wait 10 seconds between polls
if poll_count >= max_polls:
print("⏰ 3-minute timeout reached - research is still running")
print("💡 This is normal for complex research queries!")
print(f"📊 Check results later at: {API_URL}/results/{research_id}")
print("📋 Monitor progress with: tail -f /tmp/ldr_server.log")
print(
"🔍 The script will still try to fetch results (may be incomplete)"
)
# Get results
results_response = session.get(
@@ -148,18 +272,147 @@ def main():
f"- {item.get('query', 'Unknown query')} ({item.get('created_at', 'Unknown date')})"
)
# Example 4: Get and Display Research Results (with retry logic)
print("\n=== Example 4: Research Results ===")
if research_id:
print(f"📄 Fetching research results for ID: {research_id}")
print(
"🔄 Will retry until results are available (up to 2 additional minutes)\n"
)
# Retry fetching results until available
results_retries = 0
max_results_retries = 12 # 2 minutes (12 * 10 seconds)
while results_retries < max_results_retries:
results_response = session.get(
f"{API_URL}/api/research/{research_id}/report"
)
if results_response.status_code == 200:
# Results are available, parse and display them
results = results_response.json()
content = results.get("content", "")
sources = results.get("sources", [])
findings = results.get("findings", [])
print(
f"✅ Results retrieved successfully after {(results_retries + 1) * 10} seconds!"
)
print("\n📝 RESEARCH SUMMARY:")
print("=" * 50)
if content:
# Show first 500 characters of the summary
summary_preview = (
content[:500] + "..." if len(content) > 500 else content
)
print(summary_preview)
else:
print("No summary content available")
print(f"\n📚 SOURCES FOUND: {len(sources)}")
for i, source in enumerate(
sources[:3], 1
): # Show first 3 sources
title = source.get("title", "Unknown Title")
url = source.get("url", "No URL")
print(f" {i}. {title}")
print(f" {url}")
if len(sources) > 3:
print(f" ... and {len(sources) - 3} more sources")
print(f"\n🔍 KEY FINDINGS: {len(findings)}")
for i, finding in enumerate(
findings[:3], 1
): # Show first 3 findings
finding_text = finding.get("text", "No finding text")
finding_preview = (
finding_text[:150] + "..."
if len(finding_text) > 150
else finding_text
)
print(f" {i}. {finding_preview}")
if len(findings) > 3:
print(f" ... and {len(findings) - 3} more findings")
print(
f"\n🌐 View full results at: {API_URL}/results/{research_id}"
)
print("=" * 50)
print("🎉 Results displayed successfully!")
break # Exit retry loop - success!
elif results_response.status_code == 404:
results_retries += 1
elapsed_time = results_retries * 10
print(
f" Retry {results_retries}/{max_results_retries} ({elapsed_time}s): Results not ready yet, waiting..."
)
time.sleep(10) # Wait 10 seconds before retrying
else:
print(
f"❌ Failed to fetch results: {results_response.status_code}"
)
print(f"Response: {results_response.text[:200]}")
break # Exit retry loop - error
# Handle case where max retries reached
if results_retries >= max_results_retries:
print(
f"\n⏰ Maximum retry time reached ({max_results_retries * 10} seconds)"
)
print("💡 This is normal for complex research queries!")
print(f"📊 Check results later at: {API_URL}/results/{research_id}")
print("📋 Monitor progress with: tail -f /tmp/ldr_server.log")
print(
"🔍 The research is still running - results will be available when complete"
)
else:
print(
"⚠️ No research ID available - research may not have started properly"
)
# Logout
print("\n4. Logging out...")
print("\n5. Logging out...")
session.post(f"{API_URL}/auth/logout", headers=headers)
print("✅ Logged out successfully")
if __name__ == "__main__":
print("Make sure the LDR server is running:")
print(" python -m local_deep_research.web.app\n")
print("🎯 Simple LDR HTTP API Example - Works out of the box!")
print("⚡ This script creates a user automatically and tests the API")
print(
"⏱️ Total runtime: Up to 3 minutes polling + 2 minutes results retry + research time"
)
print(
"🔄 Automatically retries fetching results until available (up to 2 minutes)\n"
)
if USERNAME == "your_username":
print("⚠️ WARNING: Please update USERNAME and PASSWORD in this script!")
print(" Create an account through the web interface first.\n")
print("📋 REQUIREMENTS:")
print(" • LDR server running")
print(" • Beautiful Soup: pip install beautifulsoup4\n")
print("🚀 START THE SERVER:")
print(" • Option 1: python -m local_deep_research.web.app")
print(" • Option 2: bash scripts/dev/restart_server.sh (recommended)")
print(" • Note: restart_server.sh will kill existing server process\n")
print("📊 MONITORING:")
print(" • Server logs: tail -f /tmp/ldr_server.log")
print(" • This script polls for up to 3 minutes")
print(" • If research takes longer, script shows where to check results\n")
print("⏰ TIMING INFO:")
print(" • Script polls for 3 minutes to let research complete")
print(" • Then retries fetching results for up to 2 additional minutes")
print(" • Research typically completes in 2-10 minutes")
print(" • Script displays results automatically when available")
print(
" • If timeout reached, results URL provided for checking completion\n"
)
main()

View File

@@ -0,0 +1,242 @@
#!/usr/bin/env python3
"""
Simple Working HTTP API Example for Local Deep Research v1.0+
This is a clean, working example that demonstrates the correct way to use the LDR API.
It creates a user automatically and handles authentication properly.
Requirements:
- LDR v1.0+ server running: python -m local_deep_research.web.app
- Beautiful Soup: pip install beautifulsoup4
This example works COMPLETELY out of the box - no manual setup required!
"""
import requests
from bs4 import BeautifulSoup
import sys
import time
from pathlib import Path
# Add the src directory to Python path for programmatic user creation
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent / "src"))
from local_deep_research.database.encrypted_db import DatabaseManager
from local_deep_research.database.models import User
from local_deep_research.database.auth_db import get_auth_db_session
def create_test_user():
"""Create a test user programmatically - works out of the box!"""
username = f"testuser_{int(time.time())}"
password = "testpassword123"
print(f"Creating test user: {username}")
try:
# Create user in auth database
auth_db = get_auth_db_session()
new_user = User(username=username)
auth_db.add(new_user)
auth_db.commit()
auth_db.close()
# Create encrypted database for user
db_manager = DatabaseManager()
db_manager.create_user_database(username, password)
print(f"✅ User created successfully: {username}")
return username, password
except Exception as e:
print(f"❌ Failed to create user: {e}")
return None, None
def test_api_with_user(username, password):
"""Test the API with the created user."""
print(f"\n=== Testing API with user: {username} ===")
base_url = "http://localhost:5000"
session = requests.Session()
# 1. Test login
print("1. Testing login...")
try:
login_page = session.get(f"{base_url}/auth/login")
if login_page.status_code != 200:
print(f" ❌ Failed to get login page: {login_page.status_code}")
return False
soup = BeautifulSoup(login_page.text, "html.parser")
csrf_input = soup.find("input", {"name": "csrf_token"})
login_csrf = csrf_input.get("value")
if not login_csrf:
print(" ❌ No CSRF token found")
return False
login_response = session.post(
f"{base_url}/auth/login",
data={
"username": username,
"password": password,
"csrf_token": login_csrf,
},
allow_redirects=False,
)
print(f" Login status: {login_response.status_code}")
if login_response.status_code not in [200, 302]:
print(" ❌ Login failed")
return False
print(" ✅ Login successful")
except Exception as e:
print(f" ❌ Login error: {e}")
return False
# 2. Get CSRF token for API
print("\n2. Getting API CSRF token...")
try:
csrf_response = session.get(f"{base_url}/auth/csrf-token")
if csrf_response.status_code != 200:
print(
f" ❌ Failed to get CSRF token: {csrf_response.status_code}"
)
return False
csrf_data = csrf_response.json()
csrf_token = csrf_data.get("csrf_token")
if not csrf_token:
print(" ❌ No CSRF token in response")
return False
print(f" ✅ API CSRF token: {csrf_token[:20]}...")
except Exception as e:
print(f" ❌ CSRF token error: {e}")
return False
# 3. Test research API
print("\n3. Testing research API...")
research_request = {
"query": "What is machine learning?",
"model": "gpt-4o-mini",
"search_engines": ["searxng"],
}
headers = {"X-CSRF-Token": csrf_token, "Content-Type": "application/json"}
# Test the correct endpoint
print("\n 3.1 Testing /api/start_research...")
try:
url = f"{base_url}/api/start_research"
response = session.post(url, json=research_request, headers=headers)
print(f" Status: {response.status_code}")
print(f" Response: {response.text[:300]}")
if response.status_code == 200:
try:
data = response.json()
if data.get("status") == "success":
print(" ✅ Research started successfully!")
research_id = data.get("research_id")
if research_id:
print(f" Research ID: {research_id}")
print("\n🎉 SUCCESS! API is working correctly.")
print(
f"📊 View results at: {base_url}/results/{research_id}"
)
return True
elif data.get("status") == "queued":
print(" ✅ Research queued successfully!")
return True
else:
print(
f" ⚠️ Research returned: {data.get('status', 'unknown')}"
)
except Exception:
print(" ⚠️ Response is not valid JSON")
elif response.status_code == 401:
print(" ❌ Authentication failed")
elif response.status_code == 403:
print(" ❌ Forbidden - CSRF token issue")
elif response.status_code == 404:
print(" ❌ Endpoint not found")
elif response.status_code == 500:
print(" ❌ Server error")
print(" Check server logs: tail -f /tmp/ldr_server.log")
else:
print(" ⚠️ Unexpected status code")
except Exception as e:
print(f" ❌ Error testing endpoint: {e}")
return False
def main():
"""Main function that works completely out of the box!"""
print("=== Simple LDR API Working Example ===")
print(
"🎯 This example works completely out of the box - no manual setup required!\n"
)
# Check if server is running
try:
response = requests.get("http://localhost:5000/", timeout=5)
if response.status_code != 200:
print("❌ Server is not responding correctly")
print("\nPlease start the server:")
print(" python -m local_deep_research.web.app")
sys.exit(1)
print("✅ Server is running")
except Exception:
print(
"❌ Cannot connect to server. Please make sure it's running on http://localhost:5000"
)
print("\nStart the server with:")
print(" python -m local_deep_research.web.app")
sys.exit(1)
# Create test user automatically
username, password = create_test_user()
if not username:
print("❌ Failed to create test user")
sys.exit(1)
# Test API
success = test_api_with_user(username, password)
if success:
print("\n✅ API test completed successfully")
print(f"\n🔑 Created user: {username}")
print("📝 You can now use this user for manual testing:")
print(f" Username: {username}")
print(f" Password: {password}")
print(" Login URL: http://localhost:5000/auth/login")
print("\nNext steps:")
print("- Try different research queries")
print("- Explore other API endpoints")
print("- Check out the web interface at http://localhost:5000")
print("- Use the credentials above to log in manually")
sys.exit(0)
else:
print("\n❌ API test failed")
print("\nTroubleshooting:")
print(
"- Make sure the server is running: python -m local_deep_research.web.app"
)
print("- Check server logs for errors: tail -f /tmp/ldr_server.log")
print("- Ensure all dependencies are installed")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -1,305 +0,0 @@
#!/usr/bin/env python3
"""
Working HTTP API Example for Local Deep Research v2.0+
This is a tested, working example that demonstrates proper API usage.
It handles authentication correctly and uses the right endpoints.
Requirements:
- LDR v2.0+ (with authentication features)
- User account created through web interface at http://localhost:5000/auth/register
- LDR server running: python -m local_deep_research.web.app
- Beautiful Soup: pip install beautifulsoup4
"""
import time
import sys
from typing import Optional, Dict, Any
import requests
from bs4 import BeautifulSoup
class LDRClient:
"""Working client for interacting with LDR API v2.0+ with proper authentication"""
def __init__(self, base_url: str = "http://localhost:5000"):
self.base_url = base_url
self.session = requests.Session()
self.csrf_token = None
self.username = None
def login(self, username: str, password: str) -> bool:
"""
Authenticate with the LDR server.
Returns True if successful, False otherwise.
"""
try:
# Step 1: Get login page and extract CSRF token
print("📄 Getting login page...")
login_page = self.session.get(f"{self.base_url}/auth/login")
if login_page.status_code != 200:
print(f"❌ Failed to get login page: {login_page.status_code}")
return False
# Extract CSRF token from the login form
soup = BeautifulSoup(login_page.text, "html.parser")
csrf_input = soup.find("input", {"name": "csrf_token"})
login_csrf = csrf_input.get("value") if csrf_input else None
if not login_csrf:
print("❌ No CSRF token found in login page")
return False
# Step 2: Submit login form with CSRF token
print(f"🔐 Logging in as {username}...")
login_response = self.session.post(
f"{self.base_url}/auth/login",
data={
"username": username,
"password": password,
"csrf_token": login_csrf,
},
allow_redirects=False, # Don't follow redirects to see response clearly
)
if login_response.status_code not in [200, 302]:
print(f"❌ Login failed: {login_response.status_code}")
print(f"Response: {login_response.text[:200]}")
return False
self.username = username
print("✅ Login successful")
# Step 3: Get API CSRF token
print("🔑 Getting API CSRF token...")
csrf_response = self.session.get(f"{self.base_url}/auth/csrf-token")
if csrf_response.status_code != 200:
print(
f"❌ Failed to get CSRF token: {csrf_response.status_code}"
)
return False
csrf_data = csrf_response.json()
self.csrf_token = csrf_data.get("csrf_token")
if not self.csrf_token:
print("❌ No CSRF token in API response")
return False
print("✅ Authentication complete")
return True
except Exception as e:
print(f"❌ Login error: {e}")
return False
def start_research(self, query: str, **kwargs) -> Optional[Dict[str, Any]]:
"""
Start a new research query.
Args:
query: The research question
**kwargs: Additional parameters (model, search_engines, etc.)
Returns:
Dict with research_id and status, or None if failed
"""
if not self.csrf_token:
print("❌ Not authenticated - call login() first")
return None
# Default parameters
research_request = {
"query": query,
"model": kwargs.get("model", "gpt-4o-mini"),
"search_engines": kwargs.get("search_engines", ["searxng"]),
"iterations": kwargs.get("iterations", 3),
"questions_per_iteration": kwargs.get("questions_per_iteration", 3),
}
# Add any additional parameters
for key, value in kwargs.items():
if key not in research_request:
research_request[key] = value
headers = {
"X-CSRF-Token": self.csrf_token,
"Content-Type": "application/json",
}
try:
print(f"🔍 Starting research: {query[:50]}...")
# Use the CORRECT endpoint!
response = self.session.post(
f"{self.base_url}/api/start_research", # ✅ CORRECT ENDPOINT
json=research_request,
headers=headers,
)
if response.status_code != 200:
print(f"❌ Failed to start research: {response.status_code}")
print(f"Response: {response.text[:300]}")
return None
data = response.json()
status = data.get("status")
if status == "success":
print("✅ Research started successfully!")
return data
elif status == "queued":
print(
f"⏳ Research queued (position: {data.get('queue_position', 'unknown')})"
)
return data
else:
print(f"❌ Research returned status: {status}")
return None
except Exception as e:
print(f"❌ Error starting research: {e}")
return None
def get_research_status(self, research_id: str) -> Optional[Dict[str, Any]]:
"""Get the status of a research query."""
try:
response = self.session.get(
f"{self.base_url}/api/research/{research_id}/status"
)
if response.status_code != 200:
print(f"❌ Failed to get status: {response.status_code}")
return None
return response.json()
except Exception as e:
print(f"❌ Error getting status: {e}")
return None
def wait_for_completion(
self, research_id: str, timeout: int = 300
) -> Optional[Dict[str, Any]]:
"""
Wait for research to complete.
Args:
research_id: The research ID to wait for
timeout: Maximum time to wait in seconds
Returns:
Final status data or None if timed out
"""
start_time = time.time()
while time.time() - start_time < timeout:
status = self.get_research_status(research_id)
if not status:
time.sleep(2)
continue
status_code = status.get("status")
progress = status.get("progress", 0)
if status_code == "completed":
print("✅ Research completed!")
return status
elif status_code == "failed":
print("❌ Research failed")
return status
elif status_code in ["in_progress", "queued"]:
print(f"⏳ Status: {status_code} (Progress: {progress}%)")
time.sleep(3)
else:
print(f"❓ Unknown status: {status_code}")
time.sleep(3)
print(f"⏰ Timeout after {timeout} seconds")
return None
def get_research_report(self, research_id: str) -> Optional[Dict[str, Any]]:
"""Get the final research report."""
try:
response = self.session.get(
f"{self.base_url}/api/research/{research_id}/report"
)
if response.status_code != 200:
print(f"❌ Failed to get report: {response.status_code}")
return None
return response.json()
except Exception as e:
print(f"❌ Error getting report: {e}")
return None
def main():
"""Demonstration of the LDR API usage."""
print("=== Local Deep Research API Example ===\n")
# Configuration - UPDATE THESE
USERNAME = "your_username" # ⚠️ Change this!
PASSWORD = "your_password" # ⚠️ Change this!
if USERNAME == "your_username" or PASSWORD == "your_password":
print("⚠️ Please update USERNAME and PASSWORD in this script!")
print(" 1. Start the server: python -m local_deep_research.web.app")
print(" 2. Visit http://localhost:5000/auth/register")
print(" 3. Create an account and update the credentials below\n")
# Create client and login
client = LDRClient()
if not client.login(USERNAME, PASSWORD):
print(
"\n❌ Login failed. Please check your credentials and that the server is running."
)
print("💡 Create an account at: http://localhost:5000/auth/register")
sys.exit(1)
# Example 1: Quick research
print("\n=== Example 1: Quick Research ===")
result = client.start_research(
"What is quantum computing?",
search_engines=["wikipedia"], # Fast for demo
iterations=1,
questions_per_iteration=2,
)
if result:
research_id = result.get("research_id")
print(f"📋 Research ID: {research_id}")
# Wait for completion
final_status = client.wait_for_completion(research_id, timeout=120)
if final_status and final_status.get("status") == "completed":
# Get the report
report = client.get_research_report(research_id)
if report:
content = report.get("content", "")
print(f"\n📝 Summary: {content[:300]}...")
# Example 2: Another query
print("\n=== Example 2: Different Query ===")
result2 = client.start_research(
"What are the benefits of renewable energy?",
model="gpt-4o-mini",
search_engines=["searxng"],
)
if result2:
print(f"📋 Research ID: {result2.get('research_id')}")
print("📝 Check the web interface at http://localhost:5000 for results")
print("\n✅ Examples completed!")
print("🌐 View all results at: http://localhost:5000/history")
if __name__ == "__main__":
main()