feat: Add OpenAI and Azure AI API endpoints with connection testing functionality

This commit is contained in:
Christian Krakau-Louis
2025-04-09 07:08:38 +02:00
parent ce73f89da2
commit b258dd2f29
13 changed files with 308 additions and 44 deletions
+4
View File
@@ -11,6 +11,8 @@ from app.api.process import router as process_router
from app.api.diagnostic import router as diagnostic_router
from app.api.onedrive import router as onedrive_router
from app.api.dropbox import router as dropbox_router
from app.api.openai import router as openai_router
from app.api.azure import router as azure_router
# Set up logging
logger = logging.getLogger(__name__)
@@ -25,3 +27,5 @@ router.include_router(process_router)
router.include_router(diagnostic_router)
router.include_router(onedrive_router)
router.include_router(dropbox_router)
router.include_router(openai_router)
router.include_router(azure_router)
+124
View File
@@ -0,0 +1,124 @@
"""
Azure AI API endpoints
"""
from fastapi import APIRouter, Request, HTTPException, status
import logging
import os
from app.auth import require_login
from app.config import settings
# Import the Azure modules including the administration client
from azure.core.credentials import AzureKeyCredential
from azure.ai.documentintelligence import DocumentIntelligenceClient
from azure.ai.documentintelligence import DocumentIntelligenceAdministrationClient
import azure.core.exceptions
# Set up logging
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/azure/test")
@require_login
async def test_azure_connection(request: Request):
"""
Test if the configured Azure Document Intelligence connection is valid.
Uses the DocumentIntelligenceAdministrationClient for testing the connection.
"""
try:
logger.info("Testing Azure Document Intelligence connection")
# Check if Azure configuration is present
if not settings.azure_endpoint or not settings.azure_ai_key:
logger.warning("Azure Document Intelligence configuration is incomplete")
missing = []
if not settings.azure_endpoint:
missing.append("endpoint")
if not settings.azure_ai_key:
missing.append("API key")
return {
"status": "error",
"message": f"Azure Document Intelligence configuration is incomplete. Missing: {', '.join(missing)}"
}
# Try to initialize the admin client and make a request to list operations
try:
# Initialize the admin client with credentials
admin_client = DocumentIntelligenceAdministrationClient(
endpoint=settings.azure_endpoint,
credential=AzureKeyCredential(settings.azure_ai_key)
)
# Test the connection by listing operations - this is a documented method in the admin client
operations = list(admin_client.list_operations())
# Successfully initialized client and made a request
logger.info("Azure Document Intelligence Admin connection successfully tested")
# Return success with available operations info
operations_info = []
try:
for op in operations:
if hasattr(op, 'operation_id') and op.operation_id:
op_info = {
"id": op.operation_id,
"status": op.status if hasattr(op, 'status') else "Unknown",
"created": str(op.created_on) if hasattr(op, 'created_on') else "Unknown",
"kind": op.kind if hasattr(op, 'kind') else "Unknown"
}
operations_info.append(op_info)
operation_count = len(operations_info)
return {
"status": "success",
"message": f"Azure Document Intelligence connection is valid. Found {operation_count} operations.",
"endpoint": settings.azure_endpoint,
"operations_count": operation_count,
"recent_operations": operations_info[:3] if operations_info else []
}
except Exception as e:
# If error occurs while processing operations info, still return success
logger.warning(f"Connected to Azure but couldn't parse operations: {e}")
return {
"status": "success",
"message": "Azure Document Intelligence connection is valid, but couldn't retrieve operations details.",
"endpoint": settings.azure_endpoint
}
except azure.core.exceptions.ClientAuthenticationError as e:
logger.error(f"Azure authentication error: {e}")
return {
"status": "error",
"message": f"Authentication error: Invalid API key or credentials",
"detail": str(e)
}
except azure.core.exceptions.ServiceRequestError as e:
logger.error(f"Azure service request error: {e}")
return {
"status": "error",
"message": f"Service request error: Could not reach the Azure endpoint",
"detail": str(e)
}
except ValueError as e:
logger.error(f"Azure configuration value error: {e}")
return {
"status": "error",
"message": f"Configuration error: {str(e)}",
"detail": str(e)
}
except Exception as e:
logger.error(f"Azure connection test failed with unexpected error: {e}")
return {
"status": "error",
"message": f"Connection test failed with unexpected error",
"detail": str(e)
}
except Exception as e:
logger.exception("Unexpected error testing Azure Document Intelligence connection")
return {
"status": "error",
"message": f"Unexpected error: {str(e)}"
}
+3
View File
@@ -31,12 +31,15 @@ async def diagnostic_settings(request: Request, current_user: dict = Depends(get
"email": bool(getattr(settings, 'email_host', None)),
"s3": bool(getattr(settings, 's3_bucket_name', None)),
"dropbox": bool(getattr(settings, 'dropbox_refresh_token', None)),
"onedrive": bool(getattr(settings, 'onedrive_refresh_token', None)),
"nextcloud": bool(getattr(settings, 'nextcloud_upload_url', None)),
"sftp": bool(getattr(settings, 'sftp_host', None)),
"paperless": bool(getattr(settings, 'paperless_host', None)),
"google_drive": bool(getattr(settings, 'google_drive_credentials_json', None)),
"uptime_kuma": bool(getattr(settings, 'uptime_kuma_url', None)),
"auth": bool(getattr(settings, 'authentik_config_url', None)),
"openai": bool(getattr(settings, 'openai_api_key', None)),
"azure": bool(getattr(settings, 'azure_api_key', None) and getattr(settings, 'azure_endpoint', None)),
},
"imap_enabled": bool(getattr(settings, 'imap1_host', None) or getattr(settings, 'imap2_host', None)),
}
+75
View File
@@ -0,0 +1,75 @@
"""
OpenAI API endpoints
"""
from fastapi import APIRouter, Request, HTTPException, status
import logging
import os
import requests
from app.auth import require_login
from app.config import settings
# Set up logging
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/openai/test")
@require_login
async def test_openai_connection(request: Request):
"""
Test if the configured OpenAI API key is valid.
"""
try:
import openai
logger.info("Testing OpenAI API key validity")
# Check if API key is configured
if not settings.openai_api_key:
logger.warning("No OpenAI API key configured")
return {
"status": "error",
"message": "No OpenAI API key is configured"
}
# Configure the client
client = openai.OpenAI(api_key=settings.openai_api_key)
# Try to make a simple request to validate the key
try:
# Use a models list endpoint as a simple validation
models = client.models.list()
# If we got here, the key is valid
logger.info("OpenAI API key is valid")
return {
"status": "success",
"message": "OpenAI API key is valid",
"models_available": len(models.data) if hasattr(models, "data") else "Unknown"
}
except Exception as e:
error_msg = str(e)
logger.error(f"OpenAI API key test failed: {error_msg}")
# Determine if this is an authentication error
is_auth_error = "auth" in error_msg.lower() or "api key" in error_msg.lower()
return {
"status": "error",
"message": f"API key validation failed: {error_msg}",
"is_auth_error": is_auth_error
}
except ImportError:
logger.exception("OpenAI package not installed")
return {
"status": "error",
"message": "OpenAI package not installed"
}
except Exception as e:
logger.exception("Unexpected error testing OpenAI connection")
return {
"status": "error",
"message": f"Unexpected error: {str(e)}"
}