背景
通常大模型出现,如何有效地将大模型引入业务提供几种方式切入企业级开发
- 知识库
- agent
- prompt engineering
- 微调
为什么我要选择 Agent 这方式呢?
agent 这种方式是大模型进入企业,落地一个比较可行方案,每一个 Ai 大模型都有自身特点和擅长的领域。没有一个可以覆盖所有任务模型。大模型缺乏专业性,并且难于控制,缺乏确定性。对于没有经验人,很难通过 prompt 来控制大模型得到想要效果。针对这个问题有了 azent 的想法,agent 作为大模型的代理,通过现有信息化系统切入实际业务,真正发挥减员增效。
目标
整合大模型资源,让大模型能和业务紧密联系,发挥其应有作用。通过 azent 并有效控制大模型的输出与我们期望输出对齐。
azent 框架
- model wrapper 和 tool wrapper 分别对模型和应用进行包裹,通过 Api 形式调用和通信
- Api 层提供接口,可以 Api 接口来控制项目和观察项目
azent 框架的特点
- azent 是通讯框架,更好将资源有效整合来完成任务
- 可视化也是 azent 一个显著的特点,动态显示框架运行的状态,更加直观观察整个系统运行,跟踪系统运行
- 人的参与: agent 也可以代理人,让人直接参与到整个流程,以达到对流程的控制,让 agent 框架更符合
- 提示词引擎: prompt engine 可以帮助普通人写出高质量的 prompt,这块强化学习和遗传算法少不了
- 多工具的封装,也就是工具的扩展
- 分布式高并发,高可用,提升稳定性
相关技术
相关技术,整个框架和外部通讯依赖于 Api 调用,系统间可以 rpc 来实现跨语言调用,这个框架有点类似自动驾驶领域 Ros,对成熟模型进行封装,也支持可扩展,因为各个单位业务五花八门,各不相同,所以想设计之初考虑到灵活性,可扩展性。还有就是需要支持高并发和稳定性,就此先用 python 以后随着自己技术提升,迁移到 rust 。
设计到相关技术比较多
- 这是通讯架构,会借鉴 ROS
- 事件驱动框架,还是采用微服务,还在调研中,希望大佬给与指点
- agent 是框架核心,agent 设计是重点也是难点,
- 希望这也是一次强化学习应用,和落地的场景
agent
在框架中 agent 可以看作最小的可执行(或计算)的最小单元,不仅可以代理大模型,也有人类代理,agent 是整个框架的最小计算单元,通常 agent 还有记忆模块
- assistantAegent 代理大模型,例如 chatGPT
- decisionAgent 来代理人类
task
task 是对业务的抽象,对应实际实际一个一个的任务
- task 中是由 agents 组成的
- task 之间可以通讯,task 层级通讯为主,那么 task 看做通讯最小单元
proj
proj(office) 可以看作一个作用域概念,创建一个 project ,project 是对业务抽象,也是 task 的容器,这些 task 共同协作完成一个项目,例如设计产品,搭建网站。完成 excel 数据的统计操作等。
iprompt
好的 prompt 让我们可以更好控制大模型,prompt 生成可以进化,也就是不断学习中进步,可以 self-learning 或者 meta learning 来实现让 prompt 不断进步,设想将生成 prompt 和反馈一并输入到 update 来进行提升 prompt 生成,以及会沉淀 prompt pool 用于提供 prompt 的采样
TWrapper
- 对工具的包裹,也就为 agent 提供可使用,例如 office 的包裹
- 可扩展,框架中仅仅提供主流的工具,例如常用 office
- 将 office 等应用基本操作抽象为 Api
Agent
python
from abc import ABC,abstractmethod
class Agent(ABC):
@abstractmethod
def run(self,prompt):
pass
- 这是 Agent 抽象类
- Agent 现在暂时代理一个大模型,可能代理人,准备按行为划分
python
import json
from engine.agent import Agent
class AssistantAgent(Agent):
def __init__(self,name,client,prompt) -> None:
super().__init__()
self.name = name
self.client = client
self.prompt = prompt
self.type = "assistant"
def run(self, input):
return self.client(self.prompt.format(input))
def __str__(self) -> str:
agent_dict = {
"name":self.name,
"prompt":self.prompt,
"type":self.type
}
return json.dumps(agent_dict);
扩展一些基于基础类常用的 Agent
DecisionAgent
python
class DecisionAgent(Agent):
def __init__(self,name,tasks) -> None:
super().__init__()
self.name = name
self.tasks = tasks
def run(self,input):
return {
"output":input,
"tasks": self.tasks
}
关于 decisionAgent 设计,decisionAgent 是决定是否启动下一个 Task,所以 descisionAgent 需要 run 方法实际启动一个 task 那么 decisionAgent 存放是一个 taskid 也就是接下来要执行的 task
Task 代码
python
from collections.abc import Iterable
import uuid
import json
class Task:
def __init__(self,name) -> None:
self.name = name
self.id = uuid.uuid1()
self.agents = []
self.deps = []
def addAgent(self,agent):
self.agents.append(agent)
def run(self,input):
pass
def __str__(self) -> str:
task_dict = {
"name":self.name,
"agents":self.agents
}
return json.dumps(task_dict)
现在关于 Task 和 Agent 设计略显简陋,通过不断迭代更新 Task 和 Agent 代码以实现目标
测试
用 flask 搭建一个简单任务,来看一看效果,这里我们用 task 封装了一个 agent 然后用一个 input 来测试
- fasks 作为服务端提供 restful 服务
/tasks
获取 tasks 列表/task/<task_name>
: 启动某一个指定的任务
python
class Task(Resource):
def get(self,task_name):
input = """
When I was 6 my sister was half my age. Now
I'm 70 how old is my sister?
"""
return {'task_name':task_name,'reply':tasks[task_name].run(input)}
api.add_resource(Task, '/task/<string:task_name>')
json
{
"task_name": "two",
"reply": "When you were 6, your sister was half your age, so she was 3 years old. This means your sister is 3 years younger than you. So, if you are now 70, your sister would be 70 - 3 = 67 years old."
}
可视化既然重点,一定要下点功夫,简单右侧是 task 列表,每一个任务下显示其所属的 agent 每一个 agent 有类型和 prompt,因为这些 agent 都是大模型的 agent 所以将 prompt 显示出来,prompt 也是我们关心的,关于 prompt 应该如何更新,这部分内容还要随后仔细想一想。
Demo
任务描述: 有一段文本,关于样本检测的工作流程,需要从中提前流程以结构化数据表示,最后输出格式为 html 格式 阅读指导文件,生成路程的 html 视图的任务。
项目是这样首先分解为两个动作,也就是 2 次请求大模型,第一次是让 LLM 阅读输入文本,以列表形式将其中流程总结出来对应(agent one),然后将输出结果作为下一个动作的输入,也就是将列表转换 html ul li 标签表示输出的形式,其实之前想是一步到位,不过发现效果不好。
所以才将 1 步细化为 2 步,以后希望关于任务的划分和 agent 调度也希望交给 agent 去做
然后 preview agent 节点,返回结果给 review 如果不满意可以打回,或者向下输出想要格式,有点类似 check 流程。
python
taskOne = SequenceTask('taskone')
taskTwo = SequenceTask('tasktwo')
agent_one_prompt = "#role\n作为熟悉项目流程人员\n#workflow\n仔细阅读input的内容,分析内容提到项目工作流程,以层级列表来将工作流程描述清楚\n#input\n{} #output 输出工作流的列表"
agent_two_prompt = "#role\n作为熟悉 css 和 html 的前端开发人员\n#workflow\ninput 中列表转换 html,ul 和 li 标示输出来,如果可能添加 css 来修饰 html 呈现出精美的列表\n#input\n{}#outputFormat\n可以显示在浏览器端 html 文件"
taskOne.addAgent(ChatGPTAgent('agentone',agent_one_prompt))
taskOne.addAgent(ChatGPTAgent('agenttwo',agent_two_prompt))
taskOne.addAgent(PreviewAgent('previewagent',['taskone']))
taskTwo.addAgent(ChatGPTAgent('agentthree',agent_one_prompt))
tasks = {'taskone':taskOne,'tasktwo':taskTwo}