beego框架调用openai api需手动处理http请求、流式sse解析、跨域、鉴权差异、超时控制及token统计,无内置支持。

Beego 框架本身不内置 LLM 调用能力,直接集成 OpenAI 接口必须手动处理 HTTP 请求、流式响应解析、错误重试和跨域——这不是加个 openai 包就能跑通的事。
Beego 中调用 OpenAI API 必须绕过默认 JSON 解析器
Beego 的 Controller.ParseForm() 和 Controller.GetString() 默认只处理表单或简单 query,而 OpenAI 的 /v1/chat/completions 要求标准 JSON POST body(含 messages 数组、model、stream 等字段)。若强行用 GetString("messages") 会丢掉嵌套结构,返回空或 panic。
- 正确做法是用
this.Ctx.Input.RequestBody原始读取字节流,再用json.Unmarshal()解析 - 若需支持
stream=true,不能用json.Unmarshal()一次性解析,得按行切割data:前缀的 SSE 流(每行一个 JSON 对象) - Beego 的
Ctx.ResponseWriter默认关闭流式写入,需手动设置Header().Set("Content-Type", "text/event-stream")并禁用缓冲:this.Ctx.ResponseWriter.(http.Flusher).Flush()
OpenAI 官方 API 与 Azure OpenAI 的 base_url 差异极易导致 404 或 401
OpenAI 官方 endpoint 是 https://api.openai.com/v1;Azure OpenAI 则是 https://{resource-name}.openai.azure.com/openai/deployments/{deployment-id}/chat/completions?api-version=2024-06-01。两者路径结构、认证头、参数名全不同。
- 官方版用
Authorization: Bearer <key></key>,Azure 版用api-keyheader - Azure 版必须传
api-version查询参数,缺则 400;官方版不认这个参数 - 模型名在 Azure 中是 deployment id(如
gpt-4o-mini),不是官方模型名(如gpt-4o-mini-2024-07-18),填错直接 404 - Beego 中建议把 base_url、auth header、required params 封装进配置项,避免硬编码分散在 controller 里
流式响应下 Beego 的超时和连接中断处理很脆弱
Beego 默认 ServerTimeOut 是 60 秒,但 OpenAI 流式响应可能因网络抖动卡顿数秒,或用户中途关闭页面——此时 Beego 不会自动关闭底层连接,goroutine 泄露风险高。
- 必须在 handler 开头用
ctx := this.Ctx.Request.Context()获取上下文,并传给 HTTP client 的Do(req.WithContext(ctx)) - 显式设置 client timeout:
http.Client{Timeout: 90 * time.Second},比 server timeout 长但不过长 - 监听
ctx.Done(),一旦触发就主动关闭 response writer 并 return,否则 goroutine 挂住 - 前端断连时,
Write()可能返回broken pipe错误,需捕获并 clean exit,不 panic
Beego 日志无法自动记录 OpenAI 请求耗时与 token 用量
OpenAI 响应头里有 x-ratelimit-limit-requests、x-ratelimit-remaining-tokens,响应体里有 usage.input_tokens、usage.output_tokens,但 Beego 默认日志只记路由和状态码。
- 若要审计成本或限流,必须在 handler 里手动提取这些字段,拼进
logs.Info() - 流式响应无法在开头就拿到总 token 数,只能等最后一个
data: [DONE]后解析 final usage 字段 - 建议封装一个
recordOpenAIUsage()函数,统一处理成功/失败场景下的日志落库或上报 - 别依赖 Beego 的
AccessLogs,它不包含 response body,token 统计无从谈起
真正难的不是发请求,而是让 Beego 在流式、超时、鉴权、错误重试、token 追踪这五条线上都不掉链子——每个环节都得亲手补漏,没有开箱即用的 magic。











