基于CangjieMagic的RAG技术赋能智能问答系统

目录

引言

示例程序分析

代码结构剖析

导入模块解读

智能体配置详情

提示词模板说明

主程序功能解析

异步聊天功能实现

检索信息展示

技术要点总结

ollama 本地部署nomic-embed-text

 运行测试

结语


引言

这段时间一直在学习CangjieMagic。前几天完成了在CangjieMagic智能体框架中集成华为云的DeepSeek服务-优快云博客,今天研究了一下本地部署。CangjieMagic支持两种本地部署:Ollma和Llama.cpp。CangjieMagic提供了一个有趣的例子markdown_qa,它根据本项目的文档实现问答助手。今天就来测试一下它。

示例程序分析

例子的链接在:项目目录预览 - CangjieMagic:基于仓颉编程语言构建的 LLM Agent 开发框架,其主要特点包括:Agent DSL、支持 MCP 协议,支持模块化调用,支持任务智能规划。 - GitCode

这段代码是一个使用 Magic DSL 框架开发的智能问答机器人程序,它能借助 RAG 技术从指定文档里获取信息来回答问题。下面是对代码的详细解释:

代码结构剖析

package magic.examples.markdown_qa
  • 此程序属于magic.examples.markdown_qa包,这表明它是 Magic 框架示例的一部分。

导入模块解读

import magic.dsl.*
import magic.prelude.*
import magic.config.Config
import magic.model.ModelManager

import log.LogLevel
  • 导入了 Magic DSL 框架的核心功能,像 DSL 注解、基础函数、配置类以及模型管理工具等都包含在内。
  • 同时还导入了日志级别配置模块。

智能体配置详情

@agent[
    model: "deepseek:deepseek-chat",
    executor: "naive",
    rag: {
        source: "./docs/tutorial.md",
        mode: "static"
    }
]
class QABot { ... }
  • 这是一个基于 DeepSeek-chat 模型的智能体,它采用了简单的执行器。
  • 配置了 RAG(检索增强生成)功能,会从./docs/tutorial.md这个 Markdown 文档中获取知识,并且使用静态模式,这意味着文档内容会被预加载。

提示词模板说明

@prompt[pattern: ERA] (
    expectation: "代码块被标签 ```cangjie 和 ```包裹",
    role: "简单问答助手",
    action: "搜索文档获取知识并回答问题"
)
  • 运用 ERA(期望 - 角色 - 行动)模式构建提示词模板。
  • 期望生成的代码块使用特定的 Cangjie 标记。
  • 该智能体的角色是作为简单问答助手,其主要行动是搜索文档并生成回答。

主程序功能解析

main () {
    Config.logLevel = LogLevel.INFO
    Config.defaultEmbeddingModel = ModelManager.createEmbeddingModel("ollama:nomic-embed-text")
  • 把日志级别设定为 INFO,这样可以显示执行过程中的信息。
  • 配置了嵌入模型,用于生成文本的向量表示,这里使用的是 Ollama 平台的 nomic-embed-text 模型。

异步聊天功能实现

    let bot = QABot()
    let aresp = bot.asyncChat("Agent RAG 怎么编写")
    for (chunk in aresp) {
        print(chunk)
    }
  • 创建了 QABot 实例,并异步询问 "Agent RAG 怎么编写" 这个问题。
  • 采用流式输出的方式打印回答内容。

检索信息展示

    if (let Some(info) <- aresp.execInfo) {
        for (info in info.retrievalInfo) {
            for (doc in info.retrieval.sources) {
                println(doc.metadata)
            }
        }
    }
}
  • 展示了回答所依据的文档元数据,这体现了 RAG 的可解释性。
  • 能看到哪些文档片段被用作了回答的参考。

技术要点总结

  1. RAG 技术:该程序将检索和大语言模型相结合,利用本地文档来增强回答的准确性。
  2. 异步处理:采用异步聊天接口asyncChat,支持流式响应,提升了用户体验。
  3. 模块化设计
    • 智能体配置与业务逻辑是分离的。
    • 提示词工程采用了标准化的模板。
  4. 模型生态集成
    • 支持 DeepSeek 等 LLM 模型。
    • 与 Ollama 平台的嵌入模型进行集成。
  5. 知识来源:以静态 Markdown 文档作为知识来源,适合特定领域的问答场景。

这个程序展示了如何使用 Magic DSL 框架开发一个基于文档的智能问答系统,它具备可配置、可扩展以及可解释的特点。

ollama 本地部署nomic-embed-text

首先下载安装Ollma:

developer@developer:~/IDEProjects$ curl https://ollama.com/install.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  5503    0  5503    0     0   7219      0 --:--:-- --:--:-- --:--:--  7212>>> Cleaning up old version at /usr/local/lib/ollama
>>> Installing ollama to /usr/local
100 13281    0 13281    0     0  16854      0 --:--:-- --:--:-- --:--:-- 16854
>>> Downloading Linux amd64 bundle
######################################################################## 100.0%
>>> Creating ollama user...
>>> Adding ollama user to render group...
>>> Adding ollama user to video group...
>>> Adding current user to ollama group...
>>> Creating ollama systemd service...
>>> Enabling and starting ollama service...
Created symlink /etc/systemd/system/default.target.wants/ollama.service → /etc/systemd/system/ollama.service.
>>> The Ollama API is now available at 127.0.0.1:11434.
>>> Install complete. Run "ollama" from the command line.
WARNING: No NVIDIA/AMD GPU detected. Ollama will run in CPU-only mode.
developer@developer:~/IDEProjects$ 

