File size: 6,522 Bytes
a10e62e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
"""
AI Workflows Routes - Alias routes for /api/ai-workflows/* paths
Provides compatibility with various API path conventions
"""
from datetime import datetime
import logging
from typing import Any, Dict, List, Optional
from pydantic import BaseModel, Field

from core.base_routes import BaseAPIRouter

logger = logging.getLogger(__name__)


router = BaseAPIRouter(prefix="/api/ai-workflows", tags=["AI Workflows"])

# Pydantic Models
class NLUParseRequest(BaseModel):
    text: str = Field(..., description="Text to parse")
    provider: str = Field("deepseek", description="AI provider to use")
    intent_only: bool = Field(False, description="Only extract intent")

class NLUParseResponse(BaseModel):
    request_id: str
    text: str
    intent: str
    entities: List[Dict[str, Any]]
    tasks: List[str]
    confidence: float
    provider_used: str
    processing_time_ms: float

class CompletionRequest(BaseModel):
    prompt: str = Field(..., description="Prompt for completion")
    provider: str = Field("deepseek", description="AI provider to use")
    max_tokens: int = Field(500, description="Maximum tokens in response")
    temperature: float = Field(0.7, description="Temperature for sampling")

class CompletionResponse(BaseModel):
    completion: str
    provider_used: str
    tokens_used: int
    processing_time_ms: float

@router.post("/nlu/parse", response_model=NLUParseResponse)
async def parse_nlu(request: NLUParseRequest):
    """
    Parse natural language to extract intent, entities, and tasks.
    This is the main NLU endpoint for the agent runtime.
    """
    import time
    start_time = time.time()
    
    try:
        # Try to use the real AI service
        from enhanced_ai_workflow_endpoints import ai_service
        
        nlu_result = await ai_service.process_with_nlu(
            request.text, 
            request.provider
        )
        
        processing_time = (time.time() - start_time) * 1000
        
        return NLUParseResponse(
            request_id=f"nlu_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            text=request.text,
            intent=nlu_result.get('intent', 'unknown'),
            entities=nlu_result.get('entities', []) if isinstance(nlu_result.get('entities'), list) else [],
            tasks=nlu_result.get('tasks', []),
            confidence=nlu_result.get('confidence', 0.85),
            provider_used=nlu_result.get('ai_provider_used', request.provider),
            processing_time_ms=processing_time
        )
        
    except Exception as e:
        logger.warning(f"Real NLU failed, using fallback: {e}")
        
        # Fallback NLU with simple pattern matching
        processing_time = (time.time() - start_time) * 1000
        text_lower = request.text.lower()
        
        # Simple intent classification
        intent = "general"
        if "schedule" in text_lower or "meeting" in text_lower:
            intent = "scheduling"
        elif "send" in text_lower or "email" in text_lower:
            intent = "communication"
        elif "create" in text_lower or "add" in text_lower:
            intent = "creation"
        elif "search" in text_lower or "find" in text_lower:
            intent = "search"
        elif "workflow" in text_lower or "automate" in text_lower:
            intent = "workflow_creation"
        
        # Simple entity extraction
        entities = []
        words = request.text.split()
        for i, word in enumerate(words):
            if "@" in word:
                entities.append({"type": "email", "value": word})
            if word.isdigit():
                entities.append({"type": "number", "value": word})
        
        return NLUParseResponse(
            request_id=f"nlu_{datetime.now().strftime('%Y%m%d_%H%M%S')}",
            text=request.text,
            intent=intent,
            entities=entities,
            tasks=[f"Process: {request.text[:100]}"],
            confidence=0.7,
            provider_used="fallback",
            processing_time_ms=processing_time
        )

@router.get("/providers")
async def get_providers():
    """Get available AI providers"""
    try:
        from enhanced_ai_workflow_endpoints import ai_service
        
        providers = []
        if ai_service.openai_api_key:
            providers.append({"id": "openai", "name": "OpenAI GPT-4", "enabled": True})
        if ai_service.anthropic_api_key:
            providers.append({"id": "anthropic", "name": "Anthropic Claude", "enabled": True})
        if ai_service.deepseek_api_key:
            providers.append({"id": "deepseek", "name": "DeepSeek Chat", "enabled": True})
        if ai_service.google_api_key:
            providers.append({"id": "google", "name": "Google Gemini", "enabled": True})
        
        return {
            "providers": providers,
            "default": "deepseek" if ai_service.deepseek_api_key else "openai",
            "count": len(providers)
        }
    except Exception as e:
        return {
            "providers": [
                {"id": "openai", "name": "OpenAI GPT-4", "enabled": False},
                {"id": "anthropic", "name": "Anthropic Claude", "enabled": False},
                {"id": "deepseek", "name": "DeepSeek Chat", "enabled": False},
            ],
            "default": "openai",
            "count": 0
        }

@router.post("/complete", response_model=CompletionResponse)
async def complete_text(request: CompletionRequest):
    """
    Generate text completion using configured AI provider.
    """
    import time
    start_time = time.time()
    
    try:
        from enhanced_ai_workflow_endpoints import ai_service
        
        result = await ai_service.analyze_text(
            request.prompt,
            complexity=2,
            system_prompt="You are a helpful AI assistant."
        )
        
        processing_time = (time.time() - start_time) * 1000
        
        return CompletionResponse(
            completion=result,
            provider_used=request.provider,
            tokens_used=len(result.split()) * 2,  # Rough estimate
            processing_time_ms=processing_time
        )
        
    except Exception as e:
        logger.error(f"Completion failed: {e}")
        processing_time = (time.time() - start_time) * 1000
        
        return CompletionResponse(
            completion=f"[Completion unavailable: {str(e)[:100]}]",
            provider_used="error",
            tokens_used=0,
            processing_time_ms=processing_time
        )