File size: 10,508 Bytes
4e92cd9
 
 
 
 
 
892b47a
4e92cd9
 
 
 
 
 
892b47a
 
 
 
 
 
 
 
 
4e92cd9
 
 
 
 
 
 
 
 
892b47a
4e92cd9
 
 
 
 
 
 
892b47a
 
4e92cd9
 
 
892b47a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e92cd9
 
892b47a
 
 
 
 
 
 
 
 
 
 
 
 
 
4e92cd9
 
 
 
 
892b47a
4e92cd9
 
892b47a
4e92cd9
 
 
 
892b47a
4e92cd9
 
 
 
 
892b47a
4e92cd9
892b47a
 
 
 
 
 
 
 
 
 
 
4e92cd9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
892b47a
4e92cd9
 
 
 
 
 
 
 
892b47a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4e92cd9
 
 
 
892b47a
 
 
 
 
 
 
 
4e92cd9
 
 
 
 
 
 
 
 
892b47a
4e92cd9
 
 
 
 
 
 
 
 
 
892b47a
4e92cd9
 
 
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
"""
Chat Agent Router - API Endpoints for Chat functionality
"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from typing import List, Optional, Dict, Any
from enum import Enum
from src.services.groq_service import generate_response
from src.api.core.logger import logger

router = APIRouter()


class AgentType(str, Enum):
    """Available AI Agent Types"""
    GENERAL = "general"           # General assistant
    CODER = "coder"              # Code generation & review
    DATA_ANALYST = "data_analyst" # Data analysis
    RESEARCHER = "researcher"    # Research & writing
    TUTOR = "tutor"              # Teaching & explanations


class ChatMessage(BaseModel):
    """Chat message model"""
    role: str = Field(..., description="Role: 'user' or 'assistant'")
    content: str = Field(..., description="Message content")


class ChatRequest(BaseModel):
    """Request model for chat"""
    message: str = Field(..., description="User message")
    agent_type: Optional[AgentType] = Field(default=AgentType.GENERAL, description="Agent type to use")
    context: Optional[Dict[str, Any]] = Field(default=None, description="Additional context")
    conversation_id: Optional[str] = Field(default=None, description="Conversation ID for history")


class ChatResponse(BaseModel):
    """Response model for chat"""
    response: str
    conversation_id: str
    agent_type: str
    model: str = "llama-3.1-8b-instant"


# Agent System Prompts
AGENT_PROMPTS = {
    AgentType.GENERAL: """You are AmkyawDev AI Assistant, a highly capable and professional AI assistant.

## Your Role
You are a versatile AI assistant developed by AmkyawDev. You help users with various tasks including:
- Answering questions
- Providing explanations
- Problem-solving
- Creative tasks

## Guidelines
1. Always be helpful, polite, and professional
2. Provide accurate and well-structured responses
3. Use markdown formatting for clarity
4. Ask clarifying questions when needed
5. Admit when you don't know something
6. Be concise but thorough

## Response Format
- Use bullet points for lists
- Use code blocks for code
- Use headers for structure
- Be direct and clear""",

    AgentType.CODER: """You are AmkyawDev Coding Assistant, an expert software developer.

## Your Role
You are a specialized coding assistant that helps with:
- Writing clean, efficient code
- Code review and debugging
- Algorithm design
- Best practices
- Technical documentation

## Guidelines
1. Write clean, readable, and well-documented code
2. Follow language-specific best practices
3. Include code comments explaining complex logic
4. Handle errors gracefully
5. Consider performance and scalability
6. Provide multiple solutions when appropriate

## Response Format
- Always provide working code examples
- Use proper code formatting with language hints
- Explain the code after showing it
- Include time/space complexity when relevant
- Suggest improvements and alternatives""",

    AgentType.DATA_ANALYST: """You are AmkyawDev Data Analyst, an expert in data analysis and visualization.

## Your Role
You specialize in:
- Data analysis and interpretation
- Statistical analysis
- Data visualization suggestions
- Report generation
- Insights and recommendations

## Guidelines
1. Approach problems with data-driven mindset
2. Consider statistical significance
3. Suggest appropriate visualizations
4. Provide actionable insights
5. Explain your reasoning

## Response Format
- Use tables for structured data
- Use code blocks for data manipulation
- Include statistical measures
- Suggest visualization types""",

    AgentType.RESEARCHER: """You are AmkyawDev Research Assistant, an expert researcher and writer.

## Your Role
You help with:
- Research and information gathering
- Writing and content creation
- Summary and synthesis
- Citation and references
- Critical analysis

## Guidelines
1. Be thorough and well-researched
2. Cite sources when possible
3. Present multiple perspectives
4. Be objective and balanced
5. Structure content clearly

## Response Format
- Use headings for organization
- Include references section
- Provide summaries and conclusions
- Use bullet points for key findings""",

    AgentType.TUTOR: """You are AmkyawDev Tutor, a patient and knowledgeable teacher.

## Your Role
You help users learn and understand:
- Complex concepts made simple
- Step-by-step explanations
- Practical examples
- Knowledge building
- Skill development

## Guidelines
1. Be patient and encouraging
2. Break down complex topics
3. Use analogies and examples
4. Check understanding
5. Build on prior knowledge
6. Be interactive

