Skip to content

Commit bf7cf65

Browse files
committed
fixed issues with async execution of python methods
1 parent ec9bab5 commit bf7cf65

File tree

27 files changed

+212
-262
lines changed

27 files changed

+212
-262
lines changed

.python-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.11.9
1+
3.12

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ brew install \
7878
protobuf \
7979
# We are investigating if this is necessary or can be removed
8080
libiconv \
81-
python@3.11 \
81+
python@3.12 \
8282
# Chidori uses uv for handling python dependencies
8383
uv
8484

toolchain/Cargo.lock

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

toolchain/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ members = [
44
"chidori-prompt-format",
55
"chidori-static-analysis",
66
"chidori-debugger",
7-
"chidori-tsne",
87
]
98
resolver = "2"
109

toolchain/book_src/ARCHITECTURE.md

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ Chidori consists of the following crates:
88
- `chidori-debugger` contains a UI for visualizing and debugging Chidori executed programs.
99
- `chidori-prompt-format` implements handlebars-like templating with support for tracing composition
1010
- `chidori-static-analysis` implements our parsing and extraction of control-flow from Python and TypeScript source code
11-
- `chidori-tsne` (IGNORE) - not yet implemented, in the future we'd like to add support for visualizing embeddings within our debugger
1211

1312

1413
### Chidori Core

toolchain/book_src/COMMON_ERRORS.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
## Error: `ld: library 'python3.12' not found`
55

66
Solution:
7-
Set PYO3_PYTHON=python3.11 when building chidori-debugger to your currently installed python version.
7+
Set PYO3_PYTHON=python3.12 when building chidori-debugger to your currently installed python version.
88

99

1010

toolchain/chidori-core/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,4 @@ anyhow = "1.0.82"
122122

123123

124124
[package.metadata.pyo3]
125-
python = "/opt/homebrew/bin/python3.11"
125+
python = "/opt/homebrew/bin/python3.12"

toolchain/chidori-core/build.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ fn add_extension_module_link_args(triple: &Triple) -> io::Result<()> {
2828
writeln!(writer, "cargo:rustc-cdylib-link-arg=-undefined")?;
2929
writeln!(writer, "cargo:rustc-cdylib-link-arg=dynamic_lookup")?;
3030
writeln!(writer, "cargo:rustc-link-search=native=/opt/homebrew/Cellar/libiconv/1.17/lib")?;
31-
writeln!(writer, "cargo:rustc-link-search=native=/opt/homebrew/Cellar/python@3.11/3.11.9_1/Frameworks/Python.framework/Versions/3.11/lib")?;
32-
writeln!(writer, "cargo:rustc-link-lib=dylib=python3.11")?;
33-
println!("cargo:warning=Linking against Python 3.11");
31+
writeln!(writer, "cargo:rustc-link-search=native=/opt/homebrew/Cellar/python@3.12/3.12.5/Frameworks/Python.framework/Versions/3.12/lib")?;
32+
writeln!(writer, "cargo:rustc-link-lib=dylib=python3.12")?;
33+
println!("cargo:warning=Linking against Python 3.12");
3434

3535
// Assuming the toolchain directory is part of the RUSTUP_HOME environment variable
3636
let home_directory = home_dir().expect("Could not find the home directory");
Original file line numberDiff line numberDiff line change
@@ -1 +1,36 @@
1-
# Explaining and demonstrating our concurrency support
1+
# Explaining and demonstrating our concurrency support
2+
3+
This is a python function that is invoking a prompt by name, kwargs to this
4+
invocation are passed to the prompt. Prompts are async and return strings.
5+
```python (run_prompt_cell)
6+
async def first_letter(s):
7+
return s.replace("-", "").strip()[0]
8+
9+
async def run_prompt(number_of_states):
10+
out = ""
11+
for state in (await get_states_first_letters(num=number_of_states)).split('\n'):
12+
out += await first_letter(state)
13+
return "demo" + out
14+
```
15+
16+
This is the prompt itself. The cell name is used to refer to the prompt output when it is satisfied
17+
by globally available values. The fn key is used to name the prompt in the context of a function invocation.
18+
```prompt (states)
19+
---
20+
model: gpt-3.5-turbo
21+
fn: get_states_first_letters
22+
---
23+
List the first {{num}} US states to be added to the union.
24+
Return this as a `-` bulleted list with the name of the state on each line.
25+
```
26+
27+
A unit test demonstrates the invocation of the prompt by the function.
28+
```python (entry)
29+
import unittest
30+
31+
class TestMarshalledValues(unittest.IsolatedAsyncioTestCase):
32+
async def test_run_prompt(self):
33+
self.assertEqual(await run_prompt(5), "demoDPNGC")
34+
35+
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(TestMarshalledValues))
36+
```

toolchain/chidori-core/examples/core2_marshalling/core.md

+20
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ Chidori.assertEq(x6, [1, 2, 3]);
4242

4343
// TODO: marshalling of functions is not currently supported
4444
// Chidori.assertEq(typeof x9, "function");
45+
46+
47+
// These will appear in the UI
48+
const jsX0 = x0;
49+
const jsX1 = x1;
50+
const jsX2 = x2;
51+
const jsX3 = x3;
52+
const jsX4 = x4;
53+
const jsX5 = x5;
54+
const jsX6 = x6;
4555
```
4656

4757

@@ -83,5 +93,15 @@ class TestMarshalledValues(unittest.TestCase):
8393
self.assertEqual(y6, [1,2,3])
8494

8595
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(TestMarshalledValues))
96+
97+
98+
# These will appear in the UI
99+
pyY0 = y0
100+
pyY1 = y1
101+
pyY2 = y2
102+
pyY3 = y3
103+
pyY4 = y4
104+
pyY5 = y5
105+
pyY6 = y6
86106
```
87107

toolchain/chidori-core/examples/core4_async_function_invocations/core.md

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { assertEquals } from "https://deno.land/[email protected]/assert/mod.ts";
1313
Deno.test("async addition test", async () => {
1414
assertEquals(await add_two(2), 4);
1515
});
16+
17+
const resultJs = await add_two(2)
1618
```
1719

1820
### Demonstrates defining a function in javascript and calling it in python

toolchain/chidori-core/examples/core5_prompts_invoked_as_functions/core.md

+2-6
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,7 @@ Return this as a `-` bulleted list with the name of the state on each line.
2626

2727
A unit test demonstrates the invocation of the prompt by the function.
2828
```python (entry)
29-
import unittest
29+
result = await run_prompt(5)
30+
```
3031

31-
class TestMarshalledValues(unittest.IsolatedAsyncioTestCase):
32-
async def test_run_prompt(self):
33-
self.assertEqual(await run_prompt(5), "demoDPNGC")
3432

35-
unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(TestMarshalledValues))
36-
```

toolchain/chidori-core/examples/core6_prompts_leveraging_function_calling/core.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ def add_two_numbers(a, b):
66
```
77

88

9-
```prompt (add_population)
9+
```prompt (declare_add_population)
1010
---
11-
fn: add_population
1211
model: gpt-3.5-turbo
12+
fn: add_population
1313
import:
1414
- add_two_numbers
1515
---

toolchain/chidori-core/pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ authors = [{ name = "Colton Pierson", email = "[email protected]" }]
66
dependencies = [
77
]
88
readme = "README.md"
9-
requires-python = "== 3.11"
9+
requires-python = "== 3.12"
1010

1111
[tool.rye]
1212
managed = true

toolchain/chidori-core/src/cells/code_cell.rs

+13-21
Original file line numberDiff line numberDiff line change
@@ -78,27 +78,19 @@ pub fn code_cell(execution_state_id: ExecutionNodeId, cell: &CodeCell, range: &T
7878
let s = s.clone();
7979
let cell = cell.clone();
8080
async move {
81-
let result = tokio::task::spawn_blocking(move || {
82-
let runtime = tokio::runtime::Runtime::new().unwrap();
83-
let result = runtime.block_on(crate::library::std::code::runtime_deno::source_code_run_deno(
84-
&s,
85-
&cell.source_code,
86-
&x,
87-
&cell.function_invocation,
88-
));
89-
match result {
90-
Ok(v) =>
91-
Ok(OperationFnOutput {
92-
has_error: false,
93-
execution_state: None,
94-
output: Ok(v.0),
95-
stdout: v.1,
96-
stderr: v.2,
97-
}),
98-
Err(e) => panic!("{:?}", e),
99-
}
100-
}).await.unwrap();
101-
result
81+
let result = crate::library::std::code::runtime_deno::source_code_run_deno(
82+
&s,
83+
&cell.source_code,
84+
&x,
85+
&cell.function_invocation,
86+
).await?;
87+
Ok(OperationFnOutput {
88+
has_error: false,
89+
execution_state: None,
90+
output: result.0,
91+
stdout: result.1,
92+
stderr: result.2,
93+
})
10294
}.boxed()
10395
}),
10496
))

toolchain/chidori-core/src/execution/execution/execution_graph.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl ExecutionGraph {
178178
_ = tokio::time::sleep(Duration::from_millis(10)) => {
179179
match receiver.try_recv() {
180180
Ok((resulting_execution_state, oneshot)) => {
181-
println!("==== Received dispatch event {:?}", resulting_execution_state);
181+
println!("==== Execution Graph received dispatch event {:?}", resulting_execution_state);
182182

183183
let s = resulting_execution_state.clone();
184184
match &resulting_execution_state {
@@ -366,7 +366,7 @@ impl ExecutionGraph {
366366
ExecutionStateEvaluation::Error(_) => unreachable!("Cannot get state from a future state"),
367367
ExecutionStateEvaluation::EvalFailure(_) => unreachable!("Cannot get state from a future state"),
368368
};
369-
println!("Inserting into graph {:?}", &resulting_state_id);
369+
println!("Resulting state received from progress_graph {:?}", &resulting_state_id);
370370
// TODO: if state already exists how to handle
371371
state_id_to_state.deref_mut().insert(resulting_state_id.clone(), new_state.clone());
372372
execution_graph.deref_mut()
@@ -390,11 +390,10 @@ impl ExecutionGraph {
390390
(ExecutionNodeId, ExecutionStateEvaluation), // the resulting total state of this step
391391
Vec<(usize, OperationFnOutput)>, // values emitted by operations during this step
392392
)> {
393+
println!("step_execution_with_previous_state");
393394
let previous_state = match previous_state {
394395
ExecutionStateEvaluation::Complete(state) => state,
395-
ExecutionStateEvaluation::Executing(..) => panic!("Cannot step an execution state that is still executing"),
396-
ExecutionStateEvaluation::Error(_) => unreachable!("Cannot get state from a future state"),
397-
ExecutionStateEvaluation::EvalFailure(_) => unreachable!("Cannot get state from a future state"),
396+
_ => { panic!("Stepping execution should only occur against completed states") }
398397
};
399398
let eval_state = previous_state.determine_next_operation()?;
400399
let (new_state, outputs) = previous_state.step_execution(eval_state).await?;
@@ -444,6 +443,7 @@ impl ExecutionGraph {
444443
(ExecutionNodeId, ExecutionStateEvaluation), // the resulting total state of this step
445444
Vec<(usize, OperationFnOutput)>, // values emitted by operations during this step
446445
)> {
446+
println!("external_step_execution");
447447
let state = self.get_state_at_id(prev_execution_id);
448448
if let Some(state) = state {
449449
self.step_execution_with_previous_state(&state).await

toolchain/chidori-core/src/execution/execution/execution_state.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub enum ExecutionStateErrors {
8484
CellExecutionUnexpectedFailure(ExecutionNodeId, String),
8585
#[error("unknown execution state error")]
8686
Unknown(String),
87-
#[error("anyhow error")]
87+
#[error("Anyhow Error: {0}")]
8888
AnyhowError(String),
8989
}
9090

@@ -131,7 +131,7 @@ impl Debug for ExecutionStateEvaluation {
131131
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132132
match self {
133133
ExecutionStateEvaluation::Complete(ref state) => f.debug_tuple("Complete").field(state).finish(),
134-
ExecutionStateEvaluation::Executing(..) => f.debug_tuple("Executing").field(&format!("Future state evaluating")).finish(),
134+
ExecutionStateEvaluation::Executing(ref state) => f.debug_tuple("Executing").field(state).finish(),
135135
ExecutionStateEvaluation::Error(_) => unreachable!("Cannot get state from a future state"),
136136
ExecutionStateEvaluation::EvalFailure(_) => unreachable!("Cannot get state from a future state"),
137137
}
@@ -187,6 +187,9 @@ pub struct ExecutionState {
187187
/// Map of operation_id -> OperationNode definition
188188
pub operation_by_id: ImHashMap<OperationId, Arc<Mutex<OperationNode>>>,
189189

190+
/// Map of operation_id -> Cell definition
191+
pub cells_by_id: ImHashMap<OperationId, CellTypes>,
192+
190193
/// This is a mapping of function names to operation ids. Function calls are dispatched to the associated
191194
/// OperationId that they are initialized by. When a function is invoked, it is dispatched to the operation
192195
/// node that initialized it where we re-use that OperationNode's runtime in order to invoke the function.
@@ -225,8 +228,8 @@ fn render_map_as_table(exec_state: &ExecutionState) -> String {
225228
|---|---|"));
226229
for key in exec_state.state.keys() {
227230
if let Some(val) = exec_state.state_get(key) {
228-
table.push_str(&format!(indoc!(r"
229-
| {} | {:?} |" ), key, val));
231+
table.push_str(&format!(indoc!(r"| {} | {:?} |" ), key, val));
232+
table.push_str("\n");
230233
}
231234
}
232235
table.push_str("\n");
@@ -255,7 +258,7 @@ async fn pause_future_with_oneshot(execution_state_evaluation: ExecutionStateEva
255258
}
256259
// let recv = oneshot_receiver.await.expect("Failed to receive oneshot signal");
257260
}
258-
println!("Continuing from oneshot signal");
261+
println!("============= should resume =============");
259262
RkyvSerializedValue::Null
260263
};
261264
sender.send((execution_state_evaluation, Some(oneshot_sender))).await.expect("Failed to send oneshot signal to the graph receiver");
@@ -281,6 +284,7 @@ impl Default for ExecutionState {
281284
fresh_values: Default::default(),
282285
operation_name_to_id: Default::default(),
283286
operation_by_id: Default::default(),
287+
cells_by_id: Default::default(),
284288
function_name_to_metadata: Default::default(),
285289
has_been_set: Default::default(),
286290
dependency_map: Default::default(),
@@ -537,7 +541,7 @@ impl ExecutionState {
537541
})
538542
};
539543
operation_node.id = op_id;
540-
544+
s.cells_by_id.insert(op_id, operation_node.cell.clone());
541545
s.operation_by_id.insert(op_id, Arc::new(Mutex::new(operation_node)));
542546
s.update_callable_functions();
543547
s.exec_queue.push_back(op_id);
@@ -836,7 +840,7 @@ impl ExecutionState {
836840
let operation_count = self.operation_by_id.keys().count();
837841
let mut count_loops = 0;
838842
loop {
839-
println!("looping {:?}", self.exec_queue);
843+
println!("looping {:?} {:?}", self.exec_queue, count_loops);
840844
count_loops += 1;
841845
if count_loops >= operation_count * 2 {
842846
return Err(Error::msg("Looped through all operations without detecting an execution"));

0 commit comments

Comments
 (0)