cloudflare / cloudflare/workers-rs

[BUG] ai.run misbehaves with serde_json::Value, should probably use json_compatible serializer

Open
#1,050 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
3.7k
Forks
429
Avg merge
20h 28m
Merged PRs (30d)
7

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### What version of `workers-rs` are you using?

0.8.5

### What version of `wrangler` are you using?

4.118.0

### Describe the bug

Here, in workers-rs ai.run, it calls `serde_wasm_bindgen::to_value`.

https://github.com/cloudflare/workers-rs/blob/bb141710ebcf38b5a61c6e8f1d1c20c3dd2f3f6d/worker/src/ai.rs#L26

Unfortunately, if your input is or contains a serde_json::Value, those get converted to Javascript *Map* values, not objects.

The downstream javascript `ai.run` implementation does not seem to tolerate Map objects, and seems to just ignore them (it's kind of hard to tell what's going on but it looks like maybe it was treating them as empty objects).

I believe the workers-rs `ai.run` should be serializing its input using the [json_compatible](https://docs.rs/serde-wasm-bindgen/latest/serde_wasm_bindgen/struct.Serializer.html#method.json_compatible) serializer from serde_wasm_bindgen. This would allow it to pass on the objects appropriately to ai.run. I wouldn't be surprised if this affects multiple APIs in workers-rs.

### Steps To Reproduce

```rust
#[derive(Serialize)]
struct Tool {
name: String,
description: String,
parameters: serde_json::Value,
}

#[derive(Serialize)]
struct Message {
role: &'static str,
content: &'static str,
}

#[derive(Serialize)]
struct ChatRequest {
messages: Vec,
tools: Vec,
}

let tool = Tool {
name: "CreateCreature".into(),
description: "Create a creature".into(),
parameters: serde_json::json!({
"type": "object",
"properties": {
"creature": {
"type": "object",
"properties": {
"name": { "type": "string" },
"size": {
"type": "object",
"properties": {
"x": { "type": "integer" },
"y": { "type": "integer" },
"z": { "type": "integer" }
}
}
}
}
}
}),
};

let req = ChatRequest {
messages: vec![Message {
role: "user",
content: "Create a creature named Goblin.",
}],
tools: vec![tool],
};

ai.run(model, req).await?;
```

When I run code like the following, it doesn't seem the model actually gets the content of the `parameters` in the input schema.

Contributor guide

Open the contributing guide

Research direction

Start at worker/src/ai.rs around the linked line where ai.run serializes its input, then reproduce the issue with the serde_json::Value-based ChatRequest shown here. Check how the JavaScript value is represented and add coverage demonstrating that nested input reaches ai.run as an object rather than a Map; done means the provided tool schema is preserved.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
ai, api, backend-api-design
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.