12 个版本
0.1.15 | 2024 年 4 月 21 日 |
---|---|
0.1.14 | 2024 年 4 月 18 日 |
#1420 在 网络编程
每月 696 次下载
在 hiramu-cli 中使用
1.5MB
2.5K SLoC
Hiramu
Hiramu 是一个强大而灵活的 Rust 库,提供了与各种 AI 模型和 API(包括 Ollama 和 AWS Bedrock)交互的高级接口。
它简化了生成文本、参与聊天对话以及与不同 AI 模型协同工作的过程。
特性
- 用于生成文本和与 AI 模型进行聊天对话的简单易用的接口
- 支持 Ollama 和 Bedrock AI 服务
- 方便的 Claude 和 Mistral 接口,用于 AWS Bedrock
- 异步和流式响应,以高效处理大量输出
- 可定制的选项,以微调 AI 模型的行为
- 全面的错误处理和详尽的信息性错误消息
- 带有示例和解释的良好文档化的代码
入门指南
要开始在您的 Rust 项目中使用 Hiramu,请将以下内容添加到您的 Cargo.toml
文件中
[dependencies]
hiramu = "0.1.15"
示例
Mistral 生成文本
use hiramu::bedrock::model_info::{ModelInfo, ModelName};
use hiramu::bedrock::models::mistral::mistral_client::{MistralClient, MistralOptions};
use hiramu::bedrock::models::mistral::mistral_request_message::MistralRequestBuilder;
async fn generating_text_with_mistral() {
let mistral_options = MistralOptions::new()
.profile_name("bedrock")
.region("us-west-2");
let client = MistralClient::new(mistral_options).await;
let request =
MistralRequestBuilder::new("<s>[INST] What is the capital of France?[/INST]".to_string())
.max_tokens(200)
.temperature(0.8)
.build();
let model_id = ModelInfo::from_model_name(ModelName::MistralMixtral8X7BInstruct0x);
let response = client.generate(model_id, &request).await.unwrap();
println!("Response: {:?}", response.outputs[0].text);
}
Mistral 流式文本生成
use futures::stream::StreamExt;
use hiramu::bedrock::models::mistral::mistral_client::{MistralClient, MistralOptions};
use hiramu::bedrock::models::mistral::mistral_request_message::MistralRequestBuilder;
use hiramu::bedrock::model_info::{ModelInfo, ModelName};
pub async fn generating_text_with_mistral() {
let mistral_options = MistralOptions::new()
.profile_name("bedrock")
.region("us-west-2");
let client = MistralClient::new(mistral_options).await;
let request = MistralRequestBuilder::new("<s>[INST] What is the capital of France?[/INST]".to_string())
.max_tokens(200)
.temperature(0.8)
.build();
let model_id = ModelInfo::from_model_name(ModelName::MistralMixtral8X7BInstruct0x);
let mut stream = client.generate_with_stream(model_id, &request).await.unwrap();
while let Some(result) = stream.next().await {
match result {
Ok(response) => {
println!("Response: {:?}", response.outputs[0].text);
}
Err(err) => {
eprintln!("Error: {:?}", err);
}
}
}
}
Ollama 生成文本
use std::io::Write;
use futures::TryStreamExt;
use hiramu::ollama::ollama_client::OllamaClient;
use hiramu::ollama::model::{GenerateRequestBuilder};
async fn generating_text_with_ollama() {
let client = OllamaClient::new("https://127.0.0.1:11434".to_string());
let request = GenerateRequestBuilder::new("mistral".to_string())
.prompt("Once upon a time".to_string())
.build();
let response_stream = client.generate(request).await.unwrap();
response_stream
.try_for_each(|chunk| async move {
print!("{}", chunk.response);
std::io::stdout().flush()?;
Ok(())
})
.await
.unwrap();
}
与 Ollama 聊天
use futures::TryStreamExt;
use std::io::{self, Write};
use hiramu::ollama::{ChatRequestBuilder, Message, OllamaClient, OllamaError, OptionsBuilder};
async fn demo_chat_with_ollama_with_stream() -> Result<(), OllamaError> {
let client = OllamaClient::new("https://127.0.0.1:11434".to_string());
let messages = vec![Message::new(
"user".to_string(),
"What is the capital of France? "
.to_string(),
)];
let options = OptionsBuilder::new()
.num_predict(100) // Limit the number of predicted tokens
.temperature(0.4);
let request = ChatRequestBuilder::new("mistral".to_string())
.messages(messages.to_owned())
.options_from_builder(options)
.build();
let response_stream = client.chat(request).await?;
let result = response_stream
.try_for_each(|chunk| async {
let message = chunk.message;
print!("{}", message.content);
// Flush the output to ensure the prompt is displayed.
io::stdout().flush().unwrap();
Ok(())
})
.await;
result
}
使用 Bedrock 与 Claude 聊天
use std::io::Write;
use futures::TryStreamExt;
use hiramu::bedrock::model_info::{ModelInfo, ModelName};
use hiramu::bedrock::models::claude::claude_client::{ClaudeClient, ClaudeOptions};
use hiramu::bedrock::models::claude::claude_request_message::{
ChatOptions, ContentBlockDelta, ConversationRequest, Message, StreamResultData,
};
pub async fn chat_with_claude() {
let claude_options = ClaudeOptions::new()
.profile_name("bedrock")
.region("us-west-2");
let client = ClaudeClient::new(claude_options).await;
let mut conversation_request = ConversationRequest::default();
conversation_request
.messages
.push(Message::new_user_message("Hello, Claude!".to_owned()));
let chat_options = ChatOptions::default()
.with_temperature(0.7)
.with_max_tokens(100)
.with_model_id(ModelInfo::from_model_name(
ModelName::AnthropicClaudeHaiku1x,
));
let response_stream = client
.chat_with_stream(&conversation_request, &chat_options)
.await
.unwrap();
response_stream
.try_for_each(|chunk| async move {
match chunk {
StreamResultData::ContentBlockStart(..) => {
println!("\n------------------------------");
}
StreamResultData::ContentBlockStop(..) => {
println!("\n------------------------------");
}
StreamResultData::ContentBlockDelta(ContentBlockDelta { delta, .. }) => {
print!("{}", delta.text);
std::io::stdout().flush().unwrap();
}
_ => {}
}
Ok(())
})
.await
.unwrap();
}
Claude 与图像协同工作
use std::io::Write;
use futures::TryStreamExt;
use hiramu::bedrock::models::claude::claude_client::{ClaudeClient, ClaudeOptions};
use hiramu::bedrock::models::claude::claude_request_message::{ChatOptions, ContentBlockDelta, ConversationRequest, Message, StreamResultData};
use hiramu::fetch_and_base64_encode_image;
async fn image_with_claude() {
let claude_options = ClaudeOptions::new()
.profile_name("bedrock")
.region("us-west-2");
let client = ClaudeClient::new(claude_options).await;
let image_url = "./data/mario.png";
let input_text = "What's in this image?".to_string();
let image = fetch_and_base64_encode_image(image_url).await.unwrap().to_string();
let mime_type = "image/png".to_string();
let message = Message::new_user_message_with_image(&input_text, &image, &mime_type);
let mut conversation_request = ConversationRequest::default();
conversation_request.messages.push(message);
let chat_options = ChatOptions::default()
.with_temperature(0.7)
.with_max_tokens(100);
let response_stream = client
.chat_with_stream(&conversation_request, &chat_options)
.await
.unwrap();
response_stream
.try_for_each(|chunk| async move {
match chunk {
StreamResultData::ContentBlockStart(..) => {
println!("\n------------------------------");
}
StreamResultData::ContentBlockStop(..) => {
println!("\n------------------------------");
}
StreamResultData::ContentBlockDelta(ContentBlockDelta { delta, .. }) => {
print!("{}", delta.text);
std::io::stdout().flush().unwrap();
}
_ => {}
}
Ok(())
})
.await
.unwrap();
}
使用原始 Bedrock API
生成原始响应
use hiramu::bedrock::bedrock_client::{BedrockClient, BedrockClientOptions};
use hiramu::bedrock::model_info::{ModelInfo, ModelName};
#[tokio::main]
async fn main() {
let model_id = ModelInfo::from_model_name(ModelName::AnthropicClaudeHaiku1x);
let profile_name = "bedrock";
let region = "us-west-2";
let prompt = "Hi. In a short paragraph, explain what you can do.";
let payload = serde_json::json!({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages": [{
"role": "user",
"content": [{
"type": "text",
"text": prompt
}]
}]
});
let options = BedrockClientOptions::new()
.profile_name(profile_name)
.region(region);
let client = BedrockClient::new(options).await;
let result = client
.generate_raw(model_id.to_string(), payload)
.await
.unwrap();
println!("{:?}", result);
}
生成原始流响应
use futures::TryStreamExt;
use hiramu::bedrock::bedrock_client::{BedrockClient, BedrockClientOptions};
use hiramu::bedrock::model_info::{ModelInfo, ModelName};
#[tokio::main]
async fn main() {
let model_id = ModelInfo::from_model_name(ModelName::AnthropicClaudeHaiku1x);
let profile_name = "bedrock";
let region = "us-west-2";
let prompt = "Hi. In a short paragraph, explain what you can do.";
let payload = serde_json::json!({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 1000,
"messages": [{
"role": "user",
"content": [{
"type": "text",
"text": prompt
}]
}]
});
let options = BedrockClientOptions::new()
.profile_name(profile_name)
.region(region);
let client = BedrockClient::new(options).await;
let stream = client
.generate_raw_stream(model_id.to_string(), payload)
.await
.unwrap();
stream
.try_for_each(|chunk| async move {
println!("{:?}", chunk);
Ok(())
})
.await
.unwrap();
}
使用 Ollama 的嵌入
use hiramu::ollama::{EmbeddingsRequestBuilder, OllamaClient};
pub async fn demo_ollama_embedding() -> Result<(), Box<dyn std::error::Error>> {
let client = OllamaClient::new("https://127.0.0.1:11434".to_string());
let prompt = "The quick brown fox jumps over the lazy dog.";
let request = EmbeddingsRequestBuilder::new("nomic-embed-text".to_string(), prompt.to_string())
.keep_alive("10m".to_string())
.build();
match client.embeddings(request).await {
Ok(response) => {
// Print embeddings dimensions
println!("Embeddings dimensions: {:?}", response.embedding.len());
println!("Embeddings: {:?}", response);
}
Err(error) => {
eprintln!("Error: {:?}", error);
}
}
Ok(())
}
示例
以下是每个示例的描述表
示例 | 路径 | 描述 |
---|---|---|
demo_ollama |
src/examples/demo_ollama.rs | 一个简单的示例,演示了如何使用 Ollama API 生成响应。 |
demo_chat_with_ollama |
src/examples/demo_chat_with_ollama.rs | 一个简单的示例,演示了如何使用 Ollama 聊天 API。 |
demo_bedrock_raw_generate |
src/examples/demo_bedrock_raw_generate.rs | 演示了如何使用 generate_raw 方法从 Bedrock 服务生成原始响应。 |
demo_bedrock_raw_stream |
src/examples/demo_bedrock_raw_stream.rs | 演示了如何使用 generate_raw_stream 方法从 Bedrock 服务生成原始响应流。 |
demo_bedrock_raw_mistral |
src/examples/demo_bedrock_raw_mistral.rs | 演示了如何在Bedrock服务中从Mistral模型生成原始响应流。 |
demo_claude_chat |
src/examples/demo_claude_chat.rs | 演示了如何在Bedrock服务中使用Claude模型生成聊天响应。 |
demo_claude_chat_stream |
src/examples/demo_claude_chat_stream.rs | 演示了如何在Bedrock服务中使用Claude模型生成聊天响应流。 |
demo_claude_multimedia |
src/examples/demo_claude_multimedia.rs | 演示了如何在Bedrock服务中使用Claude模型根据文本和图像生成响应。 |
demo_ollama_embedding |
src/examples/demo_ollama_embedding.rs | 演示了如何使用Ollama API生成文本嵌入。 |
demo_mistral_stream |
src/examples/demo_mistral_stream.rs | 演示了如何在Bedrock服务中使用Mistral模型生成响应流。 |
贡献
欢迎为Hiramu做出贡献!如果您遇到任何问题,有改进建议或想添加新功能,请在GitHub仓库上创建问题或提交pull请求。
要为项目做出贡献,请按照以下步骤操作
- 将仓库Fork并为您所做的更改创建一个新的分支。
- 进行修改并确保代码成功编译。
- 编写测试以覆盖您的更改并确保所有现有测试都通过。
- 如有必要,更新文档,包括README和API文档。
- 提交一个包含更改描述和解决问题的pull请求。
许可证
Hiramu使用MIT许可证。
致谢
Hiramu构建在以下库和API之上
我们想对以下项目的开发者和维护者表示衷心的感谢,他们为Rust生态系统做出了卓越的工作和贡献。
依赖项
~19–34MB
~498K SLoC