## Response Format
- Start with fundamentals
- Build up progressively
- Use simple language
- Include practice exercises
- Ask checking questions"""
}


# Skills/Commands that users can trigger
SKILL_COMMANDS = {
    "code_review": "Review the provided code for bugs, security issues, and best practices",
    "bug_fix": "Find and fix bugs in the provided code",
    "refactor": "Improve and refactor the provided code",
    "document": "Generate documentation for the provided code",
    "explain": "Explain the provided code or concept in detail",
    "optimize": "Optimize the provided code for performance",
    "test": "Write unit tests for the provided code"
}


# Simple in-memory conversation storage
conversations: Dict[str, List[Dict[str, str]]] = {}
conversation_agents: Dict[str, AgentType] = {}  # Track agent type per conversation


def build_system_message(agent_type: AgentType) -> Dict[str, str]:
    """Build system message based on agent type"""
    base_prompt = AGENT_PROMPTS.get(agent_type, AGENT_PROMPTS[AgentType.GENERAL])
    
    # Add skill commands info
    skills_info = "\n\n## Available Skills/Commands\nYou can help with these specialized tasks:\n"
    for cmd, desc in SKILL_COMMANDS.items():
        skills_info += f"- `{cmd}`: {desc}\n"
    skills_info += "\nWhen user requests a skill, perform that task specifically."
    
    return {"role": "system", "content": base_prompt + skills_info}


@router.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest) -> ChatResponse:
    """
    Chat endpoint - AI conversation with agent control
    
    - **message**: User's message
    - **agent_type**: Type of agent (general, coder, data_analyst, researcher, tutor)
    - **context**: Optional context data
    - **conversation_id**: Optional conversation ID for history
    """
    try:
        logger.info(f"Chat request: {request.message[:50]}... (agent: {request.agent_type})")
        
        # Get or create conversation
        conv_id = request.conversation_id or "default"
        if conv_id not in conversations:
            conversations[conv_id] = []
            conversation_agents[conv_id] = request.agent_type
        
        # Use specified agent type
        agent_type = request.agent_type or conversation_agents.get(conv_id, AgentType.GENERAL)
        conversation_agents[conv_id] = agent_type
        
        # Build messages with system prompt
        messages = [build_system_message(agent_type)]
        
        # Add context if provided
        if request.context:
            context_msg = f"Context: {request.context}"
            messages.append({"role": "system", "content": context_msg})
        
        # Add conversation history
        messages.extend(conversations[conv_id][-10:])  # Keep last 10 messages
        
        # Add current message
        messages.append({"role": "user", "content": request.message})
        
        # Generate response
        response_text = await generate_response(
            messages=messages,
            model="llama-3.1-8b-instant",
            temperature=0.7,
            max_tokens=2048
        )
        
        # Save to conversation history
        conversations[conv_id].append({"role": "user", "content": request.message})
        conversations[conv_id].append({"role": "assistant", "content": response_text})
        
        # Keep history limited
        if len(conversations[conv_id]) > 20:
            conversations[conv_id] = conversations[conv_id][-20:]
        
        return ChatResponse(
            response=response_text,
            conversation_id=conv_id,
            agent_type=agent_type.value,
            model="llama-3.1-8b-instant"
        )
        
    except Exception as e:
        logger.error(f"Chat error: {str(e)}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/agents")
async def get_agents() -> Dict[str, Any]:
    """Get all available agents"""
    return {
        "agents": [
            {"id": agent.value, "name": agent.value.replace("_", " ").title(), "prompt": AGENT_PROMPTS[agent][:100] + "..."}
            for agent in AgentType
        ],
        "count": len(AgentType)
    }


@router.get("/agents/skills")
async def get_skills() -> Dict[str, Any]:
    """Get all available skills"""
    return {
        "skills": [
            {"id": cmd, "description": desc}
            for cmd, desc in SKILL_COMMANDS.items()
        ],
        "count": len(SKILL_COMMANDS)
    }


@router.get("/conversations")
async def get_conversations() -> Dict[str, Any]:
    """Get all conversation IDs"""
    return {
        "conversations": [
            {
                "id": conv_id,
                "agent_type": conversation_agents.get(conv_id, "general"),
                "message_count": len(conversations[conv_id])
            }
            for conv_id in conversations.keys()
        ],
        "count": len(conversations)
    }


@router.delete("/conversations/{conversation_id}")
async def delete_conversation(conversation_id: str) -> Dict[str, str]:
    """Delete a conversation"""
    if conversation_id in conversations:
        del conversations[conversation_id]
        conversation_agents.pop(conversation_id, None)
        return {"status": "deleted", "conversation_id": conversation_id}
    raise HTTPException(status_code=404, detail="Conversation not found")


@router.get("/conversations/{conversation_id}")
async def get_conversation(conversation_id: str) -> Dict[str, Any]:
    """Get conversation history"""
    if conversation_id in conversations:
        return {
            "conversation_id": conversation_id,
            "agent_type": conversation_agents.get(conversation_id, "general"),
            "messages": conversations[conversation_id]
        }
    raise HTTPException(status_code=404, detail="Conversation not found")