Rust中LangChain与大语言模型集成:知识库应用实战案例 (2025年05月)

云信安装大师
90
AI 质量分
4 5 月, 2025
5 分钟阅读
0 阅读

Rust中LangChain与大语言模型集成:知识库应用实战案例 (2025年05月)

引言

在AI技术快速发展的2025年,将大语言模型(LLM)与知识库系统集成已成为企业智能化的标配。本文将展示如何使用Rust语言结合LangChain框架,构建一个高效的知识库应用。通过这个实战案例,您将学习到:

  • 如何在Rust中集成LangChain
  • 如何连接大语言模型API
  • 如何实现知识检索与问答功能

准备工作

环境要求

  1. Rust 1.75+ (建议使用rustup安装最新版)
  2. Cargo (Rust包管理器)
  3. OpenAI API密钥或其他LLM服务密钥
  4. PostgreSQL数据库(用于存储知识库)

安装依赖

代码片段
cargo add tokio --features full
cargo add serde --features derive
cargo add reqwest --features json
cargo add langchain-rust
cargo add sqlx --features postgres,runtime-tokio-rustls

项目结构

代码片段
/knowledge-base-app
├── Cargo.toml
├── src/
│   ├── main.rs         # 主程序入口
│   ├── llm.rs          # LLM集成模块
│   ├── db.rs           # 数据库模块
│   └── chain.rs        # LangChain处理逻辑

核心实现步骤

1. 初始化LangChain环境

首先创建llm.rs文件设置LLM连接:

代码片段
use langchain_rust::{
    llm::openai::OpenAI,
    llm::LLM,
};

pub struct LLMService {
    client: OpenAI,
}

impl LLMService {
    pub fn new(api_key: String) -> Self {
        let client = OpenAI::new()
            .with_api_key(api_key)
            .with_model("gpt-4-turbo"); // 2025年最新模型

        Self { client }
    }

    pub async fn generate(&self, prompt: &str) -> Result<String, Box<dyn std::error::Error>> {
        let response = self.client.generate(prompt).await?;
        Ok(response)
    }
}

原理说明
OpenAI结构体是LangChain提供的客户端封装
with_model指定使用哪个LLM版本
generate方法发送提示词并获取响应

2. 知识库数据库设计

db.rs中定义数据模型:

代码片段
use sqlx::{Pool, Postgres};

#[derive(sqlx::FromRow)]
pub struct KnowledgeItem {
    pub id: i32,
    pub title: String,
    pub content: String,
    pub embedding: Vec<f32>, // 存储文本向量
}

pub struct KnowledgeBase {
    pool: Pool<Postgres>,
}

impl KnowledgeBase {
    pub async fn new(database_url: &str) -> Result<Self, sqlx::Error> {
        let pool = Pool::<Postgres>::connect(database_url).await?;

        // 自动创建表结构(生产环境建议使用迁移工具)
        sqlx::query(
            r#"
            CREATE TABLE IF NOT EXISTS knowledge_items (
                id SERIAL PRIMARY KEY,
                title TEXT NOT NULL,
                content TEXT NOT NULL,
                embedding vector(1536) -- OpenAI嵌入维度
            )
            "#
        ).execute(&pool).await?;

        Ok(Self { pool })
    }

    // ...其他方法将在下文实现...
}

注意事项
vector(1536)是PostgreSQL的向量扩展,需要安装pgvector扩展
– 生产环境应该使用数据库迁移工具如diesel或sqlx的迁移功能

3. LangChain处理流水线

chain.rs中构建处理链:

代码片段
use langchain_rust::{
    chains::{Chain, ConversationalChain},
    prompt_args,
};

pub struct KnowledgeChain {
    chain: ConversationalChain,
}

impl KnowledgeChain {
    pub fn new(llm_service: &LLMService) -> Self {
        let chain = ConversationalChain::new()
            .with_llm(llm_service.client.clone())
            .with_prompt_template("基于以下上下文回答问题:\n\n{context}\n\n问题: {question}");

        Self { chain }
    }

    pub async fn query(
        &self,
        context: &str,
        question: &str,
    ) -> Result<String, Box<dyn std::error::Error>> {
        let args = prompt_args! {
            "context" => context,
            "question" => question,
        };

        let result = self.chain.invoke(args).await?;
        Ok(result)
    }
}

关键点
ConversationalChain适合问答场景,会维护对话历史
prompt_args!宏用于构建提示词模板变量

4. 主程序集成

main.rs中整合所有组件:

代码片段
mod llm;
mod db;
mod chain;

use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化配置
    dotenv::dotenv().ok();

    // 初始化服务组件
    let llm_service = llm::LLMService::new(
        env::var("OPENAI_API_KEY").expect("缺少OPENAI_API_KEY")
    );

    let kb = db::KnowledgeBase::new(
        &env::var("DATABASE_URL").expect("缺少DATABASE_URL")
    ).await?;

    let chain = chain::KnowledgeChain::new(&llm_service);

    // CLI交互循环(实际项目可替换为Web接口)
    loop {
        println!("请输入问题(输入q退出):");

        let mut question = String::new();
        std::io::stdin().read_line(&mut question)?;

        if question.trim() == "q" { break; }

        // TODO: 从知识库检索相关内容

        if let Some(context) = retrieve_context(&kb, &question).await? { 
            let answer = chain.query(&context, &question).await?;
            println!("回答:\n{}\n", answer);
        } else {
            println!("知识库中没有相关信息");
        }
    }

    Ok(())
}

