重构: 将API配置提取到config模块并优化错误处理
- 将硬编码的API配置移到config模块,支持环境变量配置 - 添加API Key验证和配置检查 - 添加图片上传大小限制(10MB) - 移除不必要的注释,简化代码 - 改进错误处理和日志记录
This commit is contained in:
@@ -11,6 +11,10 @@ var (
|
|||||||
Password = getEnv("JWTS_PASSWORD", "")
|
Password = getEnv("JWTS_PASSWORD", "")
|
||||||
Semester = getEnv("JWTS_SEMESTER", "2025-20262")
|
Semester = getEnv("JWTS_SEMESTER", "2025-20262")
|
||||||
TWFID = getEnv("JWTS_TWFID", "")
|
TWFID = getEnv("JWTS_TWFID", "")
|
||||||
|
|
||||||
|
RecognizerAPIURL = getEnv("RECOGNIZER_API_URL", "https://api.littlelan.cn/v1/chat/completions")
|
||||||
|
RecognizerAPIKey = getEnv("RECOGNIZER_API_KEY", "")
|
||||||
|
RecognizerModel = getEnv("RECOGNIZER_MODEL", "qwen3.5-plus")
|
||||||
)
|
)
|
||||||
|
|
||||||
// getEnv 从环境变量获取配置,提供默认值
|
// getEnv 从环境变量获取配置,提供默认值
|
||||||
|
|||||||
10
main.go
10
main.go
@@ -97,7 +97,6 @@ func runHTTPServer() {
|
|||||||
|
|
||||||
// 课表图片识别接口
|
// 课表图片识别接口
|
||||||
r.POST("/recognize", func(c *gin.Context) {
|
r.POST("/recognize", func(c *gin.Context) {
|
||||||
// 读取上传的图片文件
|
|
||||||
file, header, err := c.Request.FormFile("image")
|
file, header, err := c.Request.FormFile("image")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "请上传图片文件", "details": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "请上传图片文件", "details": err.Error()})
|
||||||
@@ -107,24 +106,25 @@ func runHTTPServer() {
|
|||||||
|
|
||||||
log.Printf("收到图片上传: %s, 大小: %d bytes", header.Filename, header.Size)
|
log.Printf("收到图片上传: %s, 大小: %d bytes", header.Filename, header.Size)
|
||||||
|
|
||||||
// 读取图片数据
|
if header.Size > 10*1024*1024 {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "图片文件过大", "max_size": "10MB"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
imageData, err := io.ReadAll(file)
|
imageData, err := io.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "读取图片失败", "details": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "读取图片失败", "details": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用识别模块
|
|
||||||
courses, err := recognizer.RecognizeFromBytes(imageData)
|
courses, err := recognizer.RecognizeFromBytes(imageData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "识别失败", "details": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "识别失败", "details": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 打印识别结果
|
|
||||||
recognizer.PrintCourses(courses)
|
recognizer.PrintCourses(courses)
|
||||||
|
|
||||||
// 保存到JSON文件
|
|
||||||
err = recognizer.SaveToJSON(courses, "schedule_result.json")
|
err = recognizer.SaveToJSON(courses, "schedule_result.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("保存JSON失败: %v", err)
|
log.Printf("保存JSON失败: %v", err)
|
||||||
|
|||||||
@@ -13,16 +13,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"jwts/config"
|
||||||
"jwts/models"
|
"jwts/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 配置 - 使用您提供的API配置
|
|
||||||
const (
|
|
||||||
APIURL = "https://api.littlelan.cn/v1/chat/completions"
|
|
||||||
APIKey = "sk-Ll7P7vuiLum3N0pj7XaYfwHhD5UW1rDYlFoQ7F5JmeBfTewZ"
|
|
||||||
Model = "qwen3.5-plus" // 使用qwen3.5-plus模型
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIRequest API请求结构
|
// APIRequest API请求结构
|
||||||
type APIRequest struct {
|
type APIRequest struct {
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
@@ -68,6 +62,11 @@ func init() {
|
|||||||
client = &http.Client{
|
client = &http.Client{
|
||||||
Timeout: 120 * time.Second,
|
Timeout: 120 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.RecognizerAPIKey == "" {
|
||||||
|
log.Println("警告: RECOGNIZER_API_KEY 未设置,图片识别功能将无法使用")
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("recognizer模块已初始化")
|
log.Println("recognizer模块已初始化")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,12 +132,14 @@ func callAPI(imageBase64 string) ([]models.Course, error) {
|
|||||||
|
|
||||||
// callAPISingle 单次API调用
|
// callAPISingle 单次API调用
|
||||||
func callAPISingle(imageBase64 string) ([]models.Course, error) {
|
func callAPISingle(imageBase64 string) ([]models.Course, error) {
|
||||||
// 构建请求 - 发送图片给AI识别
|
if config.RecognizerAPIKey == "" {
|
||||||
// 禁用qwen3.5的思考模式,避免产生大量不必要的token消耗
|
return nil, fmt.Errorf("RECOGNIZER_API_KEY 未配置")
|
||||||
|
}
|
||||||
|
|
||||||
falseVal := false
|
falseVal := false
|
||||||
zero := 0
|
zero := 0
|
||||||
apiReq := APIRequest{
|
apiReq := APIRequest{
|
||||||
Model: Model,
|
Model: config.RecognizerModel,
|
||||||
MaxTokens: 4000,
|
MaxTokens: 4000,
|
||||||
EnableThinking: &falseVal,
|
EnableThinking: &falseVal,
|
||||||
ThinkingBudget: &zero,
|
ThinkingBudget: &zero,
|
||||||
@@ -175,14 +176,14 @@ JSON格式要求:
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReq, err := http.NewRequest("POST", APIURL, bytes.NewBuffer(jsonData))
|
httpReq, err := http.NewRequest("POST", config.RecognizerAPIURL, bytes.NewBuffer(jsonData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReq.Header = http.Header{
|
httpReq.Header = http.Header{
|
||||||
"Content-Type": []string{"application/json"},
|
"Content-Type": []string{"application/json"},
|
||||||
"Authorization": []string{"Bearer " + APIKey},
|
"Authorization": []string{"Bearer " + config.RecognizerAPIKey},
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[识别] 正在调用API进行识别...")
|
fmt.Println("[识别] 正在调用API进行识别...")
|
||||||
|
|||||||
Reference in New Issue
Block a user