简介
为博客加入一个 chatbot 是件有趣也实用的事。它/他/她 可以基于博客内容和作者介绍文章,回答读者的一些简单问题。 ChatBlog(chat + blog) 或者是一个有趣有用的个人技术者互动分享模式。本文记录我的探索与实现过程。
现在流行交互式的 knowledge base + LLM 模式。博客作为技术者的 open knowledge base,如果也能 open chat,是件有趣的事情。
引
如果你要学习一项技术,有什么方法可以保持兴趣和快速上手? 我的答案是让技术在现实中应用起来,让它产生价值,进而让学习保持动力。这是我一直以来的学习方法。在这篇文章中,我将分享我应用 RAG 与 LangChain + ollama 构建我自己的技术者职业代言 AI 的尝试(这句话在我打字时由 copilot 自动补全,是不是很讽刺……)。
由于这个项目代码写得有点烂,不打算开源了。以下主要讲述设计思想。
目标
把职业代言 AI 放入我的博客中。让想了解我职业情况或技术经验的人,可以用浏览博客之外的更时髦的 Chat 方法去达到目的。
数据源
技术者职业代言 AI 要有什么知识? 无非和大部分技术者博客的内容分类相近。首先当然是知道被代言者的 “个人履历” ,然后就是技术上的经验输出( Blog 技术文章)了。理论上只需要把这东西作为语料喂给 LLM,就可以做一个职业代言 AI了。个人履历是个 markdown 文件。Blog 也是目录结构下的一堆 markdown 文件。
现实
- 我不会 LLM 的二次微调之类的高级技术,所以我的工具箱只有 RAG & Prompt 。
- 作为一个 7*24 小时的服务,我不希望 24 小时打开我的 self-hosted 电脑,也不想去租用 VPS 之类的东西。这点我打算用 On Demand boot(请求时启动电脑与服务) 的方法解决。
- self-hosted 电脑 public web 网络访问问题。直接 public ip 永远不是好主意,要用其它方法。
- 服务器的硬件配置是 4 core 无 GPU。这个配置注定只能是分钟级的响应对话了。这个无解。
设计
部署
如果一个面试官问,应该先有高级设计,逻辑设计,还是物理部署设计。正路的答案当然是 高级设计
。但 self-hosted 世界好玩的地方在于什么都得放在一起考虑,因为设计的空间是相对有限的,要在有限的资源下实现可用的应用,只能打破 pattern。所以我先从物理部署着手。
- 准备 blog 内容向量数据库初始化
用户访问 iframe 嵌入到博客中的 chatbot。流经 cloudflare,到 pi 中的 envoy
- envoy 向 nginx upstream 请求启动页面
- 启动页 html 中 javascript polling 另一个 envoy 反向代理的 webhook 的
server health waitting
服务 - webhook 调用一个 bash script ,如发现目标服务器未启动,用 wake on LAN 命令启动目标服务器
- bash script 轮询目标服务器的服务状态,直到状态健康
server health waitting
服务 返回 200 后,启动页 html 重定向到正式的 streamlit 应用地址- 搜索 向量数据库
步骤 1.2: 唤醒服务中
一些 chat 示例:
数据源
- 个人履历.md 作为 prompt 的一部分
- Blog文章 markdown 文件s。
工作流
附录:LangChain RAG 的学习笔记
LangChain 文档的烂, 在 Reddit 上的 LangChain 群组中已经是共识。我在学习 LangChain 过程中,文档中的很多例子,并没有说明实现原理。所以,我边学边画图帮助自己理解。现在也分享出来,希望对大家有帮助。
My notes on LangChain Docs: Build a Retrieval Augmented Generation (RAG) App - Part 2
A diagram to illustrate LangChain rag document: Build a Retrieval Augmented Generation (RAG) App: Part 2
结语
如果从 AI 应用技术上来说,这个 chatbot 是没多少技术含量的。在开发过程中,让我觉得有意思的有以下几方面:
如何设计和实现运行 LLM(ollama) 机器的按需要启动。
一开始,我思路是标准的 backend 开发思路,用
systemd-socket-proxyd (socket-activated service)
或envoy
在访问目标服务时 wakeup on LAN。后来我发觉在应用层面(页面)做这个操作才是用户友好和实现简单的。作为我首个 LLM 应用尝试,可以体验到很多。
记得 6 年前,kubernetes 的学习也经历过类似的过程。从开始看让人缭乱,每天刷新让人无所适从,高屋建瓴的技术文章。到自己真要逐行代码去 debug 、逐个 troubleshooting 去发现时的挫败感。但好像一部分的挫败感,加上解决问题后的收获感,才能让人更容易爬上这个学习曲线。
- 编写过程中,特别是我不熟识的 python 与 html/javascript 的编写过程中。重度使用了 AI 协同编程。
我之前对 LLM 以及 基于 LLM 的应用开发的态度是有保留的。现在看来,还是那么句话,活到老,学到老。尽量不要去定论地评价一些自己没实践尝试过的东西。就像我小时候学电脑编程,社会上的人,大都觉得这东西没什么用。时过境迁,现在我自己也何尝不是用旧观念看新事物呢?或者近几年,太过多科技泡沫,让自己对热点科技产生了怀疑和心理对抗。或者,的确是年纪增长思想也固化。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。