openai-interface 0.14.0

A low-level Rust interface for the OpenAI API
Documentation
//! Non-streaming chat completion against Z.ai / 智谱 GLM (BigModel), using
//! GLM-proprietary fields gated behind the `zai` cargo feature.
//!
//! ```sh
//! cargo run --features zai --example chat_zai
//! ```
//!
//! Requires `ZAI_API_KEY` in the environment (the international Z.ai key; the
//! BigModel key from `open.bigmodel.cn` works against the same base URL). TLS:
//! add the `ferritls` feature (`cargo run --features "zai,ferritls" --example
//! chat_zai`) or install your own rustls crypto provider — see the crate docs
//! ("TLS Crypto Provider").

use openai_interface::chat::create::request::{
    Message, RequestBody, RequestTool, Thinking, ThinkingType,
};
use openai_interface::chat::create::response::no_streaming::ChatCompletion;
use openai_interface::rest::post::PostNoStream;
use openai_interface::rest::{RequestOptions, default_client};
use openai_interface::zai::{PlatformParams, SearchEngine, WebSearchTool};

/// GLM's OpenAI-compatible base URL. Note the `/api/paas/v4` suffix, which
/// replaces the `/v1` most providers use.
const GLM_BASE_URL: &str = "https://open.bigmodel.cn/api/paas/v4";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Needs the `ferritls` cargo feature; drop this line if you install
    // your own rustls crypto provider.
    #[cfg(feature = "ferritls")]
    openai_interface::rest::install_crypto_provider().ok();

    let api_key = std::env::var("ZAI_API_KEY")?;

    let request = RequestBody {
        messages: vec![
            Message::system("你是一个有用的AI助手。"),
            Message::user("最近有什么关于 Rust 的新闻?"),
        ],
        model: "glm-4.6".to_string(),
        stream: Some(false),
        // GLM-specific generic controls:
        do_sample: Some(true),
        thinking: Some(Thinking {
            type_: ThinkingType::Enabled,
            clear_thinking: Some(true),
        }),
        // GLM platform-ecosystem parameters, flattened into the body:
        zai_platform: Some(PlatformParams {
            watermark_enabled: Some(true),
        }),
        // GLM's `web_search` tool type:
        tools: Some(vec![RequestTool::WebSearch {
            web_search: WebSearchTool {
                search_engine: Some(SearchEngine::SearchProJina),
                enable: Some(true),
                ..Default::default()
            },
        }]),
        ..Default::default()
    };

    let options = RequestOptions::bearer(api_key);
    let completion: ChatCompletion = request
        .get_response(&default_client(), GLM_BASE_URL, &options)
        .await?;

    println!(
        "{}",
        completion.choices[0]
            .message
            .content
            .as_deref()
            .unwrap_or("(no content)")
    );

    // GLM returns the search results behind the answer at the top level.
    if let Some(results) = &completion.web_search {
        println!("\n--- web_search results ---");
        for result in results {
            println!(
                "{} {}",
                result.refer.as_deref().unwrap_or(""),
                result.link.as_deref().unwrap_or("")
            );
        }
    }
    Ok(())
}