开发个人Go-ChatGPT--5 模型管理 (一)

开发个人Go-ChatGP–5 模型管理 (一)

背景

开发一个chatGPT的网站,后端服务如何实现与大模型的对话?是整个项目中开发困难较大的点。
chat-GPT

如何实现上图的聊天对话功能?在开发后端的时候,如何实现stream的响应呢?本文就先介绍后端的原理,逐步攻克这个课题。

环境部署

  • 启动ollamadocker run -d -p 3000:8080 -p 11434:11434 -v ollama:/root/.ollama -v open-webui:/app/backend/data --name open-webui --restart always ollama/ollama

  • ollama 下载对话模型: docker exec -it open-webui ollama run gemma:2b

    pulling manifest 
    pulling c1864a5eb193... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 1.7 GB                         
    pulling 097a36493f71... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏ 8.4 KB                         
    pulling 109037bec39c... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏  136 B                         
    pulling 22a838ceb7fb... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏   84 B                         
    pulling 887433b89a90... 100% ▕████████████████████████████████████████████████████████████████████████████████████████████████████████████████████▏  483 B                         
    verifying sha256 digest 
    writing manifest 
    removing any unused layers 
    success
    

Stream reponse

前端

        ....const [res, controller] = await generateChatCompletion(localStorage.token, {model: model,messages: messagesBody,options: {...($settings.options ?? {})},format: $settings.requestFormat ?? undefined,keep_alive: $settings.keepAlive ?? undefined,docs: docs.length > 0 ? docs : undefined});if (res && res.ok) {console.log('controller', controller);const reader = res.body.pipeThrough(new TextDecoderStream()).pipeThrough(splitStream('\n')).getReader();...

ollamaopen-webui 前端项目实现和人类一样沟通的方法,使用的是stream监听 messages事件收到的响应,保持长连接的状态,逐渐将收到的消息显示到前端,直到后端响应结束。

后端

  • gin.Stream
...c.Stream(func(w io.Writer) bool {select {case msg, ok := <-msgChan:if !ok {// 如果msgChan被关闭,则结束流式传输return false}fmt.Print(msg)// 流式响应,发送给 messages 事件,和前端进行交互c.SSEvent("messages", msg)return truecase <-c.Done():// 如果客户端连接关闭,则结束流式传输return false}})
...
  • ollama 响应
...// llms.WithStreamingFunc 将ollama api 的响应内容逐渐返回,而不是一次性全部返回callOp := llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {select {case msgChan <- string(chunk):case <-ctx.Done():return ctx.Err() // 返回上下文的错误}return nil})_, err := llaClient.Call(context.Background(), prompt, callOp)if err != nil {log.Fatalf("Call failed: %v", err) // 处理错误,而不是 panic}
...
  • 完整代码
package mainimport ("context""fmt""io""log""net/http""github.com/gin-gonic/gin""github.com/tmc/langchaingo/llms""github.com/tmc/langchaingo/llms/ollama"
)func main() {router := gin.Default()router.GET("/ping", func(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "OK",})})router.POST("/chat", chat)router.Run(":8083")
}type Prompt struct {Text string `json:"text"`
}func chat(c *gin.Context) {var prompt Promptif err := c.BindJSON(&prompt); err != nil {c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})return}var msgChan = make(chan string)// 通过chan 将ollama 响应返回给前端go Generate(prompt.Text, msgChan)c.Stream(func(w io.Writer) bool {select {case msg, ok := <-msgChan:if !ok {// 如果msgChan被关闭,则结束流式传输return false}// fmt.Print(msg)c.SSEvent("messages", msg)return truecase <-c.Done():// 如果客户端连接关闭,则结束流式传输return false}})
}var llaClient *ollama.LLMfunc init() {// Create a new Ollama instance// The model is set to "gemma:2b"// remote url is set to "http://ollama-ip:11434"url := ollama.WithServerURL("http://ollama-ip:11434")lla, err := ollama.New(ollama.WithModel("gemma:2b"), url)if err != nil {panic(err)}llaClient = llafmt.Println("connect to ollama server successfully")
}func Generate(prompt string, msgChan chan string) {// ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) // 设置超时// defer cancel()                                                          // 确保在函数结束时取消上下文callOp := llms.WithStreamingFunc(func(ctx context.Context, chunk []byte) error {select {case msgChan <- string(chunk):case <-ctx.Done():return ctx.Err() // 返回上下文的错误}return nil})_, err := llaClient.Call(context.Background(), prompt, callOp)if err != nil {log.Fatalf("Call failed: %v", err) // 处理错误,而不是 panic}// 确保在所有数据处理完毕后关闭 msgChanclose(msgChan)
}

项目地址

jackwillsmith/openui-svelte-build (github.com)

GitHub - jackwillsmith/openui-backend-go: openui-backend-go

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/40629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue-Router4.0 报“Cannot read property ‘forEach‘ of undefined”

Vue-Router4.0在创建路由时 报“Cannot read property ‘forEach‘ of undefined” 解决办法 将路由规则名称更改为routes&#xff0c;否则报错 import { createWebHashHistory, createRouter } from vue-router; // 创建路由规定 const routes [{path: /login,name: login,co…

Linux Docker 防火墙设置 放通 MySQL(3306) Redis(6379) 端口

Linux Docker 防火墙设置 放通 MySQL(3306) Redis(6379) 端口&#xff0c;使用firewalld 防火墙或iptables &#xff0c;因此尝试重新启动 firewalld 服务&#xff0c;添加防火墙规则&#xff0c;并检查防火墙状态。以下是详细步骤&#xff1a; 1. 启动 firewalld 服务 首先启…

qt opencv 应用举例

在Qt中使用OpenCV可以实现各种图像处理和计算机视觉任务。以下是一些Qt与OpenCV联合应用的具体举例&#xff1a; 1. 图像读取与显示 读取图像&#xff1a;使用OpenCV的imread函数可以方便地读取各种格式的图像文件&#xff0c;如.bmp、.jpg、.png等。这个函数返回一个Mat对象…

【Unity数据交互】Unity中使用二进制进行数据持久化

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 专栏交流&#x1f9e7;&…

SqlSugar分表笔记

1、使用SqlSugar的分表功能时&#xff0c;.net要使用.net core&#xff1b; 我开始使用的是.net freamwork4.72&#xff0c;程序报异常&#xff0c;没能解决&#xff0c;换到.net core下面就正常&#xff1b; 2、SqlSugar自带分表支持按季度、月、周、日进行分表&#x…

ArcGIS Pro SDK (七)编辑 15 版本控制选项

ArcGIS Pro SDK &#xff08;七&#xff09;编辑 15 版本控制选项 文章目录 ArcGIS Pro SDK &#xff08;七&#xff09;编辑 15 版本控制选项获取和设置版本控制选项 环境&#xff1a;Visual Studio 2022 .NET6 ArcGIS Pro SDK 3.0 获取和设置版本控制选项 var vOptions A…

PostgreSQL 技术内幕(十七):FDW 实现原理与源码解析

对于一定规模的系统而言&#xff0c;数据仓库往往需要访问外部数据来完成分析和计算。外部数据包装器&#xff08;Foreign Data Wrapper&#xff0c; 简称 FDW&#xff09;是 PostgreSQL 提供的访问外部数据源机制。用户可以使用简单的 SQL 语句访问和操作外部数据源&#xff0…

Python面试题:Python 中的生成器(generator)是什么?有什么优点?

在Python中&#xff0c;生成器&#xff08;generator&#xff09;是一种特殊的迭代器&#xff0c;使用yield关键字生成值&#xff0c;可以逐个生成序列中的值&#xff0c;而不需要一次性将所有值加载到内存中。生成器函数在定义时使用def关键字&#xff0c;并包含一个或多个yie…

[word] Word如何快速生成一段文本 #知识分享#学习方法

Word如何快速生成一段文本 Word如何快速生成一段文本&#xff1f;有时候我们会用一大段文字来做一些功能测试&#xff0c;不少朋友的做法就是脸滚键盘&#xff0c;一顿乱按&#xff0c;这样看起来文笔不通&#xff0c;看着也会比较难受&#xff0c;测试功能的效果也不怎么理想…

uniapp中实现跳转链接到游览器(安卓-h5)

uniapp中实现跳转链接到游览器&#xff08;安卓-h5&#xff09; 项目中需要做到跳转到外部链接&#xff0c;网上找了很多都不是很符合自己的要求&#xff0c;需要编译成app后是跳转到游览器打开链接&#xff0c;编译成web是在新窗口打开链接。实现的代码如下&#xff1a; 效果&…

java基于ssm+vue 旅游信息资源平台

1前台首页功能模块 旅游资源网站 &#xff0c;在系统首页可以查看首页、景点信息、酒店信息、客房信息、交流论坛、红色文化、个人中心、后台管理、客服等内容&#xff0c;如图1所示。 图1系统功能界面图 用户登录、用户注册&#xff0c;在注册页面可以填写用户名、密码、姓名…

Redis GEO 功能解析

Redis GEO 功能解析 引言 Redis GEO 是 Redis 数据库提供的一个特殊功能,用于存储地理位置信息,并支持基于地理位置的查询。这一功能对于需要处理地理位置数据的现代应用程序来说非常宝贵,如外卖配送、社交媒体、地图服务等。本文将详细介绍 Redis GEO 的功能、使用方法,…

DFS之剪枝与优化——AcWing 165. 小猫爬山

DFS之剪枝与优化 定义 DFS之剪枝与优化指的是在执行深度优先搜索(DFS, Depth-First Search)时&#xff0c;采取的一系列策略来减少搜索空间&#xff0c;避免无效计算&#xff0c;从而加速找到问题的解。剪枝是指在搜索过程中&#xff0c;当遇到某些条件不符合解的要求或者可以…

产科管理信息系统源码:产科电子病历、高危孕产妇五色管理系统源码 孕产妇健康管理信息平台源码

产科管理信息系统源码&#xff1a;产科电子病历、高危孕产妇五色管理系统源码 孕产妇健康管理信息平台源码 产科电子病历系统是以采集病人在整个医疗护理过程中所产生的各种信息。包括病案首页、门诊病历、住院病历、出院记录、病人病程记录等全部病历文书&#xff1b;涵盖文字…

宿舍报修小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;论坛管理&#xff0c;故障上报管理&#xff0c;新闻信息管理&#xff0c;维修人员管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;新闻信息…

node.js外卖小程序-计算机毕业设计源码81838

摘要 自从计算机发展开始&#xff0c;计算机软硬件相关技术的发展速度越来越快&#xff0c;在信息化高速发展的今天&#xff0c;计算机应用技术似乎已经应用到了各个领域。在餐饮行业&#xff0c;除了外卖以外就是到店里就餐&#xff0c;在店里就餐如果需要等待点餐的话&…

转盘输入法-单独鼠标版本

序 转盘输入法&#xff0c;给你的聊天加点新意。它不用常见的九宫格或全键盘&#xff0c;而是把字母摆在圆盘上&#xff0c;一滑一滑&#xff0c;字就出来了&#xff0c;新鲜又直接。 单独鼠标版本GIF演示 演示软件下载 转盘输入法https://download.csdn.net/download/u0146…

zdppy+vue3+antd 实现表格数据渲染

基本用法 <template><a-table :columns"columns" :data-source"data"><template #headerCell"{ column }"><template v-if"column.key name"><span>xxx Name</span></template></temp…

免费鼠标连点器有吗?需要付费吗?鼠标连点器电脑版免费推荐6款!

在数字化时代&#xff0c;鼠标连点器成为了许多用户提高工作效率、优化游戏体验的得力助手。然而&#xff0c;面对市场上琳琅满目的鼠标连点器软件&#xff0c;很多用户都会产生疑问&#xff1a;是否有免费的鼠标连点器&#xff1f;它们真的需要付费吗&#xff1f;今天&#xf…

名企面试必问30题(二十二)——你对加班的看法?

1.思路 实际上&#xff0c;很多公司询问此问题&#xff0c;并非表明一定要加班&#xff0c;只是想测试您是否愿意为公司奉献。在回答时&#xff0c;一定不能有诸如不接受加班、不接受 996 等话语&#xff0c;因为没有公司能承诺永远不加班。主要回答应围绕因何原因加班&#xf…