Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

llm - Unified LLM Interface Crate

llm là một Rust crate cung cấp unified interface để làm việc với nhiều Large Language Model providers khác nhau. Crate này giúp đơn giản hóa việc integrate multiple LLM services vào application của bạn.

Đặc điểm chính

1. Multiple Provider Support

llm crate hỗ trợ rất nhiều providers thông qua một API nhất quán:

Supported Providers:

  • OpenAI (GPT-4, GPT-3.5, etc.)
  • Anthropic (Claude 3.5 Sonnet, Claude 3 Opus, etc.)
  • Ollama (Local models)
  • DeepSeek
  • xAI (Grok)
  • Phind
  • Groq
  • Google (Gemini)
  • Cohere
  • Mistral
  • ElevenLabs

2. Builder Pattern API

Sử dụng builder pattern để cấu hình requests một cách rõ ràng và type-safe:

use llm::{
    client::Client,
    provider::openai::OpenAI,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Khởi tạo client
    let client = Client::builder()
        .provider(OpenAI::new(env::var("OPENAI_API_KEY")?))
        .build()?;

    // Tạo completion request
    let response = client
        .completion()
        .model("gpt-4")
        .prompt("Explain Rust ownership in simple terms")
        .temperature(0.7)
        .max_tokens(500)
        .send()
        .await?;

    println!("{}", response.text());

    Ok(())
}

3. Request Validation

llm crate tự động validate requests trước khi gửi, giúp catch errors sớm:

use llm::client::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::from_env()?;

    // Validation sẽ kiểm tra:
    // - Model name có valid không
    // - Temperature trong range [0, 2]
    // - Max tokens không vượt quá giới hạn
    let response = client
        .completion()
        .model("gpt-4")
        .temperature(0.7)  // OK
        // .temperature(3.0)  // ❌ Sẽ error: temperature must be between 0 and 2
        .max_tokens(100)
        .prompt("Hello, world!")
        .send()
        .await?;

    Ok(())
}

4. Retry Logic với Exponential Backoff

Built-in retry mechanism với exponential backoff và jitter cho resilience:

use llm::client::Client;
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::builder()
        .retry_config(
            llm::retry::RetryConfig::default()
                .max_retries(3)
                .initial_delay(Duration::from_millis(500))
                .max_delay(Duration::from_secs(10))
                .use_jitter(true)
        )
        .build()?;

    // Tự động retry nếu có network errors hoặc rate limits
    let response = client
        .completion()
        .model("gpt-4")
        .prompt("Hello!")
        .send()
        .await?;

    Ok(())
}

Use Cases

1. Multi-Provider Support

Dễ dàng switch giữa các providers:

#![allow(unused)]
fn main() {
use llm::{
    client::Client,
    provider::{openai::OpenAI, anthropic::Anthropic},
};

async fn compare_models() -> Result<(), Box<dyn std::error::Error>> {
    let prompt = "What is Rust's ownership system?";

    // OpenAI GPT-4
    let openai_client = Client::builder()
        .provider(OpenAI::from_env()?)
        .build()?;

    let gpt4_response = openai_client
        .completion()
        .model("gpt-4")
        .prompt(prompt)
        .send()
        .await?;

    println!("GPT-4: {}\n", gpt4_response.text());

    // Anthropic Claude
    let anthropic_client = Client::builder()
        .provider(Anthropic::from_env()?)
        .build()?;

    let claude_response = anthropic_client
        .completion()
        .model("claude-3-5-sonnet-20241022")
        .prompt(prompt)
        .send()
        .await?;

    println!("Claude: {}\n", claude_response.text());

    Ok(())
}
}

2. Streaming Responses

Hỗ trợ streaming cho real-time output:

use llm::client::Client;
use futures_util::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::from_env()?;

    let mut stream = client
        .completion()
        .model("gpt-4")
        .prompt("Write a haiku about Rust programming")
        .stream()
        .await?;

    print!("Response: ");
    while let Some(chunk) = stream.next().await {
        let chunk = chunk?;
        print!("{}", chunk.text());
        std::io::Write::flush(&mut std::io::stdout())?;
    }
    println!();

    Ok(())
}

3. Function Calling

Sử dụng function calling để LLM có thể invoke tools:

use llm::{client::Client, function::Function};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::from_env()?;

    // Define function
    let weather_function = Function::builder()
        .name("get_weather")
        .description("Get the current weather for a location")
        .parameter("location", "string", "The city name")
        .build();

    let response = client
        .completion()
        .model("gpt-4")
        .prompt("What's the weather in Hanoi?")
        .function(weather_function)
        .send()
        .await?;

    if let Some(function_call) = response.function_call() {
        println!("Function: {}", function_call.name);
        println!("Arguments: {}", function_call.arguments);

        // Execute function
        match function_call.name.as_str() {
            "get_weather" => {
                let args: serde_json::Value =
                    serde_json::from_str(&function_call.arguments)?;
                println!("Getting weather for: {}", args["location"]);
            }
            _ => {}
        }
    }

    Ok(())
}

4. Evaluation & Scoring

Built-in capabilities để evaluate LLM outputs:

use llm::{client::Client, evaluation::Evaluator};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::from_env()?;

    let response = client
        .completion()
        .model("gpt-4")
        .prompt("Explain memory safety")
        .send()
        .await?;

    // Evaluate response quality
    let evaluator = Evaluator::new(&client);

    let relevance_score = evaluator
        .score_relevance("Explain memory safety", response.text())
        .await?;

    println!("Relevance score: {}/10", relevance_score);

    Ok(())
}

5. Serving as REST API

Serve bất kỳ LLM backend nào như một REST API với OpenAI-compatible format:

use llm::server::Server;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Start server on port 8080
    let server = Server::builder()
        .port(8080)
        .provider(/* your provider */)
        .build()?;

    println!("Server running on http://localhost:8080");

    // Clients có thể gọi như OpenAI API:
    // POST http://localhost:8080/v1/chat/completions

    server.run().await?;

    Ok(())
}

Configuration

Environment Variables

# OpenAI
export OPENAI_API_KEY="sk-..."

# Anthropic
export ANTHROPIC_API_KEY="sk-ant-..."

# Groq
export GROQ_API_KEY="gsk_..."

# Local Ollama
export OLLAMA_HOST="http://localhost:11434"

Cargo.toml

[dependencies]
llm = "0.5.0"
tokio = { version = "1.0", features = ["full"] }
futures-util = "0.3"
serde_json = "1.0"

Ưu điểm

Unified Interface: Một API cho tất cả providers ✅ Type Safety: Rust's type system bảo vệ bạn khỏi errors ✅ Resilience: Built-in retry và error handling ✅ Validation: Request validation trước khi gửi ✅ Flexibility: Dễ dàng switch providers ✅ Production Ready: Được thiết kế cho production use

Nhược điểm

⚠️ Abstraction Overhead: Có thể không expose tất cả provider-specific features ⚠️ Learning Curve: Cần học builder pattern API ⚠️ Dependencies: Thêm dependencies vào project

Khi nào nên dùng?

Nên dùng llm crate khi:

  • Muốn support multiple LLM providers
  • Cần unified interface để dễ switch providers
  • Muốn built-in retry và validation
  • Xây dựng production systems cần resilience

Có thể dùng provider SDK trực tiếp khi:

  • Chỉ dùng một provider duy nhất
  • Cần access provider-specific features
  • Muốn minimize dependencies

Resources

Kết luận

llm crate là một excellent choice khi bạn cần làm việc với multiple LLM providers trong Rust. Với unified API, built-in resilience, và type safety, nó giúp xây dựng robust LLM applications một cách nhanh chóng và an toàn.