返回顶部
热门问答 更多热门问答
技术文章 更多技术文章

RAG 系统开发 01:使用 rig 调用 ollama 的模型

[复制链接]
链载Ai 显示全部楼层 发表于 10 小时前 |阅读模式 打印 上一主题 下一主题

这是个系列文章,将介绍基于 Rust 语言生态来开发一个 RAG 系统。本文是文章的第一篇,主要介绍如何使用rig[1]来调用 ollama 模型。

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;display: table;padding: 0px 0.2em;color: rgb(255, 255, 255);background: rgb(15, 76, 129);">项目准备

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;padding-left: 8px;color: rgb(63, 63, 63);">设置 Rust 开发环境

ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;letter-spacing: 0.1em;color: rgb(63, 63, 63);">推荐使用RsProxy来设置 Rust 开发环境,步骤非常的简单:

    ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;color: rgb(63, 63, 63);" class="list-paddingleft-1">
  1. ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;text-indent: -1em;display: block;margin: 0.2em 8px;color: rgb(63, 63, 63);">
    1. 设置 Rustup 镜像, 修改配置ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 12.6px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;">~/.zshrcingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 12.6px;text-align: left;line-height: 1.75;color: rgb(221, 17, 68);background: rgba(27, 31, 35, 0.05);padding: 3px 5px;border-radius: 4px;">~/.bashrc
ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-feature-settings: normal;font-variation-settings: normal;font-size: 14px;margin: 10px 8px;color: rgb(201, 209, 217);background: rgb(13, 17, 23);text-align: left;line-height: 1.5;overflow-x: auto;border-radius: 8px;padding: 0px !important;">export RUSTUP_DIST_SERVER="https://rsproxy.cn"
export RUSTUP_UPDATE_ROOT="https://rsproxy.cn/rustup"
    ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;color: rgb(63, 63, 63);" class="list-paddingleft-1">
  1. ingFang SC", "Hiragino Sans GB", "Microsoft YaHei UI", "Microsoft YaHei", Arial, sans-serif;font-size: 14px;text-indent: -1em;display: block;margin: 0.2em 8px;color: rgb(63, 63, 63);">
    2. 安装 Rust(请先完成步骤一的环境变量导入并 source rc 文件或重启终端生效)
curl--proto'=https'--tlsv1.2-sSfhttps://rsproxy.cn/rustup-init.sh|sh
  1. 3. 设置 crates.io 镜像, 修改配置~/.cargo/config.toml
[source.crates-io]
replace-with='rsproxy-sparse'
[source.rsproxy]
registry="https://rsproxy.cn/crates.io-index"
[source.rsproxy-sparse]
registry="sparse+https://rsproxy.cn/index/"
[registries.rsproxy]
index="https://rsproxy.cn/crates.io-index"
[net]
git-fetch-with-cli=true

安装 ollama 并下载模型

详细安装及使用可我之前文章:本地运行 deepseek-r1,LLM 安装简明指南

创建项目

开发工具建议使用VSCode,并安装插件rust-analyzer。在命令行终端执行以下命令创建 Rust 项目并添加必要的 crates:

cargo new fusion-rag
cd fusion-rag
cargo add rig-core --features derive
cargo add tokio --features full

现在项目已经建好,可以通过 VSCode 打开

code.

执行默认的main.rs文件,可以运行成功。

使用 rig-core

通过 openai 兼容模式访问 ollama API

编辑main.rs文件,修改为以下代码:

userig::{completion:rompt, providers};

#[tokio::main]
asyncfnmain()->Result<(),Box<dyncore::error::Error>> {
letclient= providers:penai::Client::from_url("ollama","http://localhost:11434/v1");
letv1= client
.agent("qwen2.5:latest")// .agent("deepseek-r1:latest")
// preamble 用于设置对话的 `system` 部分,通常设置为聊天上下文的提示语
.preamble("你人工智能助手,你更擅长逻辑推理以及中文和英文的对话。")
.build();

// prompt 用于设置对话的 `user` 部分,用于提供每次对话的内容
letresponse= v1.prompt("1.1 和 1.11 哪个大?").await?;
println!("回答: {}", response);
Ok(())
}

运行程序,可获得如下输出:

回答: 在数值比较中,1.1 和 1.11 进行比较时,可以看出 1.11 比 1.1 要大。

数学上具体的比较过程如下:

-首先比较小数点后的第一位数字。在这个例子中都是“1”,所以这一位是相等的。
-然后继续比较下一位,也就是第二个小数点后的数字。对于 1.1 而言,这一步之后没有数字,所以我们假定为 0(在实际中通常会以零补齐),因此可以认为 1.1 相当于 1.10。这时候我们可以看到在“1.10”和“1.11”之间进行比较,“1.11”的结果显然比“1.10”大。

所以,结论是:1.11 大于 1.1。

提示:使用deepseek-r1:latest模型可以获得更详细的回答(包含思考过程),但需要的资源更多且输出的内容也会更长。读者可以自行选择适合自己的模型。

通过嵌入模型实现 RAG

