编程 使用 LangChainGo + Gin 实现流式 AI 问答系统

2025-03-09 22:26:15 +0800 CST views 343

实战: 使用 LangChainGo + Gin 实现流式 AI 问答系统

在本篇文章中,我们将使用 LangChainGo + Gin 框架,结合 Ollama 大语言模型,实现一个流式 AI 问答系统。最终,我们还会使用 curl 进行测试,由于是实战例子所以我会提供一个简单的 html+css+js 的前端来实时显示 AI 的回答。

流式响应的意义

在传统 API 调用中,我们往往要等到大语言模型(LLM)计算完成后,才能返回完整的回答。这会导致:

  • 等待时间长:用户需要等待很久,体验不佳。
  • 缺乏实时性:无法在模型生成内容的同时,逐步显示给用户。

而流式响应可以:

  • 逐步输出生成的内容,前端可以即时渲染,提升用户体验。
  • 优化带宽,避免一次性传输大数据,减少系统压力。

后端:Gin + LangChainGo 实现流式响应

我们闲话少说,开始今天的正题,具体步骤如下所示:

1. 创建项目并安装依赖

首先我们创建一个名为 robot-go 的项目,并安装其所需要的依赖。

mkdir robot-go
cd robot-go/
go mod init github.com/xxx/robot-go
go get github.com/gin-gonic/gin
go get github.com/tmc/langchaingo@v0.1.13
go get github.com/tmc/langchaingo/llms@v0.1.13

2. 编写代码

键入如下代码:

func chatHandler(c *gin.Context) {
    var request struct {
        Question string `json:"question"`
    }
    if err := c.ShouldBindJSON(&request); err != nil {
        log.Printf("Invalid request: %v", err)
        c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
        return
    }
    if request.Question == "" {
        log.Print("Empty question received")
        c.JSON(http.StatusBadRequest, gin.H{"error": "question cannot be empty"})
        return
    }
    ctx := context.Background()
    // 设置 SSE 头部
    c.Writer.Header().Set("Content-Type", "text/event-stream")
    c.Writer.Header().Set("Cache-Control", "no-cache")
    c.Writer.Header().Set("Connection", "keep-alive")
    c.Writer.Flush()
    content := []llms.MessageContent{
        llms.TextParts(llms.ChatMessageTypeHuman, request.Question),
    }
    // 调用流式 API
    _, err := llmClient.GenerateContent(ctx, content, llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {
        fmt.Fprintf(c.Writer, "data: %s\n\n", string(chunk))
        c.Writer.Flush()
        return nil
    }))
    if err != nil {
        log.Printf("Failed to generate content: %v", err)
        c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to get response"})
        return
    }
    fmt.Fprintln(c.Writer, "data: [DONE]\n")
    c.Writer.Flush()
}

代码解析

  • llm.GenerateContent:调用 LangChainGo 生成流式数据。
  • llms.WithStreamingFunc:注册一个回调函数,每当 LLM 生成新的文本,都会实时返回。
  • c.Writer.Flush():确保数据立即推送到客户端,而不是缓存。

使用 curl 进行测试

我们先运行后端服务,具体命令如下所示:

go run main.go

然后,使用 curl 进行测试:

curl -X POST http://localhost:9527/api/chat \
    -H "Content-Type: application/json" \
    -d '{"question": "请介绍一下Go语言"}' \
    --no-buffer

⚠️注意: --no-buffer 让 curl 立即显示流式数据。

测试结果如下所示:

⚠️注意: 别忘记了在本地运行 Ollama,这里我使用的模型是 qwen2:7b!!!

前端实现

由于是一个简单的例子所以就没有用 react 框架来做,前端的效果如下所示:

这里可以放置前端代码和截图(如果有的话)

总结

本篇文章,我们从后端实现到前端流式渲染,完整实现了一个流式 AI 问答系统:

  • ✅ 使用 LangChainGo + Ollama 处理 LLM 调用
  • ✅ Gin 提供 SSE(Server-Sent Events)流式 API
  • ✅ curl 终端测试,逐步返回 AI 生成文本
  • ✅ 简单的使用了 html+css+js 实现前端实时显示

🚀 完整代码已开源,你可以尝试改进并扩展,比如:

  • 支持多轮对话,携带对话上下文记忆等。
  • 接入更强大的 LLM 模型,例如 deepseek 等。
  • 优化前端 UI 交互,可以使用 react 这类框架来实现。
  • 实现更复杂的应用场景,例如问答搜索等。
复制全文 生成海报 AI 编程 Web开发 流式处理 后端开发

推荐文章

mysql 计算附近的人
2024-11-18 13:51:11 +0800 CST
PyMySQL - Python中非常有用的库
2024-11-18 14:43:28 +0800 CST
使用 Vue3 和 Axios 实现 CRUD 操作
2024-11-19 01:57:50 +0800 CST
JavaScript 异步编程入门
2024-11-19 07:07:43 +0800 CST
js一键生成随机颜色:randomColor
2024-11-18 10:13:44 +0800 CST
JavaScript 流程控制
2024-11-19 05:14:38 +0800 CST
windows下mysql使用source导入数据
2024-11-17 05:03:50 +0800 CST
php内置函数除法取整和取余数
2024-11-19 10:11:51 +0800 CST
CentOS 镜像源配置
2024-11-18 11:28:06 +0800 CST
38个实用的JavaScript技巧
2024-11-19 07:42:44 +0800 CST
Vue3中如何处理异步操作?
2024-11-19 04:06:07 +0800 CST
MySQL 日志详解
2024-11-19 02:17:30 +0800 CST
mysql删除重复数据
2024-11-19 03:19:52 +0800 CST
使用Rust进行跨平台GUI开发
2024-11-18 20:51:20 +0800 CST
Nginx 反向代理 Redis 服务
2024-11-19 09:41:21 +0800 CST
一文详解回调地狱
2024-11-19 05:05:31 +0800 CST
Vue3中如何处理组件间的动画?
2024-11-17 04:54:49 +0800 CST
JavaScript设计模式:观察者模式
2024-11-19 05:37:50 +0800 CST
Rust开发笔记 | Rust的交互式Shell
2024-11-18 19:55:44 +0800 CST
如何实现生产环境代码加密
2024-11-18 14:19:35 +0800 CST
从Go开发者的视角看Rust
2024-11-18 11:49:49 +0800 CST
程序员茄子在线接单