8 个版本
新 0.3.2 | 2024 年 8 月 14 日 |
---|---|
0.3.0 | 2024 年 8 月 13 日 |
0.2.3 | 2024 年 6 月 30 日 |
0.2.2 | 2024 年 2 月 28 日 |
0.1.1 | 2023 年 12 月 21 日 |
#297 在 机器学习 分类中
每月 175 次下载
在 kalosm 中使用
670KB
15K SLoC
Kalosm 语言
Kalosm 框架的语言处理工具。
Kalosm 的语言部分包含几个核心部分
- 模型:文本生成和嵌入模型
- 上下文:文档集合、格式支持、搜索和分块
- 集成:SurrealDB、Serper 和其他集成
文本生成模型
Model
和 ModelExt
是文本生成模型的核心理念。任何实现了这些理念的模型都可以与 Kalosm 一起使用。
使用模型的最简单方法是创建一个 llama 模型 并在它上面调用 stream_text
use kalosm::language::*;
#[tokio::main]
async fn main() {
let mut llm = Llama::new().await.unwrap();
let prompt = "The following is a 300 word essay about why the capital of France is Paris:";
print!("{prompt}");
let mut stream = llm
// Any model that implements the Model trait can be used to stream text
.stream_text(prompt)
// You can pass parameters to the model to control the output
.with_max_length(300)
// And run .await to start streaming
.await
.unwrap();
// You can then use the stream however you need. to_std_out will print the text to the console as it is generated
stream.to_std_out().await.unwrap();
}
任务
您可以定义一个带有描述的任务,然后使用输入运行它。任务将缓存描述以加快重复调用。任务与聊天和非聊天模型都兼容,但它们通常与聊天模型表现更好。
use kalosm::language::*;
#[tokio::main]
async fn main() {
// Create a new model
let model = Llama::new_chat().await.unwrap();
// Create a new task that summarizes text
let task = Task::new("You take a long description and summarize it into a single short sentence");
let mut output = task.run("You can define a Task with a description then run it with an input. The task will cache the description to repeated calls faster. Tasks work with both chat and non-chat models, but they tend to perform significantly better with chat models.", &model);
// Then stream the output to the console
output.to_std_out().await.unwrap();
}
结构化生成
结构化生成允许您更好地控制文本生成的输出。您可以为您的数据推导出一个解析器,以便轻松地从 LLM 获取结构化数据
use kalosm::language::*;
#[derive(Parse, Clone)]
struct Pet {
name: String,
age: u32,
description: String,
}
然后您可以在 Task
中使用解析器生成文本
use kalosm::language::*;
#[derive(Parse, Debug, Clone)]
struct Pet {
name: String,
age: u32,
description: String,
}
#[tokio::main]
async fn main() {
// First create a model. Chat models tend to work best with structured generation
let model = Llama::new_chat().await.unwrap();
// Then create a parser for your data. Any type that implements the `Parse` trait has the `new_parser` method
let parser = Pet::new_parser();
// Then create a task with the parser as constraints
let task = Task::builder("You generate realistic JSON placeholders")
.with_constraints(parser)
.build();
// Finally, run the task
let pet: Pet = task.run("Generate a pet in the form {\"name\": \"Pet name\", \"age\": 0, \"description\": \"Pet description\"}", &model).await.unwrap();
println!("{pet:?}");
}
嵌入模型
Embedder
和 EmbedderExt
是文本嵌入模型的核心理念。任何实现了这些理念的模型都可以与 Kalosm 一起使用。
使用嵌入模型的最简单方法是创建一个 BERT 模型 并对其调用 embed
。返回的 Embedding
以数值形式表示文本的含义。
use kalosm::language::*;
#[tokio::main]
async fn main() {
// First create a model. Bert::new() is a good default embedding model for general tasks
let model = Bert::new().await.unwrap();
// Then embed some text into the vector space
let embedding = model.embed("Kalosm is a library for building AI applications").await.unwrap();
// And some more text
let embedding = model.embed(prompt_input("Text: ").unwrap()).await.unwrap();
// You can compare the cosine similarity of the two embeddings to see how similar they are
println!("cosine similarity: {}", embedding.cosine_similarity(&embedding));
}
上下文
收集上下文是构建大型语言模型 (LLM) 应用程序的关键部分。向模型提供正确的上下文可以使输出更加相关和有用。它还可以帮助防止幻觉。
Kalosm 提供了从各种来源生成、收集和处理上下文的工具。
收集上下文
Kalosm 提供了从各种来源收集上下文的实用工具
- 本地文件 (.txt, .md, .html, .docx, .pdf)
- RSS 流
- 网站
- 搜索引擎
- 通过 Whisper 转写 的麦克风输入和音频输入
这些来源中的每一个都实现了 IntoDocument
或 IntoDocuments
,以将数据转换为包含文档内容和元数据的 Document
。
use kalosm::language::*;
use std::convert::TryFrom;
use std::path::PathBuf;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Try to extract an article from a URL
let page = Url::parse("https://www.nytimes.com/live/2023/09/21/world/zelensky-russia-ukraine-news")?;
let document = page.into_document().await?;
println!("Title: {}", document.title());
println!("Body: {}", document.body());
Ok(())
}
上下文分块
收集上下文后,通常将其分成更小的部分以进行搜索很有用。Kalosm 提供了将上下文分块为文档、句子、段落或语义块的工具。Kalosm 在分割文档为更小部分时会嵌入每个块。最强大的分块器之一是语义分块器,它允许您将文档分块为语义上相似的块,而无需显式设置块的大小。
use kalosm::language::*;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// First, create an embedding model for semantic chunking
let model = Bert::new().await?;
// Then create a document folder with some documents
let documents = DocumentFolder::new("./documents")?.into_documents().await?;
// Then chunk the documents into sentences
let chunked = SemanticChunker::new().chunk_batch(&documents, &model).await?;
println!("{:?}", chunked);
Ok(())
}
嵌入式搜索
将上下文分块后,您可以使用嵌入进行搜索或检索增强生成。基于嵌入的搜索允许您找到与特定单词或短语语义上相似的文档,即使没有任何单词完全匹配。
use kalosm::language::*;
use surrealdb::{engine::local::RocksDb, Surreal};
#[tokio::main]
async fn main() {
// Create database connection
let db = Surreal::new::<RocksDb>(std::env::temp_dir().join("temp.db")).await.unwrap();
// Select a specific namespace / database
db.use_ns("search").use_db("documents").await.unwrap();
// Create a table in the surreal database to store the embeddings
let document_table = db
.document_table_builder("documents")
.build::<Document>()
.await
.unwrap();
// Add documents to the database
document_table.add_context(DocumentFolder::new("./documents").unwrap()).await.unwrap();
loop {
// Get the user's question
let user_question = prompt_input("Query: ").unwrap();
let nearest_5 = document_table
.select_nearest(user_question, 5)
.await
.unwrap();
println!("{:?}", nearest_5);
}
}
依赖关系
~50–73MB
~1.5M SLoC