完整知识检索实现

完善db.rs中的检索功能:

代码片段
impl KnowledgeBase {
     // ...之前代码...

     /// 存储知识条目并生成嵌入向量
     pub async fn add_knowledge(
         &self,
         title: &str,
         content: &str,
         embedding_client: &EmbeddingClient, // LangChain的嵌入客户端 
     ) -> Result<i32, Box<dyn std::error::Error>> {
         let embedding = embedding_client.embed(content).await?;

         let id = sqlx::query!(
             r#"
             INSERT INTO knowledge_items (title, content, embedding)
             VALUES ($1, $2, $3)
             RETURNING id
             "#,
             title, content, embedding.as_slice()
         )
         .fetch_one(&self.pool)
         .await?
         .id;

         Ok(id)
     }

     /// 语义搜索相关知识条目 
     pub async fn search_similar(
         &self,
         query_embedding: &[f32],
         limit: i64,
     ) -> Result<Vec<KnowledgeItem>, Box<dyn std::error::Error>> { 
         let items = sqlx::query_as!(
             KnowledgeItem,
             r#"
             SELECT id, title, content, embedding as "embedding!: Vec<f32>"
             FROM knowledge_items 
             ORDER BY embedding <-> $1 
             LIMIT $2 
             "#,
             query_embedding as &[f32],
             limit 
         )
         .fetch_all(&self.pool)
         .await?;

         Ok(items)
     }
}

然后在main.rs中添加检索逻辑:

代码片段
async fn retrieve_context(
    kb: &db::KnowledgeBase,
    question: &str,
) -> Result<Option<String>, Box<dyn std::error::Error>> {

   use langchain_rust::{embeddings::{Embeddings}}; 

   let embedder = OpenAIEmbeddings {};
   let query_embedding = embedder.embed_query(question).await?; 

   // Top3最相关的知识条目 
   let items = kb.search_similar(&query_embedding,3).await?; 

   if items.is_empty() { return Ok(None); }

   // Combine top items into context string  
   let context:String=items.iter().map(|item|format!("标题:{}\n内容:{}\n",item.title ,item.content)).collect(); 

   Ok(Some(context))
}

部署与优化建议

  1. 性能优化

    • Redis缓存频繁查询的结果
    • pgvector索引加速向量搜索:
      代码片段
      CREATE INDEX ON knowledge_items USING ivfflat (embedding vector_l2_ops) WITH (lists=100);<br>
      
  2. 生产环境建议
    “`bash

    Docker部署PostgreSQL with pgvector

    docker run –name pgvector -e POSTGRES_PASSWORD=password -p5432 :5432 ankane/pgvector

    Rust项目发布优化编译

    RUSTFLAGS=”-C target-cpu=native” cargo build–release

3.监控与日志:

代码片段
# Cargo.toml添加依赖  
tracing="0.1"  
tracing-subscriber="0.3"  

// main.rs初始化日志  
tracing_subscriber ::fmt().init();  

//关键操作添加日志追踪  
#[tracing ::instrument]  
asyncfn retrieve_context(...){...}  

常见问题解决

Q:pgvector扩展安装失败

A:

代码片段
进入PostgreSQL命令行执行:  
CREATE EXTENSION IF NOT EXISTS vector;  

如果报错说明需要先安装系统级依赖:  

# Ubuntu/Debian  
sudo apt install postgresql -XX-contrib  

# MacOS (Homebrew)  
brew install postgresql_vector  

Q:Rust编译时报langchain-rust找不到

A:
确保Cargo.toml指定正确的git源(2025年可能已发布到crates.io):

代码片段
[dependencies]  
langchain-rust={git="https://github.com/yourlangchain/rust.git",branch="main"}   

Q:OpenAI响应速度慢

A:
1.调整超时设置:

代码片段
let client=OpenAI ::new()   
.with_timeout(std ::time ::Duration ::from_secs(30));   

2.**启用流式响应**:   

let stream=client.stream(prompt). await ?;   

for chunk in stream{   
println!("{: ?}",chunk ?);   
}   

总结

本文完整实现了:

1.Rust中LangChain与LLM的集成方案
2.PostgreSQL向量搜索的知识库架构
3.端到端的问答系统流水线

关键优势:

✔️ 高性能: Rust+pgvector实现毫秒级语义搜索
✔️ 可扩展:轻松切换不同LLM提供商
✔️ 生产就绪:包含错误处理和监控方案

下一步改进方向:

•增加PDF/网页爬虫自动更新知识库
•实现用户反馈循环优化答案质量
•添加多租户支持

希望这个案例能帮助您在Rust生态中构建更强大的AI应用!

原创 高质量