用Rust搞Agent开发,试了试几种调用LLM的方式

reqwest 直接去请求 deepseek 的api,想看看最基础的请求LLM到底要做多少事。

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
    dotenvy::dotenv().ok();
    let api_key = std::env::var("DEEPSEEK_API_KEY").expect("DEEPSEEK_API_KEY must be set");
    let api_url = std::env::var("DEEPSEEK_API_URL")
        .unwrap_or_else(|_| "https://api.deepseek.com/v1/chat/completions".to_string());
    let body = serde_json::json!({
        "model": "deepseek-v4-flash",
        "messages": [{"role": "user", "content": "你好,你是?"}],
        "stream": false
    });
    let response = reqwest::Client::new()
        .post(api_url)
        .header("Authorization", format!("Bearer {}", api_key))
        .header("Content-Type", "application/json")
        .body(body.to_string())
        .send()
        .await?;
    let text = response.text().await?;
    let body: serde_json::Value = serde_json::from_str(&text).unwrap();
    println!("{:#?}", body);
    Ok(())
}

然后换用 async-openai 的sdk来请求LLM,代码能少写点。

use async_openai::{Client,types::chat::{ChatCompletionRequestUserMessage,CreateChatCompletionRequestArgs},};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();

    let client = Client::new();

    let request = CreateChatCompletionRequestArgs::default()
        .model("gpt-5.4-mini")
        .messages(vec![
            ChatCompletionRequestUserMessage::from("你好,你是?").into(),
        ])
        .build()?;

    let response = client.chat().create(request).await?;

    println!("{response:#?}");
    Ok(())
}

如果是用 responses 的话,代码大概是下面这样。

use async_openai::{Client, types::responses::CreateResponseArgs};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenvy::dotenv().ok();

    let client = Client::new();

    let request = CreateResponseArgs::default()
        .model("gpt-5.4-mini")
        .input("你好,你是?")
        .build()?;

    let response = client.responses().create(request).await?;

    println!("{response:#?}");
    Ok(())
}

小白问一下,async-openai这个库现在稳定吗?我看它官网文档好像好久没更新了,有点不敢用,是不是直接用reqwest更保险一点?还有那个responses模块和chat模块到底啥区别啊,有点搞不明白。

rust写agent比go复杂一截 异步要想清楚

同问,蹲个后续。

其实直接用reqwest写也没那么麻烦,我最近也在搞agent,不过我是把API调用封装成一个trait,后面换模型方便。就比如先定义一个LlmClient trait,里面就一个async fn chat(&self, messages: Vec) → Result。然后给DeepSeek、OpenAI这些分别实现一下。reqwest那块代码虽然原始,但自己控制得更细,比如你想加个自定义的retry逻辑或者特定header,SDK不一定支持。我之前用async-openai就遇到它超时设置不太灵活的问题,最后还是自己用reqwest重写了调用层。