nomic-embed-text 模型

nomic-embed-text是专门用于生成文本嵌入(text embeddings)的模型。文本嵌入是将文本数据转换为向量表示的过程,这些向量能够捕捉文本的语义信息,在很多自然语言处理任务中都非常有用,例如信息检索(找到与查询文本语义相近的文档)、文本分类、聚类分析等。可通过以下命令下载此模型。

ollamapullnomic-embed-text

添加 crates 依赖

cargoaddserde

实现 RAG 逻辑

编辑main.rs文件,更新为以下代码:

userig::{
completion:rompt, embeddings::EmbeddingsBuilder, providers,
vector_store::in_memory_store::InMemoryVectorStore, Embed,
};
useserde::Serialize;

// 需要进行 RAG 处理的数据。需要对 `definitions` 字段执行向量搜索,
// 因此我们为 `WordDefinition` 标记 `#[embed]` 宏以派生 `Embed` trait。
#[derive(Embed, Serialize, Clone, Debug, Eq, PartialEq, Default)]
structWordDefinition{
id:String,
word:String,
#[embed]
definitions:Vec<String>,
}

#[tokio::main]
asyncfnmain()->Result<(),Box<dyncore::error::Error>> {
constMODEL_NAME: &str="qwen2.5";
constEMBEDDING_MODEL: &str="nomic-embed-text";
letclient= providers:penai::Client::from_url("ollama","http://localhost:11434/v1");
letembedding_model= client.embedding_model(EMBEDDING_MODEL);

// 使用指定的嵌入模型为所有文档的定义生成嵌入向量
letembeddings= EmbeddingsBuilder::new(embedding_model.clone())
.documents(vec![
WordDefinition {
id:"doc0".to_string(),
word:"flurbo".to_string(),
definitions:vec![
"1. *flurbo* (名词):flurbo是一种生活在寒冷行星上的绿色外星人。".to_string(),
"2. *flurbo* (名词):一种虚构的数字货币,起源于动画系列《瑞克和莫蒂》。".to_string()
]
},
WordDefinition {
id:"doc1".to_string(),
word:"glarb glarb".to_string(),
definitions:vec![
"1. *glarb glarb* (名词):glarb glarb是次郎星球居民祖先用来耕种土地的古老工具。".to_string(),
"2. *glarb glarb* (名词):一种虚构的生物,发现于仙女座星系Glibbo星球遥远的沼泽地。".to_string()
]
},
])?
.build()
.await?;

// 使用这些嵌入创建向量存储
letvector_store= InMemoryVectorStore::from_documents(embeddings);

// 创建向量存储索引
letindex= vector_store.index(embedding_model);

letrag_agent= client
.agent(MODEL_NAME)
.preamble(
"您是这里的词典助理,帮助用户理解单词的含义。
您将在下面找到其他可能有用的非标准单词定义。",
)
.dynamic_context(1, index)
.build();

// 提示并打印响应
letresponse= rag_agent.prompt("\"glarb glarb\" 是什么意思?").await?;
println!("{}", response);

Ok(())
}

先运行程序看看效果,可获得如下输出:

$cargo run -q
在给出的定义中,“glarb glarb”有以下两种解释:

1. **名词**: 这是次郎星球居民祖先用来耕种土地的古老工具。
2. **名词**: 一种虚构的生物,发现于仙女座星系Glibbo星球遥远的沼泽地。

请注意,这是基于提供的文档定义,“glarb glarb”可能是两个不同的名词,具有不同的含义和背景。

当我们注释掉.dynamic_context(1, index)一行时再次运行,输出结果如下:

$cargo run -q
很抱歉,“glarb glarb”并不是一个已知的词语或表达方式,在标准语言中没有明确的意义。这可能是误输入或者是某种特定情境下的自创语句。具体含义需要更多上下文信息来确定。如果您是在某个游戏中、书中或是特殊社群里看到这个短语,可能需要参照该环境中的规则或解释。

可以看到,我们在使用.dynamic_context(1, index)函数后,这个函数会根据输入的提示,从向量存储中搜索最相似的文档,然后将这些文档添加到提示中,从而实现 RAG(Retrieval Augmented Generation)的效果。

小结

本文简单的介绍了如何使用 rig-core 库来使用 Ollama 的本地模型实现 RAG。这是一个基本的示例,实际应用中可能需要根据需求进行一些调整和扩展。后面会有更详细的介绍和示例,比如:文档(PDF、Word、excel、PPT)解析、数据持久化存储、……敬请期待。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

链载AI是专业的生成式人工智能教程平台。提供Stable Diffusion、Midjourney AI绘画教程,Suno AI音乐生成指南,以及Runway、Pika等AI视频制作与动画生成实战案例。从提示词编写到参数调整,手把手助您从入门到精通。
  • 官方手机版

  • 微信公众号

  • 商务合作

  • Powered by Discuz! X3.5 | Copyright © 2025-2025. | 链载Ai
  • 桂ICP备2024021734号 | 营业执照 | |广西笔趣文化传媒有限公司|| QQ