samvadsetu | संवाद-सेतु
A Rust-native library for sending chat-completion requests to multiple LLM providers through a single, unified API.
Sanskrit: saṃvāda (संवाद) = dialogue · setu (सेतु) = bridge.
Supported Providers
| Provider | llm_service string |
Auth env var | Batch API |
|---|---|---|---|
| OpenAI / ChatGPT | "chatgpt" / "openai" |
OPENAI_API_KEY |
✓ |
| DeepSeek | "deepseek" |
DEEPSEEK_API_KEY |
✓ |
| Alibaba Qwen (DashScope) | "qwen" |
DASHSCOPE_API_KEY |
✓ |
| llama.cpp server | "llamacpp" |
LLAMACPP_API_KEY (opt.) |
— |
| Anthropic Claude | "claude" / "anthropic" |
ANTHROPIC_API_KEY |
✓ |
| Google Gemini (legacy) | "gemini" |
GOOGLE_API_KEY |
— |
| Google GenAI | "google_genai" |
GOOGLE_API_KEY |
— |
| Ollama (local) | "ollama" |
(none) | — |
Installation
[]
= "0.2"
Optional async support (future):
= { = "0.2", = ["async"] }
Quick Start
use LLMTextGenBuilder;
use ChatMessage;
Set the API key in your environment before running:
Core Types
ChatMessage — Building conversations
use ChatMessage;
// Convenience constructors:
let msg = system;
let msg = user;
let msg = assistant;
// Returning a tool result to the model:
let msg = tool_result;
// Building an assistant message that made tool calls:
use ToolCall;
use json;
let msg = assistant_with_tool_calls;
LlmApiResult — What you get back
use LlmApiResult;
let result: LlmApiResult = /* ... */;
println!;
println!;
println!;
println!;
println!;
// Tool calls the model wants to make:
for tc in &result.tool_calls
// Chain-of-thought (DeepSeek R1, Ollama `think`, Claude with thinking):
if let Some = &result.reasoning_content
Feature: Token Log-Probabilities (Hallucination Proxy)
Token log-probabilities are returned by OpenAI-family models (ChatGPT, DeepSeek, Qwen, llama.cpp) and newer Gemini models. Claude does not support logprobs.
use LLMTextGenBuilder;
use ChatMessage;
let llm_gen = build.unwrap;
let messages = vec!;
let result = llm_gen.generate_text.unwrap;
// Aggregate confidence metrics:
if let Some = result.mean_probability
if let Some = result.min_token_probability
// Per-token breakdown:
for lp in &result.logprobs
Rule of thumb:
mean_probability> 0.9 generally indicates high-confidence generation; values < 0.7 warrant extra scrutiny.
Feature: Tool Calling / Function Calling
use LLMTextGenBuilder;
use ;
use json;
let llm_gen = build.unwrap;
let tools = vec!;
let mut messages = vec!;
// First turn: model requests a tool call
let r1 = llm_gen.generate_text.unwrap;
for tc in &r1.tool_calls
// Second turn: model uses the tool result to answer
let r2 = llm_gen.generate_text.unwrap;
println!;
Feature: Structured Output / JSON Mode
use ResponseFormat;
use json;
// JSON Object mode (model must output valid JSON; you define the shape in the prompt)
let result = llm_gen.generate_text.unwrap;
// JSON Schema mode (model output is constrained to match your schema)
let schema = json!;
let fmt = JsonSchema ;
let result = llm_gen.generate_text.unwrap;
let parsed: Value = from_str.unwrap;
JSON Schema mode is fully supported by OpenAI (structured outputs), llama.cpp, and Ollama. DeepSeek and Qwen support JSON object mode. Gemini supports both via
response_mime_typeandresponse_schema.
Feature: Batch Processing
Batch APIs let you submit hundreds or thousands of requests at lower cost and process the results asynchronously (OpenAI: up to 50 % cost reduction; Anthropic: 50 %).
use LLMTextGenBuilder;
use ;
use Duration;
let llm_gen = build.unwrap;
let requests = vec!;
// Submit
let mut handle = llm_gen.submit_batch.unwrap;
println!;
// Poll until complete
loop
// Retrieve results
if handle.status == Completed
Configuration via TOML File
# app_config.toml
[]
= "gpt-4o-mini"
= "https://api.openai.com/v1/chat/completions"
= 0.0
= 8192
= 16384
= 120
= "You are a helpful assistant."
[]
= "claude-haiku-4-5"
= "https://api.anthropic.com/v1/messages"
= 0.0
= 4096
= 120
[]
= "llama3.2"
= "http://localhost:11434/api/chat"
= 0.0
= 4096
= 8192
= 0
use ;
use LLMTextGenBuilder;
use ChatMessage;
let app_config = builder
.add_source
.build
.expect;
let llm_gen = build_from_config
.expect;
let messages = vec!;
let result = llm_gen.generate_text.unwrap;
println!;
Multi-Turn Conversation
The library is stateless — callers own the message history:
let mut history: = vec!;
loop
Using Different Providers
use LLMTextGenBuilder;
use ChatMessage;
// DeepSeek (OpenAI-compatible)
let llm_gen = build.unwrap;
// Qwen (DashScope, Singapore region by default; override api_url for other regions)
let llm_gen = build.unwrap;
// Anthropic Claude (no logprobs available)
let llm_gen = build.unwrap;
// Local llama.cpp server
let mut llm_gen = build.unwrap;
llm_gen.svc_base_url = "http://192.168.1.100:8080/v1/chat/completions".to_string;
// Local Ollama
let mut llm_gen = build.unwrap;
llm_gen.svc_base_url = "http://10.13.31.113:11434/api/chat".to_string;
Rate Limiting (Multi-threaded)
use ;
use LLMTextGenBuilder;
// Share a mutex across threads; calls will be spaced at least 6 seconds apart.
let rate_limit_mutex = new;
let llm_gen = build.unwrap;
Error Handling
All errors return SamvadSetuError:
use SamvadSetuError;
match llm_gen.generate_text
Provider Capability Matrix
| Feature | ChatGPT | DeepSeek | Qwen | Claude | Gemini | Ollama | llama.cpp |
|---|---|---|---|---|---|---|---|
| Chat completions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Tool calling | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Token logprobs | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ |
| JSON object mode | ✓ | ✓ | ✓ | — | ✓ | ✓ | ✓ |
| JSON schema | ✓ | — | — | — | ✓ | ✓ | ✓ |
| Batch API | ✓ | ✓ | ✓ | ✓ | — | — | — |
| Chain-of-thought | — | ✓ | — | ✓ | — | ✓ | — |
Claude does not return logprobs via its API —
result.logprobswill be empty andresult.mean_probability()will returnNone.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
See CONTRIBUTING.md.