安装成功后它会自动启动服务器。

 这个实例需要‌ Nomic-embed-text模型。Nomic-embed-text ‌是一个基于 Sentence Transformers 库的句子嵌入模型,专门用于特征提取和句子相似度计算。该模型在多个任务上表现出色,特别是在分类、检索和聚类任务中,能够生成高质量的句子嵌入,这些嵌入在语义上非常接近,从而在相似度计算和分类任务中表现优异‌。

执行下面的语句下载该模型:

ollama pull nomic-embed-text

 运行测试

然后就可以修改程序适配华为版的DeepSeek,具体做法参考:在CangjieMagic智能体框架中集成华为云的DeepSeek服务-优快云博客

这个程序实际上先用本地的Nomic-embed-text模型提取文档中有用的部分,然后把它和用户问题一起发给DeepSeek。下面是简单的原理示意。

  "messages": [
    {
      "role": "system",
      "content": "## Expectation\n代码块被标签 ```cangjie 和 ```包裹\n## Role\n简单问答助手\n## Action\n搜索文档获取知识并回答问题\n\n\n# Retrieved Content\n除了系统提示词,外部知识也可以增强 Agent 的解决问题的能力。 Agent 能够从各类知识源中提取必要和有用的信息。\n目前,Agent 的 `rag` 属性表明外部知识的数据源,它接受多个数据源配置,每个数据源包含如下的键值对:\n| 属性  | 属性值 | 说明 |\n|---|---|---|\n| `source`  | `String \\| Expr`  | 数据源 |\n| `mode`  | `String`  | 使用模式,支持 `\"static\"` 和 `\"dynamic\"` 两种;默认为 `\"static\"` |\n| `description`  | `String`  | 可进一步描述数据源,帮助 Agent 更加精准地获取数据 |\n属性 `source` 表明数据的实际来源,支持两种类型:\n- 合法路径指向*预置的文件类型*\n    - 当前支持的文件类型包括 markdown, Sqlite 数据库\n- 类型为 `Retriever` 的表达式\n```cangjie\n@agent[\n  rag: { source: \"path/to/some.db\" }\n]\nclass Foo { }\n```\n⚠️注意:使用 Sqlite 数据库的功能需要配置 `cfg.toml` 中 `sqlite = \"enable\"`,且由于数据库使用了 Sqlite,所以需要安装三方依赖。详见 [third_party_libs.md](./third_party_libs.md)\n[使用示例](../src/examples/mini_rag/main.cj)\n除了通过 `@agent` 定义 Agent 之外,当前框架内置如下的几种 Agent。\n目前,我们使用宏 `@agent` 修饰 `class` 类型来定义一个 Agent 类型。\n```cangjie\n@agent class Foo { }\n```\n宏 `@agent` 支持如下属性。具体属性可参考相应章节内容\n| 属性名 | 值类型 | 说明 |\n|-------|-------|-------|\n| `description` | `String` | Agent 的功能描述;默认未设置时,将由 LLM 从提示词中自动总结出 |\n| `model` | `String` | 配置使用到的 LLM 模型服务;默认使用 gpt-4o |\n| `tools` | `Array` | 配置能够使用的外部工具 |\n| `mcp` | `Array` | 配置接入的 MCP 服务器 |\n| `rag` |   `Map` | 配置外部的知识源 |\n| `memory` |  `Bool` | 是否使用记忆,即保存 Agent 的多次问答记录(目前记忆仅支持 in-memory 非持久化数据);默认为 `false` |\n| `executor` | `String` | 规划模式;默认为 `react` |\n| `temperature` | `Float` | Agent 使用 LLM 时的 temperature 值;默认为 `0.5` |\n| `enableToolFilter` | `Bool` | 启用工具过滤功能,Agent 在执行前会自动根据输入问题选择合适的工具集合;默认 `false` |\n| `dump` | `Bool` | 调试代码用,是否打印 Agent 变换后的 AST;默认为 `false` |\n工具可以理解为 Agent 执行过程中能够执行的代码。当前 Agent 工具有两个来源:\n- 使用 DSL 直接编写的工具函数\n- 由 MCP 服务器提供的工具(MCP 服务器可视为*一组工具的集合*)。\n---end of Retrieved Content---\n\n\n\n\n"
    },
    {
      "role": "user",
      "content": "Agent RAG 怎么编写"
    }
  ],

DeepSeek收到我们提供的数据和用户的问题,就会生成解答。

下面是日志中解答的部分。 

