Skip to content

Commit 2cc8eb1

Browse files
committed
client
1 parent 18dd0db commit 2cc8eb1

File tree

316 files changed

+123969
-1314
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

316 files changed

+123969
-1314
lines changed

.gitignore

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
target
22
node_modules
3-
toolchain/chidori/package_node/native/chidori.node
3+
toolchain/chidori-old/package_node/native/chidori.node
44
toolcahin/chidori/build
55
__pycache__
66

@@ -64,6 +64,6 @@ dist
6464
.idea
6565
.venv
6666

67-
toolchain/chidori/package_python/chidori/_chidori.abi3.so
67+
toolchain/chidori-old/package_python/chidori/_chidori.abi3.so
6868

6969
.pre-commit-config.yaml

.idea/toolchain.iml

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

+15-264
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@ https://github.com/ThousandBirdsInc/chidori/assets/515757/6b088f7d-d8f7-4c7e-900
33

44
<div align="center">
55

6-
# &nbsp; Chidori &nbsp;
6+
# &nbsp; Chidori (v2) &nbsp;
77

88
**A reactive runtime for building durable AI agents**
99

1010
<p>
1111
<a href="https://github.com/ThousandBirdsInc/chidori/commits"><img alt="Current Build Status" src="https://img.shields.io/github/actions/workflow/status/ThousandBirdsInc/chidori/push.yml" /></a>
1212
<a href="https://github.com/ThousandBirdsInc/chidori/commits"><img alt="GitHub Last Commit" src="https://img.shields.io/github/last-commit/ThousandBirdsInc/chidori" /></a>
1313
<a href="https://crates.io/crates/chidori"><img alt="Cargo.io download" src="https://img.shields.io/crates/v/chidori" /></a>
14-
<a href="https://pypi.org/project/chidori/"><img alt="Pypi package" src="https://img.shields.io/pypi/v/chidori" /></a>
15-
<a href="https://www.npmjs.com/package/@1kbirds/chidori"><img alt="NPM package" src="https://img.shields.io/npm/v/@1kbirds/chidori" /></a>
1614
<a href="https://github.com/ThousandBirdsInc/chidori/blob/main/LICENSE"><img alt="Github License" src="https://img.shields.io/badge/License-MIT-green.svg" /></a>
1715
</p>
1816

