132 lines
3.5 KiB
Go
132 lines
3.5 KiB
Go
package handlers
|
||
|
||
import (
|
||
"ai_scheduler/pkg/types"
|
||
"net/http"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
)
|
||
|
||
// ChatHandler 聊天处理器
|
||
type ChatHandler struct {
|
||
routerService types.RouterService
|
||
}
|
||
|
||
// NewChatHandler 创建聊天处理器
|
||
func NewChatHandler(routerService types.RouterService) *ChatHandler {
|
||
return &ChatHandler{
|
||
routerService: routerService,
|
||
}
|
||
}
|
||
|
||
// ChatRequest HTTP聊天请求
|
||
type ChatRequest struct {
|
||
Message string `json:"message" binding:"required" example:"北京今天天气怎么样?"`
|
||
Model string `json:"model,omitempty" example:"llama2"`
|
||
}
|
||
|
||
// ChatResponse HTTP聊天响应
|
||
type ChatResponse struct {
|
||
Message string `json:"message" example:"北京今天天气晴朗,温度15.3°C"`
|
||
ToolCalls []ToolCallResponse `json:"tool_calls,omitempty"`
|
||
Finished bool `json:"finished" example:"true"`
|
||
}
|
||
|
||
// ToolCallResponse 工具调用响应
|
||
type ToolCallResponse struct {
|
||
ID string `json:"id" example:"call_1"`
|
||
Type string `json:"type" example:"function"`
|
||
Function FunctionCallResponse `json:"function"`
|
||
Result interface{} `json:"result,omitempty"`
|
||
}
|
||
|
||
// FunctionCallResponse 函数调用响应
|
||
type FunctionCallResponse struct {
|
||
Name string `json:"name" example:"get_weather"`
|
||
Arguments interface{} `json:"arguments"`
|
||
}
|
||
|
||
// ErrorResponse 错误响应
|
||
type ErrorResponse struct {
|
||
Error string `json:"error" example:"Invalid request"`
|
||
Code int `json:"code" example:"400"`
|
||
Message string `json:"message" example:"请求参数错误"`
|
||
}
|
||
|
||
// Chat 处理聊天请求
|
||
// @Summary 智能聊天
|
||
// @Description 发送消息给AI助手,支持工具调用
|
||
// @Tags chat
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param request body ChatRequest true "聊天请求"
|
||
// @Success 200 {object} ChatResponse "聊天响应"
|
||
// @Failure 400 {object} ErrorResponse "请求错误"
|
||
// @Failure 500 {object} ErrorResponse "服务器错误"
|
||
// @Router /api/v1/chat [post]
|
||
func (h *ChatHandler) Chat(c *gin.Context) {
|
||
var req ChatRequest
|
||
if err := c.ShouldBindJSON(&req); err != nil {
|
||
c.JSON(http.StatusBadRequest, ErrorResponse{
|
||
Error: "Invalid request",
|
||
Code: http.StatusBadRequest,
|
||
Message: err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 转换为服务层请求
|
||
serviceReq := &types.ChatRequest{
|
||
Message: req.Message,
|
||
Model: req.Model,
|
||
}
|
||
|
||
// 调用路由服务
|
||
response, err := h.routerService.Route(c.Request.Context(), serviceReq)
|
||
if err != nil {
|
||
c.JSON(http.StatusInternalServerError, ErrorResponse{
|
||
Error: "Service error",
|
||
Code: http.StatusInternalServerError,
|
||
Message: err.Error(),
|
||
})
|
||
return
|
||
}
|
||
|
||
// 转换响应格式
|
||
httpResponse := &ChatResponse{
|
||
Message: response.Message,
|
||
Finished: response.Finished,
|
||
}
|
||
|
||
// 转换工具调用
|
||
if len(response.ToolCalls) > 0 {
|
||
httpResponse.ToolCalls = make([]ToolCallResponse, len(response.ToolCalls))
|
||
for i, toolCall := range response.ToolCalls {
|
||
httpResponse.ToolCalls[i] = ToolCallResponse{
|
||
ID: toolCall.ID,
|
||
Type: toolCall.Type,
|
||
Function: FunctionCallResponse{
|
||
Name: toolCall.Function.Name,
|
||
Arguments: toolCall.Function.Arguments,
|
||
},
|
||
Result: toolCall.Result,
|
||
}
|
||
}
|
||
}
|
||
|
||
c.JSON(http.StatusOK, httpResponse)
|
||
}
|
||
|
||
// Health 健康检查
|
||
// @Summary 健康检查
|
||
// @Description 检查服务是否正常运行
|
||
// @Tags system
|
||
// @Produce json
|
||
// @Success 200 {object} map[string]string
|
||
// @Router /health [get]
|
||
func (h *ChatHandler) Health(c *gin.Context) {
|
||
c.JSON(http.StatusOK, gin.H{
|
||
"status": "ok",
|
||
"service": "ai-scheduler",
|
||
})
|
||
} |