Skip to content

Commit

Permalink
Fix proc macro, simplify, refactor (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
guywaldman authored Jul 21, 2024
1 parent 07483be commit 55f4c20
Show file tree
Hide file tree
Showing 24 changed files with 624 additions and 608 deletions.
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

0 comments on commit 55f4c20

Please sign in to comment.