@@ -54,7 +52,9 @@ Check out [high level docs ](https://docs.thousandbirds.ai/3fe20a82965148c7a0b48
5452

5553

5654
## 📖 Chidori
57-
Chidori is a reactive runtime for building AI agents. It provides a framework for building AI agents that are reactive, observable, and robust. It supports building agents with Node.js, Python, and Rust.
55+
Chidori is an open-source environment for building AI agents with simple and straight forward code.
56+
You author code like you typically would with python or javascript, and we provide a layer for interfacing
57+
with the complexities of AI models in long running workflows.
5858

5959
It is currently in alpha, and is not yet ready for production use. We are continuing to make significant changes in response to feedback.
6060

@@ -69,40 +69,12 @@ It is currently in alpha, and is not yet ready for production use. We are contin
6969
## ⚡️ Getting Started
7070

7171
### Installation
72-
You can use Chidori from Node.js, Python or Rust.
73-
74-
<table>
75-
<tr>
76-
<th width="450px"><b>Node.js</b></th>
77-
<th width="450px"><b>Python</b></th>
78-
<th width="450px"><b>Rust</b></th>
79-
</tr>
80-
<tr>
81-
<td>
82-
83-
```bash
84-
npm i @1kbirds/chidori
85-
```
86-
87-
</td>
88-
<td>
72+
Chidori is available on [crates.io](https://crates.io/crates/chidori) and can be installed using cargo.
8973

9074
```bash
91-
pip install chidori
75+
cargo install chidori-core
9276
```
9377

94-
</td>
95-
<td>
96-
97-
```bash
98-
cargo install chidori
99-
```
100-
101-
</td>
102-
</tr>
103-
</table>
104-
105-
10678

10779
### Environment Variables
10880
You will need to set the following environment variables if you depend on nodes that
@@ -120,16 +92,14 @@ the OpenAI API to filter to AI related launches and then format that data into m
12092
are pushed into the Chidori database and can be visualized using the prompt-graph-ui project. We'll update this example
12193
with a pattern that makes those results more accessible soon.
12294

123-
<table>
124-
<tr>
125-
<th width="450px"><b>Node.js</b></th>
126-
<th width="450px"><b>Python</b></th>
127-
<th width="450px"><b>Rust</b></th>
128-
</tr>
129-
<tr>
130-
<td>
13195

132-
```javascript
96+
Beginning here is an executable Chidori agent:
97+
------
98+
<pre>
99+
Chidori agents can be a single file, or a collection of files structured as a typical Typescript or Python project.
100+
The following example is a single file agent.
101+
102+
```js
133103
const axios = require('axios');
134104
const {Chidori, GraphBuilder} = require("@1kbirds/chidori");
135105

@@ -231,230 +201,11 @@ async function main() {
231201

232202

233203
main();
234-
235204
```
205+
</pre>
236206

237-
</td>
238-
<td>
239-
240-
```python
241-
import aiohttp
242-
import asyncio
243-
from typing import List, Optional
244-
import json
245-
from chidori import Chidori, GraphBuilder
246-
247-
248-
class Story:
249-
def __init__(self, title: str, url: Optional[str], score: Optional[float]):
250-
self.title = title
251-
self.url = url
252-
self.score = score
253-
254-
255-
HN_URL_TOP_STORIES = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty"
256-
257-
258-
async def fetch_story(session, id):
259-
async with session.get(f"https://hacker-news.firebaseio.com/v0/item/{id}.json?print=pretty") as response:
260-
return await response.json()
261-
262-
263-
async def fetch_hn() -> List[Story]:
264-
async with aiohttp.ClientSession() as session:
265-
async with session.get(HN_URL_TOP_STORIES) as response:
266-
story_ids = await response.json()
267-
268-
tasks = []
269-
for id in story_ids[:30]: # Limit to 30 stories
270-
tasks.append(fetch_story(session, id))
271-
272-
stories = await asyncio.gather(*tasks)
273-
274-
stories_out = []
275-
for story in stories:
276-
for k in ('title', 'url', 'score'):
277-
stories_out.append(Story(**dict((k, story.get(k, None)))))
278-
279-
return stories_out
280-
281-
282-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
283-
# Methods for fetching hacker news posts via api
284-
285-
class ChidoriWorker:
286-
def __init__(self):
287-
self.c = Chidori("0", "http://localhost:9800")
288-
self.staged_custom_nodes = []
289-
290-
async def build_graph(self):
291-
g = GraphBuilder()
292-
293-
# Create a custom node, we will implement our
294-
# own handler for this node type
295-
h = await g.custom_node(
296-
name="FetchTopHN",
297-
node_type_name="FetchTopHN",
298-
output="{ output: String }"
299-
)
300-
301-
# A prompt node, pulling in the value of the output from FetchTopHN
302-
# and templating that into the prompt for GPT3.5
303-
h_interpret = await g.prompt_node(
304-
name="InterpretTheGroup",
305-
template="""
306-
Based on the following list of HackerNews threads,
307-
filter this list to only launches of new AI projects: {{FetchTopHN.output}}
308-
"""
309-
)
310-
await h_interpret.run_when(g, h)
311-
312-
h_format_and_rank = await g.prompt_node(
313-
name="FormatAndRank",
314-
template="""
315-
Format this list of new AI projects in markdown, ranking the most
316-
interesting projects from most interesting to least.
317-
318-
{{InterpretTheGroup.promptResult}}
319-
"""
320-
)
321-
await h_format_and_rank.run_when(g, h_interpret)
322-
323-
# Commit the graph, this pushes the configured graph
324-
# to our durable execution runtime.
325-
await g.commit(self.c, 0)
326-
327-
async def run(self):
328-
# Construct the agent graph
329-
await self.build_graph()
330-
331-
# Start graph execution from the root
332-
await self.c.play(0, 0)
333-
334-
# Run the node execution loop
335-
await self.c.run_custom_node_loop()
336-
337-
338-
async def handle_fetch_hn(node_will_exec):
339-
stories = await fetch_hn()
340-
result = {"output": json.dumps([story.__dict__ for story in stories])}
341-
return result
342-
343-
344-
async def main():
345-
w = ChidoriWorker()
346-
await w.c.start_server(":memory:")
347-
await w.c.register_custom_node_handle("FetchTopHN", handle_fetch_hn)
348-
await w.run()
349-
350-
351-
if __name__ == "__main__":
352-
asyncio.run(main())
353-
```
354-
355-
</td>
356-
<td>
357-
358-
```rust
359-
extern crate chidori;
360-
use std::collections::HashMap;
361-
use std::env;
362-
use std::net::ToSocketAddrs;
363-
use anyhow;
364-
use futures::stream::{self, StreamExt, TryStreamExt};
365-
use reqwest;
366-
use serde::{Deserialize, Serialize};
367-
use serde_json::json;
368-
use chidori::{create_change_value, NodeWillExecuteOnBranch};
369-
use chidori::register_node_handle;
370-
use chidori::translations::rust::{Chidori, CustomNodeCreateOpts, DenoCodeNodeCreateOpts, GraphBuilder, Handler, PromptNodeCreateOpts, serialized_value_to_string};
371-
372-
#[derive(Debug, Deserialize, Serialize)]
373-
struct Story {
374-
title: String,
375-
url: Option<String>,
376-
score: Option<f32>,
377-
}
378-
379-
const HN_URL_TOP_STORIES: &'static str = "https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty";
380-
381-
async fn fetch_hn() -> anyhow::Result<Vec<Story>> {
382-
let client = reqwest::Client::new();
383-
// Fetch the top 60 story ids
384-
let story_ids: Vec<u32> = client.get(HN_URL_TOP_STORIES).send().await?.json().await?;
385-
386-
// Fetch details for each story
387-
let stories: anyhow::Result<Vec<Story>> = stream::iter(story_ids.into_iter().take(30))
388-
.map(|id| {
389-
let client = &client;
390-
async move {
391-
let resource = format!("https://hacker-news.firebaseio.com/v0/item/{}.json?print=pretty", id);
392-
let mut story: Story = client.get(&resource).send().await?.json().await?;
393-
Ok(story)
394-
}
395-
})
396-
.buffer_unordered(10) // Fetch up to 10 stories concurrently
397-
.try_collect()
398-
.await;
399-
stories
400-
}
401-
402-
async fn handle_fetch_hn(_node_will_exec: NodeWillExecuteOnBranch) -> anyhow::Result<serde_json::Value> {
403-
let stories = fetch_hn().await.unwrap();
404-
let mut result = HashMap::new();
405-
result.insert("output", format!("{:?}", stories));
406-
Ok(serde_json::to_value(result).unwrap())
407-
}
408-
409-
/// Maintain a list summarizing recent AI launches across the week
410-
#[tokio::main]
411-
async fn main() -> anyhow::Result<()> {
412-
let mut c = Chidori::new(String::from("0"), String::from("http://localhost:9800"));
413-
c.start_server(Some(":memory:".to_string())).await?;
414-
415-
let mut g = GraphBuilder::new();
416-
417-
let h = g.custom_node(CustomNodeCreateOpts {
418-
name: "FetchTopHN".to_string(),
419-
node_type_name: "FetchTopHN".to_string(),
420-
output: Some("{ output: String }".to_string()),
421-
..CustomNodeCreateOpts::default()
422-
})?;
423-
424-
let mut h_interpret = g.prompt_node(PromptNodeCreateOpts {
425-
name: "InterpretTheGroup".to_string(),
426-
template: "Based on the following list of HackerNews threads, filter this list to only launches of new AI projects: {{FetchTopHN.output}}".to_string(),
427-
..PromptNodeCreateOpts::default()
428-
})?;
429-
h_interpret.run_when(&mut g, &h)?;
430-
431-
let mut h_format_and_rank = g.prompt_node(PromptNodeCreateOpts {
432-
name: "FormatAndRank".to_string(),
433-
template: "Format this list of new AI projects in markdown, ranking the most interesting projects from most interesting to least. {{InterpretTheGroup.promptResult}}".to_string(),
434-
..PromptNodeCreateOpts::default()
435-
})?;
436-
h_format_and_rank.run_when(&mut g, &h_interpret)?;
437-
438-
// Commit the graph
439-
g.commit(&c, 0).await?;
440-
441-
// Start graph execution from the root
442-
c.play(0, 0).await?;
443-
444-
// Register the handler for our custom node
445-
register_node_handle!(c, "FetchTopHN", handle_fetch_hn);
446-
447-
// Run the node execution loop
448-
if let Err(x) = c.run_custom_node_loop().await {
449-
eprintln!("Custom Node Loop Failed On - {:?}", x);
450-
};
451-
Ok(())
452-
}
453-
```
207+
------
454208

455-
</td>
456-
</tr>
457-
</table>
458209

459210
## 🤔 About
460211

0 commit comments

Comments
 (0)