maf

JaydenAI15 小时前
ai·c#·agent·maf·agent管道·agent中中间件
[MAF预定义Agent中间件-01]LoggingAgent——在Agent调用前后输出日志ChatClientAgent管道由三部分组成,面向LLM的ChatClient管道中预定义了一个LoggingChatClient中间件,Agent中间件管道中预定义了一个LoggingAgent中间件,除了所处位置决定的调用时机不同外,它们的设计和实现方法几乎一摸一样。所以我们以LoggingChatClient——在LLM调用前后输出日志这篇文章一样的结构来介绍LoggingAgent中间件。该中间件它在调用Agent前后输出日志,帮助我们更好地了解Agent的执行过程。它会记录每次调用的输入和输出
JaydenAI16 小时前
ai·c#·agent·maf
[MAF预定义的AIContextProvider-10]TodoProvider——用TodoList驱动Agent的任务执行当LLM需要执行一个包含多个步骤的复杂任务时,随着对话轮次的增加,提示词会变得极长,LLM极易发生注意力涣散,导致漏掉某些步骤或重复执行已完成的步骤。解决的方法也很简单,就是创建一个TodoList,把每一步都列出来,LLM每完成一步,就在对应的代办事项上做个标记,这样就能时刻提醒LLM当前的进度和剩余的步骤了。作为LangChain的Harness框架的Deep Agents提供了一个TodoListModdleware来实现这个功能,MAF中与之对应的则是TodoProvider。
JaydenAI2 天前
ai·c#·agent·agent skills·maf
[MAF预定义的AIContextProvider-02]AgentSkillsProvider——将Agent Skills引入MAFSkills针对Agent的重要性是不言而喻的。从本质上讲,Agent Skills就是随着用户与LLM对话的推进,动态加载被称为Skill作为提示词的一种机制。在大部分实现中,Skill的内容会被封装成角色为Tool的消息被添加到对话历史中,因为这样可以借助针对对话历史的压缩实现对老旧Skill的卸载。Agent Skills依然是输入增强的一种形式,所以Agent Skills在MAF中是被AgentSkillsProvider的AIContextProvider引入的。
Artech3 天前
ai·agent·maf·agent管道·ichatclient
[MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱省时间我们知道LLM的调用不仅仅是一个耗时的操作,还会产生一定的费用,所以我们希望能够尽可能地减少不必要的调用。CachingChatClient就是为此而生的一个中间件实现,它通过在内存中维护一个缓存来存储之前调用LLM的输入和输出,从而避免了对相同输入的重复调用。当我们调用GetResponseAsync方法时,CachingChatClient会先检查缓存中是否已经存在针对相同输入的响应,如果存在就直接返回缓存中的响应,而不需要再次调用LLM;如果不存在,那么它就会调用LLM来获取响应,并将输入和响应一起
Artech4 天前
ai·agent·react·maf·ichatclient
[MAF预定义ChatClient中间件-02]FunctionInvokingChatClient——实现ReAct循环和人机交互的大功臣在众多预定义的IChatClient中间件中,FunctionInvokingChatClient无疑是最重要的一个,以至于没有它整个Agent就无法工作了。原因在于驱动Agent执行的核心机制的ReAct循环就是通过FunctionInvokingChatClient实现的,我们注册的工具函数最终由它来调用。对于相对敏感的工具函数,我们还需要通过人机交互引入审批流程,这也是通过FunctionInvokingChatClient来实现的。
JaydenAI4 天前
ai·c#·agent·maf·ichatclient
[MAF预定义ChatClient中间件-09]MessageInjectingChatClient-赋予工具消息注入的能力MAF中的ReAct循环是由FunctionInvokingChatClient中间件完成的,这意味着AIFunction的调用也是由它驱动。在默认的情况下,AIFunction绑定的委托执行完成后,结果会转换成AIContent并被封装成一个角色为Tool的ChatMessage。这个ChatMessage最终被添加到对话历史中,并作为后续调用LLM的输入。换言之,AIFunction不像LangChain的工具函数一样,可以通过返回Command对象添加具有合法结构的消息列表到对话历史中。当工具在执行
Artech5 天前
ai·logging·agent·maf·ichatclient
[MAF预定义ChatClient中间件-01]LoggingChatClient——在调用前后输出日志LoggingChatClient是一个预定义的IChatClient中间件,它在调用前后输出日志,帮助我们更好地了解Agent的执行过程。它会记录每次调用的输入和输出,以及调用的时间戳等信息。这对于调试和监控Agent的行为非常有用。
JaydenAI5 天前
ai·c#·agent·memory·maf
[MAF预定义的AIContextProvider-03]ChatHistoryMemoryProvider——赋予Agent从经验中学习的能力LLM具有固化的知识,而且针对LLM的调用是完全无状态,永远只做一锤子买卖。但是交给Agent的任务基本上不可能一蹴而就,而且还希望Agent具有学习进化的能力。所以你会发现,很多的Harness手段的目的就是为了弥合两者之间的鸿沟。解决这个问题的基本的前提是:需要赋予Agent记忆。短期记忆赋予Agent在同一个语境下进行多轮对话的能力,对于MAF来说,就是Session。长期记忆实现了跨Session的信息共享,其共享范围可以针对用户(比如了解用户的偏好)、针对Agent(比如了解Agent的能力和经
Artech6 天前
ai·agent·maf·agent管道
[MAF的Agent管道详解-07]利用AIAgent中间件构建Agent管道与采用DelegatingChatClient中间件装饰IChatClient对象并构成IChatClient管道的方式类似,我们可以使用DelegatingAIAgent代表的AIAgent中间件来装饰一个AIAgent对象,并构成一个AIAgent管道。通过在不同的阶段插入不同的AIAgent中间件,我们就可以实现对Agent调用的全方位控制和增强。DelegatingAIAgent中间件链条位于整个AIAgent管道的最前端。
Artech7 天前
ai·agent·maf·agent管道
[MAF的Agent管道详解-06]ChatClientAgent对IChatClient和输入输出增强管道的整合上面我们介绍了与LLM交互的IChatClient管道、持久化对话消息的ChatHistoryProvider、以及实现输入和输出增强的AIContextProvider,接下来我们来看看ChatClientAgent是如何将它们整合在一起的。
Artech9 天前
ai·agent·maf·aicontextprovider·chathistoryprovider
[MAF的Agent管道详解-05]对话历史的持久化和输入输出的增强ChatClientAgent自身是对IChatClient对象的封装,后者提供了与LLM交互的能力。在不考虑LLM自身差异的前提下,LLM响应内容的质量和准确性取决于作为输入提供给LLM的消息列表和配置选项,如果能否提供一种灵活的机制动态地定制输入给LLM的消息列表和配置选项,无疑是非常有价值的。另一方面,LLM返回的结果往往也需要经过一些定制化的处理才能满足我们的需求,如果上述的这种机制还能对LLM返回的结果进行定制化处理,那就更加完美了。其实这个机制就实现在ChatClientAgent自身的类型定
JaydenAI10 天前
ai·c#·agent·maf·chatclient管道
[MAF预定义ChatClient中间件-05]动态修改对话配置的两种解决方案调用IChatClient的GetResponseAsync或者GetStreamingResponseAsync方法时,我们通常会传入一个ChatOptions对象来控制运行行为。当我们基于IChatClient构建一个ChatClientAgent对象时,可以指定对应的ChatClientAgentOptions。ChatClientAgentOptions携带的ChatOptions会每次应用到针对IChatClient的调用中去,所以这是绑定静态ChatOptions的一个好方式。如果某些调用需要
JaydenAI10 天前
ai·c#·agent·maf·chatclient管道·对话历史压缩
[MAF预定义ChatClient中间件-04]ReducingChatClient——通过精减对话实施又不丢失基本语义绝大部分的Agent都采用对话的方式来和用户进行交互,所以对话的内容就成了Agent决策的基础,对话历史也成为占据LLM上下文窗口的主要内容。LLM推理的质量并非与上下文的丰富程度成正向关系,有时候过多的上下文信息反而会干扰Agent的判断,导致它做出错误的决策。ReducingChatClient就是为了解决这个问题而设计的一个中间件,它通过精减对话内容来帮助Agent更好地理解用户的意图,从而做出更准确的决策。为上下文窗口腾出更多空间也是保证可靠性的一种基本的手段。
Artech10 天前
ai·agent·maf·agent管道
[MAF的Agent管道详解-04]如何让LLM按照要求的结构输出数据?针对IChatClient的结构化输出可以通过调用如下这些重载的GetResponseAsync<T>扩展方法来完成。具体的实现很简单,这些方法最终会利用指定或者默认的JsonSerializerOptions针对泛型参数T生成一个ChatResponseFormatJson对象,并作为ChatOptions的ResponseFormat属性。这个ResponseFormat承载的JSON Schema将提供给LLM指导它按照定义的格式生成输出内容。当IChatClient接收到LLM的响应结果时,利用匹
Artech11 天前
ai·llm·openai·agent·maf·agent管道·ichatclient
[MAF的Agent管道详解-03]连接LLM的IChatClient对象在IChatClient管道的最末端是一个与LLM进行交互的IChatClient对象,这个对象负责将最终的请求发送给LLM并返回响应结果。这个IChatClient对象的具体类型取决于我们使用的是什么模型以及模型的部署方式。系统提供了很多这样的IChatClient实现来支持不同的模型和部署方式。对于目前主流的LLM,我们都可以直接利用其客户端来创建一个对应的IChatClient对象.
JaydenAI11 天前
ai·人机交互·agent·react·hitl·maf·chatclient中间件
[MAF预定义ChatClient中间件-02]FunctionInvokingChatClient——实现ReAct循环和人机交互的大功臣在众多预定义的IChatClient中间件中,FunctionInvokingChatClient无疑是最重要的一个,以至于没有它整个Agent就无法工作了。原因在于驱动Agent执行的核心机制的ReAct循环就是通过FunctionInvokingChatClient实现的,我们注册的工具函数最终由它来调用。对于相对敏感的工具函数,我们还需要通过人机交互引入审批流程,这也是通过FunctionInvokingChatClient来实现的。
JaydenAI11 天前
ai·c#·agent·caching·maf·chatclient中间件
[MAF预定义ChatClient中间件-03]CachingChatClient——利用缓存省钱(Token)省时间我们指导LLM的调用不仅仅是一个耗时的操作,还会产生一定的费用,所以我们希望能够尽可能地减少不必要的调用。CachingChatClient就是为此而生的一个中间件实现,它通过在内存中维护一个缓存来存储之前调用LLM的输入和输出,从而避免了对相同输入的重复调用。当我们调用GetResponseAsync方法时,CachingChatClient会先检查缓存中是否已经存在针对相同输入的响应,如果存在就直接返回缓存中的响应,而不需要再次调用LLM;如果不存在,那么它就会调用LLM来获取响应,并将输入和响应一起