大模型 aZent 框架,让大模型真正成为你的同事(1)

背景

通常大模型出现,如何有效地将大模型引入业务提供几种方式切入企业级开发

  • 知识库
  • 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}
相关推荐
光影少年1 天前
webpack打包优化
webpack·掘金·金石计划·前端工程化
光影少年2 天前
Typescript工具类型
前端·typescript·掘金·金石计划
光影少年8 天前
Promise状态和方法都有哪些,以及实现原理
javascript·promise·掘金·金石计划
光影少年8 天前
next.js和nuxt与普通csr区别
nuxt.js·掘金·金石计划·next.js
光影少年8 天前
js异步解决方案以及实现原理
前端·javascript·掘金·金石计划
光影少年12 天前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划
ZTStory15 天前
JS 处理生僻字字符 sm4 加密后 Java 解密字符乱码问题
javascript·掘金·金石计划
光影少年15 天前
webpack打包优化都有哪些
前端·webpack·掘金·金石计划
冯志浩16 天前
Harmony Next - 手势的使用(二)
harmonyos·掘金·金石计划
冯志浩17 天前
Harmony Next - 手势的使用(一)
harmonyos·掘金·金石计划