| `temperature` | `Float` | Agent 使用 LLM 时的 temperature 值;默认为 `0.5` |
| `enableToolFilter` | `Bool` | 启用工具过滤功能,Agent 在执行前会自动根据输入问题选择合适的工具集合;默认 `false` |
| `dump` | `Bool` | 调试代码用,是否打印 Agent 变换后的 AST;默认为 `false` |
工具可以理解为 Agent 执行过程中能够执行的代码。当前 Agent 工具有两个来源:
- 使用 DSL 直接编写的工具函数
- 由 MCP 服务器提供的工具(MCP 服务器可视为*一组工具的集合*)。
---end of Retrieved Content---





2025/05/30 17:33:17.562631 INFO logger QABot: Chat Message[ user ]: Agent RAG 怎么编写
嗯,用户问的是如何编写Agent的RAG部分。我需要先回忆一下之前学过的相关知识。根据检索到的内容,RAG属性在Agent中用于配置外部知识源。首先,RAG接受多个数据源配置,每个数据源需要指定source、mode和description等属性。

source可以是文件路径或者Retriever表达式。比如,用户可能想连接一个数据库或者Markdown文件。例如,使用source: "path/to/some.db"来指定SQLite数据库。但要注意,使用SQLite需要配置cfg.toml中的sqlite选项为enable,并且安装相关依赖。

mode有static和dynamic两种模式,默认是static。static可能是指数据源在初始化时加载,而dynamic可能在运行时动态获取。需要确认用户是否需要实时更新的数据,从而选择合适的模式。

description用来进一步描述数据源,帮助Agent更准确地获取信息。这部分可能需要用户提供详细的描述,比如数据内容或结构。

然后,用户需要在@agent宏中设置rag属性。例如,@agent[rag: { source: "data.md" }]来引入Markdown文件作为知识源。如果使用多个数据源,可能需要用数组形式,但检索到的内容里提到rag是Map类型,可能需要确认是否支持多个配置。

另外,用户可能需要知道如何结合工具和RAG。比如,在工具函数中调用检索到的内容,或者在回答问题时引用这些数据。示例中的代码片段展示了如何将数据库作为RAG源,用户可能需要参考示例代码来编写自己的Agent。

还要注意,使用SQLite数据库需要安装第三方库,用户可能需要查看third_party_libs.md文档。此外,示例中的main.cj文件可能提供了具体的实现方法,建议用户参考。

总结来说,编写Agent的RAG需要配置rag属性,指定数据源路径或表达式,选择合适的模式,添加描述,并确保依赖项正确安装。用户可能需要根据具体的数据类型和需求调整配置,同时参考提供的示例代码进行实现。


在 Cangjie DSL 中编写 Agent 的 RAG 功能需要以下步骤:

1. **基本结构定义**
使用 `@agent` 宏修饰 class 来定义 Agent:

```cangjie
@agent[
  rag: {
    source: "path/to/your_data.md",  // 数据源路径
    mode: "static",                 // 使用模式
    description: "产品知识库"        // 数据源描述
  }
]
class MyAssistant {
  // Agent 的具体实现...
}
```

2. **关键参数配置**:
- `source`:支持两种形式
```cangjie
// 文件路径形式(支持 markdown/sqlite)
source: "data/product_manual.db"

// Retriever 表达式形式
source: Retriever.new("https://api.example.com/knowledge-base")
```

- `mode` 模式选择:
```cangjie
mode: "static"   // 静态加载(默认)
mode: "dynamic"  // 动态实时检索
```

3. **多数据源配置**(使用数组):
```cangjie
@agent[
  rag: [
    { 
      source: "internal_knowledge.db",
      description: "公司内部技术文档"
    },
    {
      source: Retriever.new(API_ENDPOINT),
      mode: "dynamic",
      description: "实时市场数据接口"
    }
  ]
]
```

4. **SQLite 数据库注意事项**:
- 在 `cfg.toml` 中启用:
```toml
sqlite = "enable"
```
- 需要安装依赖:
```bash
pip install sqlalchemy datasets
```

5. **典型使用场景示例**:
```cangjie
// 客户服务 Agent 示例
@agent[
  rag: {
    source: "customer_service_qa.db",
    description: "包含常见问题解答和产品故障处理方案"
  },
  memory: true
]
class CustomerServiceBot {
  // 会自动继承 RAG 检索能力
  // 在对话处理中可直接引用知识库内容
}
```

完整示例可参考框架中的 `/src/examples/mini_rag/main.cj` 实现。建议先通过 markdown 文件进行原型验证,再逐步接入数据库等结构化数据源。
---end---
[(Header 1, 用户教程), (Header 2, 外部知识)]
[(Header 1, 用户教程), (Header 2, 常用 API 介绍), (Header 3, 知识图谱), (Header 4, 使用示例)]
[(Header 1, 用户教程), (Header 2, 常用 API 介绍), (Header 3, 内置 Agent)]
[(Header 1, 用户教程), (Header 2, Agent 定义)]
[(Header 1, 用户教程), (Header 2, MCP 协议和工具)]

cjpm run finished

结语

RAG模型的优势在于可实现即时的知识更新,从而提供更高效和精准的信息服务。 CangjieMagic在这方面做得很不错,值得进一步挖掘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神一样的老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值