如何设计大模型开发框架的高级接口,包括 RAG、Agent、问答、聊天等。
何为高级接口高级接口指高度抽象的接口,更接近用户,远离底层LLM等技术细节,
对于用户来说,我们关心的无非如下几点内容:
• 用哪个大模型
• 对话过程中的提示和回答
• 系统提示词(用来创建智能体)
• 创建、维护、和使用知识库
• 工具的调用
重要性从上往下依次降低。
那么我们的应用程序框架也理应如此。
产品设计的真实性原则我们顺便提一下如何进行产品设计(很多设计都是同样的道理)。 从目标或者需求出发,用户必须要做的事情的就具有真实性,反之则是虚假的。我们设计产品就是保留真实性,尽量去除虚假无用的东西。 程序设计也同样如此。当然很多时候大家会魔怔,不太容易理解真实性有哪些,但这是另外一个问题。
那么我们假设使用一下程序设计来描述应一下刚刚提到的用户需求。
用哪个大模型
使用 Prompt 类来做高级抽象,load_model 提供一个 load_model 方法来加载模型,如下。
prompter = Prompt().load_model("<你的模型名称>")对话过程中的提示和回答
使用 prompt_main 方法来做高级抽象,进行对话:
response = prompter.prompt_main(prompt="你好")系统提示词
系统提示词 也是很重要的一部分,是我们定制智能体机器人的必要条件,增加 context 参数:
context = "你是一个xxx助手, ..."
response = prompter.prompt_main(prompt="Who is Joe Biden?", context=context)文件问答
为了应对常规的文件问答问题,我们提供了 prompt_file 方法来做高级抽象,如下:
response = prompter.prompt_file(file_path, query="fast query")
文件问答和知识库区别文件问答一般是临时性的,单文件或者少量文件的,即用即抛的问答和对话。 而知识库一般是长期的,多文件的,需要长期维护和频繁使用的问答和对话。
知识库和 RAG
大模型应用的重点在于知识库和 RAG,为了实现这两个功能,也比较简单, 通过 Library 来定义知识库:
# 定义知识库
library = Library().create_new_library(name)
# 添加文件到知识库
library.add_file(file_path)
# 添加多个文件
library.add_files(file_paths)
我们还可以扩展知识库的功能,比如读取网站,读取数据库等等。
library.add_webside(url)
library.add_database(database_url, table_name)
当然还有更新知识库的功能,比如更新文件,更新网站,更新数据库等等。
library.update_file(file_path)
library.update_website(url)
我们使用文件名称和路径来作为知识库文档的唯一标识,这样可以方便的更新知识库文档,也可以方便的删除知识库文档。
# 获取所有资源
library.get_resources()
# 指定类型
library.get_documents()
library.get_blocks()
library.get_images()
library.get_pages()
library.get_tables()
知识库存储按照上面的设计,最简单的存储方式就是文件存储加元数据索引。├── metadata.json
├── resources
│ └── file...
└── cache
└── ..
还有就是知识库常用的维护操作,比如更新文档,删除文档以及知识库等。
library.delete_file(file_path)
library.delete_files(file_paths)知识库问答
我们可以简单设计一个 prompt_library 方法来做知识库的问答,指定知识库即可
prompter.prompt_library(library_name, query="fast query")
实际的过程场景中我们可以一个对话加载一个 Prompt 对象,然后回来遇到如下场景, 并且随时切换:
• 对话
• 修改系统提示词,继续对话
• 上传文件,基于文件对话
• 维护知识库,基于知识库对话
• 对话过程中调用工具
• 开启、切换新的对话 ...
上面的场景基本可以使用我们上面提到的抽象方法一步实现。
关于智能体和历史消息
对于历史消息的处理,市面上的聊天产品一般有如下处理,
• 全部加载到上下文(但是对话的长度有个限制)
• 只加载最近的上下文和系统提示词
• 加载最近的上下文,对过早的上下文有一个摘要,一并加入上下文
• 一般情况下历史摘要并不会提升我们的用户体验
这三种处理方式各有优缺点,第一种就不必说,长度有限,作为智能体来说没法一直用。 后面两种用着用着就会出现莫名其妙的问题。
我觉得更好一点聊天对话应用,应该有如下能力:
• 支持多对话和历史、
• 支持智能体创建
• 可以从对话中快速创建智能体
• 智能体可快速编辑系统提示词
• 智能体可锁定和编辑样本提问及回答
• 对话过程支持切换模型
• 对话过程支持切换知识库
用户体验优化上面提到的内容,很重要的一点就是用户体验优化。 市面上的流行产品比如 Poe,可能要服务于他的商业和更多的入门级探索用户, 对于有明确需求的专业用户来说用户体验并不好。
一些程序样例
上篇文章介绍了 llmware 这个工具,其实文章前面提到框架设计就是 llmware 的高级抽象。
看两个简单的例子。
聊天对话机器人:
prompter = Prompt().load_model(model_name, temperature=0.0, sample=False)
prompt = st.chat_input("Say something")
if prompt:
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
response = prompter.prompt_main(prompt)
st.markdown(response["llm_response"].strip("\n"))
知识库问答
基于官网的例子稍微改一下:
其他
llmware 还有一些高级功能,比如函数调用、智能体、数据存储等。 不过高级的抽象也少了一些,知识库细粒度维护还需要自己实现。
另外, llmware 是设计给 私有云 和 企业级应用 使用的, 模型也是私有部署的,对于习惯了共有云服务进行 LLM API 调用的可能有些不习惯。
--- END ---
领取专属 10元无门槛券
私享最新 技术干货