moar files for debugging

This commit is contained in:
2025-09-17 20:01:28 +02:00
parent 3bd78b5251
commit f088ed5bc9
2 changed files with 472 additions and 0 deletions

View File

@@ -0,0 +1,379 @@
"use client"
import { useState, useEffect } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Badge } from "@/components/ui/badge"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { ProtectedRoute } from "@/components/auth/ProtectedRoute"
import { apiClient } from "@/lib/api-client"
import { Bug, Database, Search, CheckCircle, XCircle, AlertCircle } from "lucide-react"
interface SystemStatus {
database: string
modules: Record<string, any>
redis: string
qdrant: string
timestamp: string
}
interface ChatbotConfig {
chatbot: {
id: string
name: string
type: string
description: string
created_at: string
is_active: boolean
conversation_count: number
}
prompt_template: {
type: string | null
system_prompt: string | null
variables: any[]
}
rag_collections: any[]
configuration: {
max_tokens: number
temperature: number
streaming: boolean
memory_config: any
}
}
interface RagTestResult {
query: string
results: any[]
collections_searched: string[]
result_count: number
error?: string
message?: string
}
export default function DebugPage() {
const [systemStatus, setSystemStatus] = useState<SystemStatus | null>(null)
const [chatbots, setChatbots] = useState<any[]>([])
const [selectedChatbot, setSelectedChatbot] = useState<string>("")
const [chatbotConfig, setChatbotConfig] = useState<ChatbotConfig | null>(null)
const [ragQuery, setRagQuery] = useState("What is security?")
const [ragTest, setRagTest] = useState<RagTestResult | null>(null)
const [loading, setLoading] = useState(false)
useEffect(() => {
loadSystemStatus()
loadChatbots()
}, [])
const loadSystemStatus = async () => {
try {
const response = await apiClient.get("/api-internal/v1/debugging/system/status")
setSystemStatus(response)
} catch (error) {
console.error("Failed to load system status:", error)
}
}
const loadChatbots = async () => {
try {
const response = await apiClient.get("/api-internal/v1/chatbot/list")
setChatbots(response)
if (response.length > 0) {
setSelectedChatbot(response[0].id)
}
} catch (error) {
console.error("Failed to load chatbots:", error)
}
}
const loadChatbotConfig = async (chatbotId: string) => {
setLoading(true)
try {
const response = await apiClient.get(`/api-internal/v1/debugging/chatbot/${chatbotId}/config`)
setChatbotConfig(response)
} catch (error) {
console.error("Failed to load chatbot config:", error)
} finally {
setLoading(false)
}
}
const testRagSearch = async () => {
if (!selectedChatbot) return
setLoading(true)
try {
const response = await apiClient.get(
`/api-internal/v1/debugging/chatbot/${selectedChatbot}/test-rag`,
{ params: { query: ragQuery } }
)
setRagTest(response)
} catch (error) {
console.error("Failed to test RAG search:", error)
} finally {
setLoading(false)
}
}
const getStatusIcon = (status: string) => {
if (status.includes("healthy")) return <CheckCircle className="h-4 w-4 text-green-500" />
if (status.includes("error")) return <XCircle className="h-4 w-4 text-red-500" />
return <AlertCircle className="h-4 w-4 text-yellow-500" />
}
return (
<ProtectedRoute>
<div className="container mx-auto px-4 py-8">
<div className="mb-8">
<h1 className="text-3xl font-bold mb-2">Debugging Dashboard</h1>
<p className="text-muted-foreground">
Troubleshoot and diagnose chatbot issues
</p>
</div>
<Tabs defaultValue="system" className="space-y-6">
<TabsList>
<TabsTrigger value="system">System Status</TabsTrigger>
<TabsTrigger value="chatbot">Chatbot Debug</TabsTrigger>
<TabsTrigger value="rag">RAG Testing</TabsTrigger>
</TabsList>
<TabsContent value="system" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Database className="h-5 w-5" />
System Health Status
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{systemStatus ? (
<div className="grid gap-4">
<div className="flex items-center justify-between p-4 border rounded">
<span className="font-medium">Database</span>
<div className="flex items-center gap-2">
{getStatusIcon(systemStatus.database)}
<span className="text-sm">{systemStatus.database}</span>
</div>
</div>
<div className="flex items-center justify-between p-4 border rounded">
<span className="font-medium">Redis</span>
<div className="flex items-center gap-2">
{getStatusIcon(systemStatus.redis)}
<span className="text-sm">{systemStatus.redis}</span>
</div>
</div>
<div className="flex items-center justify-between p-4 border rounded">
<span className="font-medium">Qdrant</span>
<div className="flex items-center gap-2">
{getStatusIcon(systemStatus.qdrant)}
<span className="text-sm">{systemStatus.qdrant}</span>
</div>
</div>
<div className="mt-6">
<h4 className="font-medium mb-3">Modules Status</h4>
<div className="grid gap-2">
{Object.entries(systemStatus.modules).map(([name, info]: [string, any]) => (
<div key={name} className="flex items-center justify-between p-3 border rounded">
<span className="text-sm font-medium capitalize">{name}</span>
<div className="flex items-center gap-2">
<Badge variant={info.enabled ? "default" : "secondary"}>
{info.enabled ? "Enabled" : "Disabled"}
</Badge>
<Badge variant={info.status === "healthy" ? "default" : "destructive"}>
{info.status}
</Badge>
</div>
</div>
))}
</div>
</div>
</div>
) : (
<p>Loading system status...</p>
)}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="chatbot" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Bug className="h-5 w-5" />
Chatbot Configuration
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex gap-4">
<div className="flex-1">
<label className="text-sm font-medium">Select Chatbot</label>
<select
value={selectedChatbot}
onChange={(e) => {
setSelectedChatbot(e.target.value)
if (e.target.value) {
loadChatbotConfig(e.target.value)
}
}}
className="w-full mt-1 p-2 border rounded"
>
{chatbots.map((bot) => (
<option key={bot.id} value={bot.id}>
{bot.name}
</option>
))}
</select>
</div>
<Button
onClick={() => selectedChatbot && loadChatbotConfig(selectedChatbot)}
disabled={loading || !selectedChatbot}
>
Load Config
</Button>
</div>
{chatbotConfig && (
<div className="space-y-6 mt-6">
<div>
<h4 className="font-medium mb-2">Chatbot Info</h4>
<div className="p-4 border rounded space-y-2 text-sm">
<div><strong>Name:</strong> {chatbotConfig.chatbot.name}</div>
<div><strong>Type:</strong> {chatbotConfig.chatbot.type}</div>
<div><strong>Description:</strong> {chatbotConfig.chatbot.description}</div>
<div><strong>Active:</strong> {chatbotConfig.chatbot.is_active ? "Yes" : "No"}</div>
<div><strong>Conversations:</strong> {chatbotConfig.chatbot.conversation_count}</div>
</div>
</div>
<div>
<h4 className="font-medium mb-2">Configuration</h4>
<div className="p-4 border rounded space-y-2 text-sm">
<div><strong>Max Tokens:</strong> {chatbotConfig.configuration.max_tokens}</div>
<div><strong>Temperature:</strong> {chatbotConfig.configuration.temperature}</div>
<div><strong>Streaming:</strong> {chatbotConfig.configuration.streaming ? "Yes" : "No"}</div>
</div>
</div>
<div>
<h4 className="font-medium mb-2">Prompt Template</h4>
<div className="p-4 border rounded">
<div className="text-sm mb-2">
<strong>Type:</strong> {chatbotConfig.prompt_template.type || "None"}
</div>
{chatbotConfig.prompt_template.system_prompt && (
<div className="mt-3">
<div className="text-sm font-medium mb-1">System Prompt:</div>
<pre className="text-xs bg-muted p-3 rounded overflow-auto max-h-40">
{chatbotConfig.prompt_template.system_prompt}
</pre>
</div>
)}
</div>
</div>
{chatbotConfig.rag_collections.length > 0 && (
<div>
<h4 className="font-medium mb-2">RAG Collections</h4>
<div className="space-y-2">
{chatbotConfig.rag_collections.map((collection) => (
<div key={collection.id} className="p-3 border rounded text-sm">
<div><strong>Name:</strong> {collection.name}</div>
<div><strong>Documents:</strong> {collection.document_count}</div>
<div><strong>Qdrant Collection:</strong> {collection.qdrant_collection_name}</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</CardContent>
</Card>
</TabsContent>
<TabsContent value="rag" className="space-y-6">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<Search className="h-5 w-5" />
RAG Search Test
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div className="flex gap-4">
<div className="flex-1">
<label className="text-sm font-medium">Test Query</label>
<Input
value={ragQuery}
onChange={(e) => setRagQuery(e.target.value)}
placeholder="Enter a test query..."
className="mt-1"
/>
</div>
<Button onClick={testRagSearch} disabled={loading || !selectedChatbot}>
Test Search
</Button>
</div>
{ragTest && (
<div className="mt-6 space-y-4">
<div className="p-4 border rounded">
<h4 className="font-medium mb-2">Test Results</h4>
<div className="text-sm space-y-1">
<div><strong>Query:</strong> {ragTest.query}</div>
<div><strong>Results Found:</strong> {ragTest.result_count}</div>
<div><strong>Collections Searched:</strong> {ragTest.collections_searched.join(", ")}</div>
{ragTest.message && (
<div><strong>Message:</strong> {ragTest.message}</div>
)}
{ragTest.error && (
<div className="text-red-500"><strong>Error:</strong> {ragTest.error}</div>
)}
</div>
</div>
{ragTest.results.length > 0 && (
<div>
<h4 className="font-medium mb-2">Search Results</h4>
<div className="space-y-3 max-h-96 overflow-y-auto">
{ragTest.results.map((result, index) => (
<div key={index} className="p-3 border rounded text-sm">
<div className="flex justify-between items-start mb-2">
<Badge variant="outline">Score: {result.score?.toFixed(3) || "N/A"}</Badge>
{result.collection_name && (
<Badge variant="secondary">{result.collection_name}</Badge>
)}
</div>
<div className="text-xs text-muted-foreground mb-1">
{result.metadata?.source || "Unknown source"}
</div>
<div className="text-sm">
{result.content?.substring(0, 200)}
{result.content?.length > 200 && "..."}
</div>
</div>
))}
</div>
</div>
)}
</div>
)}
</CardContent>
</Card>
</TabsContent>
</Tabs>
<div className="mt-8 p-4 border rounded">
<h3 className="font-medium mb-2">How to Use This Dashboard</h3>
<ul className="text-sm text-muted-foreground space-y-1">
<li> <strong>System Status:</strong> Check if all services (Database, Redis, Qdrant) are healthy</li>
<li> <strong>Chatbot Debug:</strong> View detailed configuration for any chatbot</li>
<li> <strong>RAG Testing:</strong> Test if document search is working correctly</li>
<li> Check browser console logs for detailed request/response debugging information</li>
</ul>
</div>
</div>
</ProtectedRoute>
)
}

93
test_debugging.py Executable file
View File

@@ -0,0 +1,93 @@
#!/usr/bin/env python3
"""
Test script to verify debugging endpoints
"""
import requests
import json
import sys
import os
# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from backend.app.core.security import create_access_token
from backend.app.db.database import SessionLocal
from backend.app.models.user import User
def get_auth_token():
"""Get an authentication token for testing"""
db = SessionLocal()
try:
# Get first user (or create one for testing)
user = db.query(User).first()
if not user:
# Create test user if none exists
user = User(
email="test@example.com",
hashed_password="$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LeZeUfkZMBs9kYZP6" # password: password
)
db.add(user)
db.commit()
db.refresh(user)
# Create JWT token
token = create_access_token(data={"sub": str(user.id)})
return token
finally:
db.close()
def test_endpoint(url, token, method="GET", data=None):
"""Test an endpoint with authentication"""
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}
if method == "GET":
response = requests.get(f"http://localhost:3000{url}", headers=headers)
elif method == "POST":
response = requests.post(f"http://localhost:3000{url}", headers=headers, json=data)
print(f"\n{method} {url}")
print(f"Status: {response.status_code}")
if response.status_code == 200:
print("Response:")
print(json.dumps(response.json(), indent=2))
else:
print("Error:", response.text)
return response
def main():
print("=== Testing Debugging Endpoints ===")
# Get authentication token
print("\n1. Getting authentication token...")
token = get_auth_token()
print(f"Token: {token[:50]}...")
# Test system status
print("\n2. Testing system status...")
test_endpoint("/api-internal/v1/debugging/system/status", token)
# Test getting chatbot list first
print("\n3. Getting chatbot list...")
response = test_endpoint("/api-internal/v1/chatbot/list", token)
if response.status_code == 200:
chatbots = response.json()
if chatbots:
chatbot_id = chatbots[0]["id"]
print(f"\n4. Testing chatbot config for: {chatbot_id}")
test_endpoint(f"/api-internal/v1/debugging/chatbot/{chatbot_id}/config", token)
print(f"\n5. Testing RAG search for: {chatbot_id}")
test_endpoint(f"/api-internal/v1/debugging/chatbot/{chatbot_id}/test-rag?query=What is security?", token)
else:
print("\n4. No chatbots found to test")
else:
print("\n4. Could not get chatbot list")
if __name__ == "__main__":
main()