package service import ( "bytes" "context" "encoding/json" "fmt" "net/http" "time" "x-agents/server/internal/model" "x-agents/server/internal/repository" "github.com/google/uuid" ) type ChatService struct { pythonURL string agentRepo *repository.AgentRepository modelRepo *repository.ModelRepository } func NewChatService(pythonURL string, agentRepo *repository.AgentRepository, modelRepo *repository.ModelRepository) *ChatService { return &ChatService{ pythonURL: pythonURL, agentRepo: agentRepo, modelRepo: modelRepo, } } type ChatRequest struct { AgentID string `json:"agent_id"` Message string `json:"message"` SessionID string `json:"session_id"` ModelID string `json:"model_id"` Context map[string]interface{} `json:"context"` } // ModelConfig 模型配置,用于传递给 Python 服务 type ModelConfig struct { Provider string `json:"provider"` Model string `json:"model"` APIKey string `json:"api_key"` BaseURL string `json:"base_url"` APIEndpoint string `json:"api_endpoint"` } type ChatResponse struct { Reply string `json:"reply"` SessionID string `json:"session_id"` ToolsUsed []string `json:"tools_used"` Metadata map[string]interface{} `json:"metadata"` } // Chat 处理聊天请求 func (s *ChatService) Chat(ctx context.Context, userID string, req model.AgentRequest) (*model.AgentResponse, error) { // 1. 检查 Agent 是否存在 agent, err := s.agentRepo.FindByID(req.AgentID) if err != nil { return nil, fmt.Errorf("agent not found: %w", err) } // 2. 检查用户权限 if !agent.IsActive { return nil, fmt.Errorf("agent is not active") } // 3. 生成会话ID sessionID := req.SessionID if sessionID == "" { sessionID = uuid.New().String() } // 4. 如果提供了 ModelID,获取模型配置 var modelConfig *ModelConfig if req.ModelID != "" { modelInfo, err := s.modelRepo.FindByID(req.ModelID) if err != nil { return nil, fmt.Errorf("model not found: %w", err) } modelConfig = &ModelConfig{ Provider: modelInfo.Provider, Model: modelInfo.Model, APIKey: modelInfo.APIKey, BaseURL: modelInfo.BaseURL, APIEndpoint: modelInfo.APIEndpoint, } } // 5. 调用 Python 服务 pythonReq := ChatRequest{ AgentID: req.AgentID, Message: req.Message, SessionID: sessionID, ModelID: req.ModelID, Context: req.Context, } // 将模型配置放入 Context 中传递给 Python 服务 if modelConfig != nil { pythonReq.Context = make(map[string]interface{}) for k, v := range req.Context { pythonReq.Context[k] = v } pythonReq.Context["model_config"] = modelConfig } pythonResp, err := s.callPythonChat(ctx, pythonReq) if err != nil { return nil, fmt.Errorf("failed to call python service: %w", err) } return &model.AgentResponse{ Reply: pythonResp.Reply, SessionID: pythonResp.SessionID, ToolsUsed: pythonResp.ToolsUsed, Metadata: pythonResp.Metadata, }, nil } func (s *ChatService) callPythonChat(ctx context.Context, req ChatRequest) (*ChatResponse, error) { jsonData, err := json.Marshal(req) if err != nil { return nil, err } httpReq, err := http.NewRequestWithContext( ctx, "POST", s.pythonURL+"/agent/chat", bytes.NewBuffer(jsonData), ) if err != nil { return nil, err } httpReq.Header.Set("Content-Type", "application/json") client := &http.Client{ Timeout: 120 * time.Second, // Agent 可能需要较长时间 } resp, err := client.Do(httpReq) if err != nil { return nil, err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return nil, fmt.Errorf("python service returned status: %d", resp.StatusCode) } var chatResp ChatResponse if err := json.NewDecoder(resp.Body).Decode(&chatResp); err != nil { return nil, err } return &chatResp, nil } // ListAgents 获取用户可用的 Agent 列表 func (s *ChatService) ListAgents(userID string) ([]model.Agent, error) { return s.agentRepo.FindByOwnerID(userID) } // CreateAgent 创建新的 Agent func (s *ChatService) CreateAgent(userID string, name, description string) (*model.Agent, error) { agent := &model.Agent{ ID: uuid.New().String(), Name: name, Description: description, OwnerID: userID, IsActive: true, } if err := s.agentRepo.Create(agent); err != nil { return nil, err } return agent, nil }