Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix proc macro, simplify, refactor #9

Merged
merged 3 commits into from
Jul 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 46 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ orch = "*" # Substitute with the latest version

## Simple Text Generation

```rust
```rust no_run
use orch::execution::*;
use orch::lm::*;

Expand All @@ -42,7 +42,7 @@ async fn main() {

## Streaming Text Generation

```rust
```rust no_run
use orch::execution::*;
use orch::lm::*;
use tokio_stream::StreamExt;
Expand All @@ -67,54 +67,74 @@ async fn main() {

## Structured Data Generation

```rust
```rust no_run
use orch::execution::*;
use orch::lm::*;
use orch_response_derive::*;
use orch::response::*;

#[derive(OrchResponseOptions)]
pub enum CapitalCityExecutorResponseOptions {
#[response(
scenario = "You know the capital city of the country",
description = "Capital city of the country"
)]
#[derive(Variants, serde::Deserialize)]
pub enum ResponseVariants {
Answer(AnswerResponseVariant),
Fail(FailResponseVariant),
}

#[derive(Variant, serde::Deserialize)]
#[variant(
variant = "Answer",
scenario = "You know the capital city of the country",
description = "Capital city of the country"
)]
pub struct AnswerResponseVariant {
#[schema(
field = "capital",
description = "Capital city of the received country",
example = "London"
)]
Answer { capital: String },
#[response(
scenario = "You don't know the capital city of the country",
description = "Reason why the capital city is not known"
)]
pub capital: String,
}

#[derive(Variant, serde::Deserialize)]
#[variant(
variant = "Fail",
scenario = "You don't know the capital city of the country",
description = "Reason why the capital city is not known"
)]
pub struct FailResponseVariant {
#[schema(
field = "reason",
description = "Reason why the capital city is not known",
example = "Country 'foobar' does not exist"
)]
Fail { reason: String },
pub reason: String,
}

#[tokio::main]
async fn main() {
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = StructuredExecutorBuilder::new()
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = StructuredExecutorBuilder::new()
.with_lm(&lm)
.with_preamble("You are a geography expert who helps users understand the capital city of countries around the world.")
.with_options(&options!(CapitalCityExecutorResponseOptions))
.with_options(&variants!(ResponseVariants))
.try_build()
.unwrap();
let response = executor.execute("What is the capital of Fooland?").await.expect("Execution failed");

println!("Response:");
println!("{:?}", response.content);
let response = executor
.execute("What is the capital of Fooland?")
.await
.expect("Execution failed");

println!("Response:");
match response.content {
ResponseVariants::Answer(answer) => {
println!("Capital city: {}", answer.capital);
}
ResponseVariants::Fail(fail) => {
println!("Model failed to generate a response: {}", fail.reason);
}
}
}
```

## Embedding Generation

```rust
```rust no_run
use orch::execution::*;
use orch::lm::*;

Expand All @@ -138,7 +158,3 @@ async fn main() {
## More Examples

See the [examples](https://github.com/guywaldman/orch/tree/main/core/examples) directory for usage examples.

## Roadmap

- [ ] Agents and tools
6 changes: 3 additions & 3 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "orch"
version = "0.0.11"
version = "0.0.12"
edition = "2021"
license = "MIT"
description = "Language model orchestration library"
Expand All @@ -9,8 +9,8 @@ repository = "https://github.com/guywaldman/orch"
keywords = ["llm", "openai", "ollama", "rust"]

[dependencies]
orch_response = { path = "../response", version = "0.0.11" }
orch_response_derive = { path = "../response_derive", version = "0.0.11" }
orch_response = { path = "../response", version = "0.0.12" }
orch_response_derive = { path = "../response_derive", version = "0.0.12" }
async-gen = "0.2.3"
dotenv = "0.15.0"
dyn-clone = "1.0.17"
Expand Down
143 changes: 1 addition & 142 deletions core/README.md
Original file line number Diff line number Diff line change
@@ -1,144 +1,3 @@
# orch

![Crates.io Version](https://img.shields.io/crates/v/orch?link=https%3A%2F%2Fcrates.io%2Fcrates%2Forch)
![Crates.io Total Downloads](https://img.shields.io/crates/d/orch?link=https%3A%2F%2Fcrates.io%2Fcrates%2Forch)

`orch` is a library for building language model powered applications and agents for the Rust programming language.
It was primarily built for usage in [magic-cli](https://github.com/guywaldman/magic-cli), but can be used in other contexts as well.

> [!NOTE]
>
> If the project gains traction, this can be compiled as an addon to other languages such as Python or a standalone WebAssembly module.

# Installation

```shell
cargo add orch
```

Alternatively, add `orch as a dependency to your `Cargo.toml` file:

