CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。
这篇文章剖析一下 CangjieMagic 框架中的 AbsAgent。
首先看一下框架中的Agent类型层次结构:
AbsAgent是一个抽象类,实现了Agent接口,提供了处理Agent请求的基本流程。让我们详细分析它的实现:
public abstract class AbsAgent <: Agent {
public func chat(question: String): String {
return chat(AgentRequest(question)).content
}
public open override func chat(request: AgentRequest): AgentResponse {
// 实现代码...
}
override open public func asyncChat(request: AgentRequest): AsyncAgentResponse {
return this.executor.asyncRun(this, request)
}
}
首先,我们看到chat(question: String)函数,这是对完整chat函数的简化版本:
public func chat(question: String): String {
return chat(AgentRequest(question)).content
}
这相当于我们生活中的便捷通道。就像超市有自助结账和人工服务台一样,这个函数允许用户只需提供一个问题字符串,就能快速获取回答,而不必手动构建完整的AgentRequest对象。内部将自动为您创建一个请求对象,并从响应中提取内容返回。
chat(request: AgentRequest)函数是AbsAgent的核心,实现了请求处理的完整流程:
public open override func chat(request: AgentRequest): AgentResponse {
if (let Some(interceptor) <- this.interceptor) {
if (interceptor.shouldIntercept(request)) {
return interceptor.doIntercept(request)
} else {
interceptor.doBypass(request)
}
}
var resp = if (let Some(r) <- Instrumentor.doInstrumentBeforeAgentRun(this, request)) {
r
} else {
this.executor.run(this, request)
}
resp = Instrumentor.doInstrumentAfterAgentRun(this, request, resp)
if (let Some(memory) <- this.memory) {
if (let Some(info) <- resp.execInfo) {
memory.update(info.dialog.toString()) // Update the agent memory
}
}
return resp
}
这个函数包含几个关键步骤:
if (let Some(interceptor) <- this.interceptor) {
if (interceptor.shouldIntercept(request)) {
return interceptor.doIntercept(request)
} else {
interceptor.doBypass(request)
}
}
这就像交通系统中的红绿灯。如果Agent配置了拦截器(interceptor),系统会询问拦截器:"我们需要对这个请求进行特殊处理吗?"如果拦截器决定拦截(shouldIntercept返回true),那么请求会被重定向到拦截器处理,并直接返回结果。如果拦截器决定放行,只会记录一下这次"放行"的事实,然后继续处理请求。
拦截器可以设置为三种模式:
var resp = if (let Some(r) <- Instrumentor.doInstrumentBeforeAgentRun(this, request)) {
r
} else {
this.executor.run(this, request)
}
这类似于科学实验中的"对照组"设置。Instrumentor允许我们在Agent执行前注入特殊逻辑,可以用于测试、监控或调试。如果插桩器决定接管处理(返回Some值),则使用插桩器的结果;否则,正常执行Agent的处理逻辑。
如果没有插桩器接管,那么请求会被传递给executor执行:
this.executor.run(this, request)
executor是实际执行聊天逻辑的组件,不同类型的Agent可能使用不同的执行器实现不同的处理策略。
resp = Instrumentor.doInstrumentAfterAgentRun(this, request, resp)
这相当于科学实验中的"结果分析"阶段。无论是通过哪种方式获得的响应,都会经过这个"后处理"阶段,允许我们对结果进行分析、修改或记录。
if (let Some(memory) <- this.memory) {
if (let Some(info) <- resp.execInfo) {
memory.update(info.dialog.toString()) // Update the agent memory
}
}
最后,如果Agent配置了记忆组件,并且响应中包含执行信息,会更新Agent的记忆。这就像人类在交谈后会记住对话内容一样,让Agent能够保持对话的连贯性。
override open public func asyncChat(request: AgentRequest): AsyncAgentResponse {
return this.executor.asyncRun(this, request)
}
这个函数提供了异步调用的能力,可以理解为"非阻塞"的聊天方式,特别适合处理需要长时间等待的复杂查询。它直接将请求传递给执行器的异步函数,并返回一个可以稍后获取结果的响应对象。
AbsAgent在CangjieMagic框架中扮演着承上启下的关键角色:
这使得开发者可以专注于实现特定Agent的业务逻辑,而不必关心请求处理的通用流程。
通过学习AbsAgent,我们可以看到仓颉编程语言在构建AI应用方面的强大能力:
在实际开发中,建议:
@agent注解方式创建Agent原文作者:;如有侵权,请联系管理员删除。