package handler import ( "net/http" "github.com/gin-gonic/gin" "github.com/google/generative-ai-go/genai" "google.golang.org/api/option" "encoding/json" "strings" ) type RateHandler struct { geminiAPIKey string apiKey string } type RateRequest struct { Content string `json:"content" binding:"required"` Criteria string `json:"criteria"` WritingRequirement string `json:"writing_requirement"` APIKey string `json:"apikey" binding:"required"` } type RateResponse struct { Rate int `json:"rate"` Summary string `json:"summary"` DetailedReview string `json:"detailed_review"` Success bool `json:"success"` } func NewRateHandler(geminiAPIKey, apiKey string) *RateHandler { return &RateHandler{ geminiAPIKey: geminiAPIKey, apiKey: apiKey, } } func (h *RateHandler) HandleRate(c *gin.Context) { var req RateRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, RateResponse{ Success: false, }) return } // Validate API key if req.APIKey != h.apiKey { c.JSON(http.StatusUnauthorized, RateResponse{ Success: false, }) return } // Initialize Gemini client ctx := c.Request.Context() client, err := genai.NewClient(ctx, option.WithAPIKey(h.geminiAPIKey)) if err != nil { c.JSON(http.StatusInternalServerError, RateResponse{ Success: false, }) return } defer client.Close() // Prepare criteria criteria := req.Criteria if criteria == "" { criteria = `你是一名语文老师。你正在给学生的作文打分。根据以下中考作文评分标准,给作文打分。 ## 评分总分值:100分。 ### 88-100分 符合题意;写作目的和对象明确;思考充分,立意深刻,感情真挚;选材精当,内容充实;中心突出,条理清晰;表达准确,语言流畅。 ### 75-87分 符合题意;写作目的和对象较明确;思考较充分,立意清楚,感情真实;选材合理,内容具体;中心明确,有一定条理;表达较准确,语言通畅。 ### 60-74分 符合题意;写作目的和对象较模糊;有一定思考,感情真实;有一定内容;结构基本完整;语言尚通畅。 ### 60分以下 不符合题意;缺乏写作目的和对象;基本没有思考,感情虚假;内容空洞;结构混乱;不成篇。` } writing_requirement := req.WritingRequirement if writing_requirement == "" { writing_requirement = "写一篇不少于600字的作文,体裁不限。" } // 规定输出格式是json,包含rate, summary, detailed_review,放入prompt的最后 format := `请按照以下JSON格式输出: { "rate": 分数, // 最多100分制的分数,int类型 "summary": "总体评价", // 100字以内的总体评价,string类型 "detailed_review": "详细点评" // 300字以内的详细点评,包含优点和建议,string类型 }` // Prepare prompt prompt := "作文要求:\n" + writing_requirement + "\n\n" + "评分标准:\n" + criteria + format + "\n\n" + "\n\n作文内容:\n" + req.Content // Generate content model := client.GenerativeModel("gemini-2.0-flash-exp") resp, err := model.GenerateContent(ctx, genai.Text(prompt)) if err != nil { c.JSON(http.StatusInternalServerError, RateResponse{ Success: false, }) return } if len(resp.Candidates) > 0 && len(resp.Candidates[0].Content.Parts) > 0 { if textPart, ok := resp.Candidates[0].Content.Parts[0].(genai.Text); ok { // Parse the response to extract rate, summary, and detailed review result := parseRateResponse(string(textPart)) c.JSON(http.StatusOK, RateResponse{ Rate: result.Rate, Summary: result.Summary, DetailedReview: result.Detailed, Success: true, }) return } } c.JSON(http.StatusInternalServerError, RateResponse{ Success: false, }) } type rateResult struct { Rate int `json:"rate"` Summary string `json:"summary"` Detailed string `json:"detailed_review"` } func parseRateResponse(response string) rateResult { var result rateResult //去除所有\n response = strings.ReplaceAll(response, "\n", "") //去除所有\t response = strings.ReplaceAll(response, "\t", "") // 去除response中的```json前缀和```后缀 response = strings.TrimSpace(response) response = strings.TrimPrefix(response, "```json") response = strings.TrimSuffix(response, "```") // 检查response是否是json格式 if !strings.HasPrefix(response, "{") { return rateResult{ Rate: 0, Summary: "解析失败", Detailed: "没有左括号", } } if !strings.HasSuffix(response, "}") { return rateResult{ Rate: 0, Summary: "解析失败", Detailed: "没有右括号", } } // 解析json err := json.Unmarshal([]byte(response), &result) if err != nil { return rateResult{ Rate: 0, Summary: "解析失败", Detailed: "反序列化失败", } } // 合并所有验证条件 if result.Rate <= 0 || result.Rate > 100 || result.Summary == "" || result.Detailed == "" { return rateResult{ Rate: 0, Summary: "解析失败", Detailed: "字段验证条件不满足", } } return result }