```toml
[dependencies]
orch = "*" # Substitute with the latest version
```

# Basic Usage

## Simple Text Generation

```rust
use orch::execution::*;
use orch::lm::*;

#[tokio::main]
async fn main() {
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = TextExecutorBuilder::new().with_lm(&lm).try_build().unwrap();
let response = executor.execute("What is 2+2?").await.expect("Execution failed");
println!("{}", response.content);
}
```

## Streaming Text Generation

```rust
use orch::execution::*;
use orch::lm::*;
use tokio_stream::StreamExt;

#[tokio::main]
async fn main() {
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = TextExecutorBuilder::new().with_lm(&lm).try_build().unwrap();
let mut response = executor.execute_stream("What is 2+2?").await.expect("Execution failed");
while let Some(chunk) = response.stream.next().await {
match chunk {
Ok(chunk) => print!("{chunk}"),
Err(e) => {
println!("Error: {e}");
break;
}
}
}
println!();
}
```

## Structured Data Generation

```rust
use orch::execution::*;
use orch::lm::*;
use orch_response_derive::*;

#[derive(OrchResponseOptions)]
pub enum CapitalCityExecutorResponseOptions {
#[response(
scenario = "You know the capital city of the country",
description = "Capital city of the country"
)]
#[schema(
field = "capital",
description = "Capital city of the received country",
example = "London"
)]
Answer { capital: String },
#[response(
scenario = "You don't know the capital city of the country",
description = "Reason why the capital city is not known"
)]
#[schema(
field = "reason",
description = "Reason why the capital city is not known",
example = "Country 'foobar' does not exist"
)]
Fail { reason: String },
}

#[tokio::main]
async fn main() {
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = StructuredExecutorBuilder::new()
.with_lm(&lm)
.with_preamble("You are a geography expert who helps users understand the capital city of countries around the world.")
.with_options(&options!(CapitalCityExecutorResponseOptions))
.try_build()
.unwrap();
let response = executor.execute("What is the capital of Fooland?").await.expect("Execution failed");

println!("Response:");
println!("{:?}", response.content);
}
```

## Embedding Generation

```rust
use orch::execution::*;
use orch::lm::*;

#[tokio::main]
async fn main() {
let lm = OllamaBuilder::new().try_build().unwrap();
let executor = TextExecutorBuilder::new()
.with_lm(&lm)
.try_build()
.unwrap();
let embedding = executor
.generate_embedding("Phrase to generate an embedding for")
.await
.expect("Execution failed");

println!("Embedding:");
println!("{:?}", embedding);
}
```

## More Examples

See the [examples](https://github.com/guywaldman/orch/tree/main/core/examples) directory for usage examples.

## Roadmap

- [ ] Agents and tools
See the [main README](../README.md) for more information.
6 changes: 3 additions & 3 deletions core/examples/embeddings.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! This example demonstrates how to use the `Executor` to generate embeddings from the language model.
//! We construct an `Ollama` instance and use it to generate embeddings.
//! Run like so: `cargo run --example embeddings`

use orch::execution::*;
use orch::lm::*;
Expand All @@ -26,13 +26,13 @@ async fn main() {
let lm: Box<dyn LanguageModel> = match provider {
LanguageModelProvider::Ollama => Box::new(
OllamaBuilder::new()
.with_embeddings_model(ollama_embedding_model::NOMIC_EMBED_TEXT)
.with_embeddings_model(ollama_embedding_model::NOMIC_EMBED_TEXT.to_string())
.try_build()
.unwrap(),
),
LanguageModelProvider::OpenAi => Box::new(
OpenAiBuilder::new()
.with_api_key(&open_ai_api_key)
.with_api_key(open_ai_api_key)
.try_build()
.unwrap(),
),
Expand Down
76 changes: 0 additions & 76 deletions core/examples/structured_data_generation_basic.rs

This file was deleted.

Loading
Loading