Make language model deserialization more resilient (#31311)
This expands our deserialization of JSON from models to be more tolerant of different variations that the model may send, including capitalization, wrapping things in objects vs. being plain strings, etc. Also when deserialization fails, it reports the entire error in the JSON so we can see what failed to deserialize. (Previously these errors were very unhelpful at diagnosing the problem.) Finally, also removes the `WrappedText` variant since the custom deserializer just turns that style of JSON into a normal `Text` variant. Release Notes: - N/A
This commit is contained in:
parent
7443fde4e9
commit
00fd045844
9 changed files with 301 additions and 69 deletions
|
@ -19,7 +19,7 @@ use language_model::{
|
|||
LanguageModelCompletionError, LanguageModelId, LanguageModelKnownError, LanguageModelName,
|
||||
LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName,
|
||||
LanguageModelProviderState, LanguageModelRequest, LanguageModelToolChoice,
|
||||
LanguageModelToolResultContent, MessageContent, RateLimiter, Role, WrappedTextContent,
|
||||
LanguageModelToolResultContent, MessageContent, RateLimiter, Role,
|
||||
};
|
||||
use language_model::{LanguageModelCompletionEvent, LanguageModelToolUse, StopReason};
|
||||
use schemars::JsonSchema;
|
||||
|
@ -350,11 +350,7 @@ pub fn count_anthropic_tokens(
|
|||
// TODO: Estimate token usage from tool uses.
|
||||
}
|
||||
MessageContent::ToolResult(tool_result) => match &tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent {
|
||||
text,
|
||||
..
|
||||
}) => {
|
||||
LanguageModelToolResultContent::Text(text) => {
|
||||
string_contents.push_str(text);
|
||||
}
|
||||
LanguageModelToolResultContent::Image(image) => {
|
||||
|
@ -592,10 +588,9 @@ pub fn into_anthropic(
|
|||
tool_use_id: tool_result.tool_use_id.to_string(),
|
||||
is_error: tool_result.is_error,
|
||||
content: match tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(
|
||||
WrappedTextContent { text, .. },
|
||||
) => ToolResultContent::Plain(text.to_string()),
|
||||
LanguageModelToolResultContent::Text(text) => {
|
||||
ToolResultContent::Plain(text.to_string())
|
||||
}
|
||||
LanguageModelToolResultContent::Image(image) => {
|
||||
ToolResultContent::Multipart(vec![ToolResultPart::Image {
|
||||
source: anthropic::ImageSource {
|
||||
|
|
|
@ -37,7 +37,7 @@ use language_model::{
|
|||
LanguageModelProvider, LanguageModelProviderId, LanguageModelProviderName,
|
||||
LanguageModelProviderState, LanguageModelRequest, LanguageModelToolChoice,
|
||||
LanguageModelToolResultContent, LanguageModelToolUse, MessageContent, RateLimiter, Role,
|
||||
TokenUsage, WrappedTextContent,
|
||||
TokenUsage,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -639,8 +639,7 @@ pub fn into_bedrock(
|
|||
BedrockToolResultBlock::builder()
|
||||
.tool_use_id(tool_result.tool_use_id.to_string())
|
||||
.content(match tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent { text, .. }) => {
|
||||
LanguageModelToolResultContent::Text(text) => {
|
||||
BedrockToolResultContentBlock::Text(text.to_string())
|
||||
}
|
||||
LanguageModelToolResultContent::Image(_) => {
|
||||
|
@ -775,11 +774,7 @@ pub fn get_bedrock_tokens(
|
|||
// TODO: Estimate token usage from tool uses.
|
||||
}
|
||||
MessageContent::ToolResult(tool_result) => match tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent {
|
||||
text,
|
||||
..
|
||||
}) => {
|
||||
LanguageModelToolResultContent::Text(text) => {
|
||||
string_contents.push_str(&text);
|
||||
}
|
||||
LanguageModelToolResultContent::Image(image) => {
|
||||
|
|
|
@ -23,7 +23,7 @@ use language_model::{
|
|||
LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest,
|
||||
LanguageModelRequestMessage, LanguageModelToolChoice, LanguageModelToolResultContent,
|
||||
LanguageModelToolSchemaFormat, LanguageModelToolUse, MessageContent, RateLimiter, Role,
|
||||
StopReason, WrappedTextContent,
|
||||
StopReason,
|
||||
};
|
||||
use settings::SettingsStore;
|
||||
use std::time::Duration;
|
||||
|
@ -455,11 +455,7 @@ fn into_copilot_chat(
|
|||
for content in &message.content {
|
||||
if let MessageContent::ToolResult(tool_result) = content {
|
||||
let content = match &tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent {
|
||||
text,
|
||||
..
|
||||
}) => text.to_string().into(),
|
||||
LanguageModelToolResultContent::Text(text) => text.to_string().into(),
|
||||
LanguageModelToolResultContent::Image(image) => {
|
||||
if model.supports_vision() {
|
||||
ChatMessageContent::Multipart(vec![ChatMessagePart::Image {
|
||||
|
|
|
@ -426,10 +426,7 @@ pub fn into_google(
|
|||
}
|
||||
language_model::MessageContent::ToolResult(tool_result) => {
|
||||
match tool_result.content {
|
||||
language_model::LanguageModelToolResultContent::Text(text)
|
||||
| language_model::LanguageModelToolResultContent::WrappedText(
|
||||
language_model::WrappedTextContent { text, .. },
|
||||
) => {
|
||||
language_model::LanguageModelToolResultContent::Text(text) => {
|
||||
vec![Part::FunctionResponsePart(
|
||||
google_ai::FunctionResponsePart {
|
||||
function_response: google_ai::FunctionResponse {
|
||||
|
|
|
@ -13,7 +13,7 @@ use language_model::{
|
|||
LanguageModelId, LanguageModelName, LanguageModelProvider, LanguageModelProviderId,
|
||||
LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest,
|
||||
LanguageModelToolChoice, LanguageModelToolResultContent, LanguageModelToolUse, MessageContent,
|
||||
RateLimiter, Role, StopReason, WrappedTextContent,
|
||||
RateLimiter, Role, StopReason,
|
||||
};
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -428,11 +428,7 @@ pub fn into_mistral(
|
|||
}
|
||||
MessageContent::ToolResult(tool_result) => {
|
||||
let content = match &tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent {
|
||||
text,
|
||||
..
|
||||
}) => text.to_string(),
|
||||
LanguageModelToolResultContent::Text(text) => text.to_string(),
|
||||
LanguageModelToolResultContent::Image(_) => {
|
||||
// TODO: Mistral image support
|
||||
"[Tool responded with an image, but Zed doesn't support these in Mistral models yet]".to_string()
|
||||
|
|
|
@ -13,7 +13,7 @@ use language_model::{
|
|||
LanguageModelId, LanguageModelName, LanguageModelProvider, LanguageModelProviderId,
|
||||
LanguageModelProviderName, LanguageModelProviderState, LanguageModelRequest,
|
||||
LanguageModelToolChoice, LanguageModelToolResultContent, LanguageModelToolUse, MessageContent,
|
||||
RateLimiter, Role, StopReason, WrappedTextContent,
|
||||
RateLimiter, Role, StopReason,
|
||||
};
|
||||
use open_ai::{ImageUrl, Model, ResponseStreamEvent, stream_completion};
|
||||
use schemars::JsonSchema;
|
||||
|
@ -407,11 +407,7 @@ pub fn into_open_ai(
|
|||
}
|
||||
MessageContent::ToolResult(tool_result) => {
|
||||
let content = match &tool_result.content {
|
||||
LanguageModelToolResultContent::Text(text)
|
||||
| LanguageModelToolResultContent::WrappedText(WrappedTextContent {
|
||||
text,
|
||||
..
|
||||
}) => {
|
||||
LanguageModelToolResultContent::Text(text) => {
|
||||
vec![open_ai::MessagePart::Text {
|
||||
text: text.to_string(),
|
||||
}]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue