Commit 9c7b1ead authored by Graham King's avatar Graham King Committed by GitHub
Browse files

fix(pystr): Output python errors (#99)

If the python file raises an exception we print it like Python would.

```
$ ./target/debug/dynamo-run in=http out=pystr:~/Temp/cn47/1_e.py --model-name test

Traceback (most recent call last):
  File "/home/graham/Temp/cn47/1_e.py", line 17, in generate
    raise MyException("The message")
1_e.MyException: The message
```
parent a954a1c6
......@@ -188,17 +188,33 @@ async fn main_loop(
let mut stdout = std::io::stdout();
let mut assistant_message = String::new();
while let Some(item) = stream.next().await {
let data = item.data.as_ref().unwrap();
let entry = data.inner.choices.first();
let chat_comp = entry.as_ref().unwrap();
if let Some(c) = &chat_comp.delta.content {
let _ = stdout.write(c.as_bytes());
let _ = stdout.flush();
assistant_message += c;
}
if chat_comp.finish_reason.is_some() {
tracing::trace!("finish reason: {:?}", chat_comp.finish_reason.unwrap());
break;
match (item.data.as_ref(), item.event.as_deref()) {
(Some(data), _) => {
// Normal case
let entry = data.inner.choices.first();
let chat_comp = entry.as_ref().unwrap();
if let Some(c) = &chat_comp.delta.content {
let _ = stdout.write(c.as_bytes());
let _ = stdout.flush();
assistant_message += c;
}
if chat_comp.finish_reason.is_some() {
tracing::trace!("finish reason: {:?}", chat_comp.finish_reason.unwrap());
break;
}
}
(None, Some("error")) => {
// There's only one error but we loop in case that changes
for err in item.comment.unwrap_or_default() {
tracing::error!("Engine error: {err}");
}
}
(None, Some(annotation)) => {
tracing::debug!("Annotation. {annotation}: {:?}", item.comment);
}
_ => {
unreachable!("Event from engine with no data, no error, no annotation.");
}
}
}
println!();
......
......@@ -234,17 +234,14 @@ where
// todo: add task-local context to the python async generator
ctx.stop_generating();
let msg = format!("critical error: invalid response object from python async generator; application-logic-mismatch: {}", e);
tracing::error!(request_id, "{}", msg);
msg
}
ResponseProcessingError::PythonException(e) => {
let msg = format!("a python exception was caught while processing the async generator: {}", e);
tracing::warn!(request_id, "{}", msg);
msg
}
ResponseProcessingError::OffloadError(e) => {
let msg = format!("critical error: failed to offload the python async generator to a new thread: {}", e);
tracing::error!(request_id, "{}", msg);
msg
}
};
......@@ -288,8 +285,11 @@ async fn process_item<Resp>(
where
Resp: Data + for<'de> Deserialize<'de>,
{
let item = item.map_err(|e| ResponseProcessingError::PythonException(e.to_string()))?;
let item = item.map_err(|e| {
println!();
Python::with_gil(|py| e.display(py));
ResponseProcessingError::PythonException(e.to_string())
})?;
let response = tokio::task::spawn_blocking(move || {
Python::with_gil(|py| depythonize::<Resp>(&item.into_bound(py)))
})
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment