ITPub博客

首页 > 数据库 > 数据库开发技术 > 【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(7):AbsAgent

【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(7):AbsAgent

数据库开发技术 作者:96tlq4q9 时间:2025-04-10 08:57:09 0 删除 编辑

CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。

这篇文章剖析一下 CangjieMagic 框架中的 AbsAgent。

1 代码结构与继承关系

首先看一下框架中的Agent类型层次结构:

2 AbsAgent的核心功能分析

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)
    }
}

2.1 简化接口函数

首先,我们看到chat(question: String)函数,这是对完整chat函数的简化版本:

public func chat(question: String): String {
    return chat(AgentRequest(question)).content
}

这相当于我们生活中的便捷通道。就像超市有自助结账和人工服务台一样,这个函数允许用户只需提供一个问题字符串,就能快速获取回答,而不必手动构建完整的AgentRequest对象。内部将自动为您创建一个请求对象,并从响应中提取内容返回。

2.2 主要流程处理

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
}

这个函数包含几个关键步骤:

1) 拦截器处理
if (let Some(interceptor) <- this.interceptor) {
    if (interceptor.shouldIntercept(request)) {
        return interceptor.doIntercept(request)
    } else {
        interceptor.doBypass(request)
    }
}

这就像交通系统中的红绿灯。如果Agent配置了拦截器(interceptor),系统会询问拦截器:"我们需要对这个请求进行特殊处理吗?"如果拦截器决定拦截(shouldIntercept返回true),那么请求会被重定向到拦截器处理,并直接返回结果。如果拦截器决定放行,只会记录一下这次"放行"的事实,然后继续处理请求。

拦截器可以设置为三种模式:

  • 总是拦截(Always)
  • 周期性拦截(Periodic)- 例如每处理3个请求拦截一次
  • 条件拦截(Conditional)- 基于请求内容决定是否拦截
2) 执行前的插桩处理
var resp = if (let Some(r) <- Instrumentor.doInstrumentBeforeAgentRun(this, request)) {
    r
} else {
    this.executor.run(this, request)
}

这类似于科学实验中的"对照组"设置。Instrumentor允许我们在Agent执行前注入特殊逻辑,可以用于测试、监控或调试。如果插桩器决定接管处理(返回Some值),则使用插桩器的结果;否则,正常执行Agent的处理逻辑。

3) 执行主体逻辑

如果没有插桩器接管,那么请求会被传递给executor执行:

this.executor.run(this, request)

executor是实际执行聊天逻辑的组件,不同类型的Agent可能使用不同的执行器实现不同的处理策略。

4) 执行后的插桩处理
resp = Instrumentor.doInstrumentAfterAgentRun(this, request, resp)

这相当于科学实验中的"结果分析"阶段。无论是通过哪种方式获得的响应,都会经过这个"后处理"阶段,允许我们对结果进行分析、修改或记录。

5) 记忆更新
if (let Some(memory) <- this.memory) {
    if (let Some(info) <- resp.execInfo) {
        memory.update(info.dialog.toString()) // Update the agent memory
    }
}

最后,如果Agent配置了记忆组件,并且响应中包含执行信息,会更新Agent的记忆。这就像人类在交谈后会记住对话内容一样,让Agent能够保持对话的连贯性。

2.3 异步接口实现

override open public func asyncChat(request: AgentRequest): AsyncAgentResponse {
    return this.executor.asyncRun(this, request)
}

这个函数提供了异步调用的能力,可以理解为"非阻塞"的聊天方式,特别适合处理需要长时间等待的复杂查询。它直接将请求传递给执行器的异步函数,并返回一个可以稍后获取结果的响应对象。

3 AbsAgent在框架中的关键作用

AbsAgent在CangjieMagic框架中扮演着承上启下的关键角色:

  • 向上:实现了Agent接口定义的所有必要函数
  • 向下:为具体的Agent实现(如AgentProxy和BaseAgent)提供了通用功能

这使得开发者可以专注于实现特定Agent的业务逻辑,而不必关心请求处理的通用流程。

4 小结与应用建议

通过学习AbsAgent,我们可以看到仓颉编程语言在构建AI应用方面的强大能力:

  1. 类型系统支持接口和抽象类,实现了清晰的架构设计
  2. Option类型的使用增强了代码的安全性
  3. 函数式编程风格与面向对象编程相结合,代码简洁而强大

在实际开发中,建议:

  1. 如果使用现有框架功能,优先考虑@agent注解方式创建Agent
  2. 需要深度自定义Agent行为时,可以继承BaseAgent或直接继承AbsAgent
  3. 利用拦截器实现请求过滤、转发或修改
  4. 利用Instrumentor进行监控和调试

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-02-05

  • 博文量
    18
  • 访问量
    638