嗨!我是小谷,大家好久不见~
前段时间网上冲浪,发现一个 大模型在垂类场景的典型应用 ,定位是 Github 智能答疑助手,功能包含优质仓库推荐、代码片段解读、提 issue 、查 issue … 对于 Ant Design 这种前端组件库,甚至可以通过一张原型图,给出界面上包含哪些 Ant Design 的原子组件!
亲自体验了一番,感觉确实很方便,发现源码也已经在 Github 上开源了,整体实现涉及 Prompt 调优、向量化知识库构建 以及 Langchain 工具链集成,每个环节都有很多学习之处,那就让我们一起通过源码看看大模型部分的实现细节吧!
PeterCat 简介
如官网介绍,PeterCat 是专为社区维护者和开发者打造的智能答疑机器人解决方案。
支持用户在平台中通过对话模式快速搭建一个 Github 仓库的智能答疑机器人,内置 提 issue、查 issue、回 issue、Discussion 回复、PR Summary、Code Review、项目信息查询 基础能力,也可以通过自托管部署方案和一体化应用 SDK 集成至项目仓库。
目前在 PeterCat 平台中,已有 9 个前端方向典型应用的智能答疑机器人。
以 Ant Design 为例,我们不仅可以通过 Ant Design 答疑小助手来了解如何快速上手 Ant Design 组件库的使用,还能通过一张原型图快速判断出通过 Ant Design 的哪些组件可以实现,甚至连图表和文字都能准确识别,大模型对于图片中内容的解析真的有超乎预期!
原型稿 | 识别结果 |
---|---|
![]() |
![]() |
接下来,就让我们一起来看看 PeterCat 是如何做到的吧!
源码解读
业界通用方案
所谓大模型垂类应用场景,指的是大模型在特定领域的应用,主要解决的是诸如 GPT、通义千问 等通用大模型在特定领域由于缺乏领域知识而表现欠佳的问题。这类场景通常需要喂给大模型大量的数据作为知识库进行辅助决策。
关于大模型在垂类场景的应用,常见的执行 SOP 包含:
向量化知识库构建 -> (大模型微调) -> 用户 prompt 输入 -> 向量化关键词检索 -> 查询结果精排 -> 大模型 prompt 生成 -> 大模型意图识别 -> 结果生成。
如果是自建大模型,还可以通过大模型微调来让意图识别质量更高。
可以发现,无论在知识库构建阶段,还是关键词检索阶段,向量化 都是被反复提及的概念。
所谓向量化,其实指的是将大规模的数据或文本转化为向量的表示方式。经过向量化处理的数据,能够更好地表达数据之间的关系和相似性,提高模型的训练和预测效果。
而从向量化关键词检索到大模型 prompt 生成的过程,就是我们常说的 RAG ,目的是为了最终喂给大模型的 Prompt 质量更高,也就是大家常说的如何更好的向大模型提问。
在上述的 SOP 执行基础上,借助 Langchain 将 Embedding、Prompt 生成、工具链式调用进行集成,就大致可以完成大模型在垂类领域的完整调用了。
如果把大模型比作是人类的大脑,那么 Langchain 可以类比为人类的四肢和躯干,大模型只用专注于模型预测的核心工作,至于工具调用、上下文记忆、多轮对话等工作交给 Langchain 进行统筹管理即可。
PeterCat 源码
有了上述一些基础知识,我们来看下 PeterCat 在大模型相关模块的实现细节:
PeterCat 大模型相关的代码主要集中在 server/agent 目录下,整体包含:
bot 构建、llm 调用、prompt 设定和 tools 工具预置四大能力,
最终以 base.py 和 qa_chat.py 文件作为 Langchain 处理用户输入以及大模型结果输出的中枢。
而向量化知识库的构建,以及 RAG 检索生成,集中在 petercat_utils 目录下实现,最终通过 server/routers/rag.py 进行调用。
Agent 工作流
按照 PeterCat 官方文档的介绍,当用户在 PeterCat 平台中输入了一个 Github 仓库地址或名称时,创建智能答疑机器人的整个 Agent 工作流为:
使用创建工具,生成该仓库答疑机器人的各项配置(Prompt,、名字、 头像、开场白、引导语、工具集……),同时触发 Issue 和 Markdown 的入库任务。
这些任务会拆分为多个子任务,将该仓库的所有已解决 issue 、高票回复以及所有 Markdown 文件内容经过 load -> split -> embed -> store 的加工过程进行知识库构建,作为机器人的回复知识依据。
RAG
PeterCat 服务端,采用 FastAPI 框架开发,使用了 supabase 作为数据存储方案。
为了在 RAG 检索生成时比对效率更高,机器人关联的 Github 仓库中所有文档都是通过 Embedding 处理后分类存入数据库中。
用户输入的 query 也会经过 Embedding 化后,与 supabase 中存储的知识进行匹配,再返回匹配结果。
这个过程就包含了前文说的 load -> split -> embed -> store 。
def supabase_embedding(documents, **kwargs: Any):
from langchain_text_splitters import CharacterTextSplitter
try:
text_splitter = CharacterTextSplitter(
chunk_size=CHUNK_SIZE, chunk_overlap=CHUNK_OVERLAP
)
docs = text_splitter.split_documents(documents)
embeddings = OpenAIEmbeddings()
vector_store = SupabaseVectorStore.from_documents(
docs,
embeddings,
client=get_client(),
table_name=TABLE_NAME,
query_name=QUERY_NAME,
chunk_size=CHUNK_SIZE,
**kwargs,
)
return vector_store
except Exception as e:
print(e)
return None
def add_knowledge_by_doc(config: RAGGitDocConfig):
loader = init_github_file_loader(config)
documents = loader.load()
supabase = get_client()
is_doc_added_query = (
supabase