Add GLM 5.3 Flash support
This commit is contained in:
1 parent
9a33c61ea6
commit
46d6a976a5
31 files changed
+7806
-447
No files matched your search
+41
-1
@@ -54,6 +54,23 @@ pub(super) fn anthropic_request(value: Value) -> Result<ChatRequest, (u16, Strin
|
||||
for block in blocks {
|
||||
match block.get("type").and_then(Value::as_str).unwrap_or("text") {
|
||||
"text" => text.push_str(block.get("text").and_then(Value::as_str).unwrap_or("")),
|
||||
"image" => {
|
||||
let source = block.get("source").and_then(Value::as_object);
|
||||
let media = source
|
||||
.and_then(|source| source.get("media_type"))
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("");
|
||||
let data = source
|
||||
.and_then(|source| source.get("data"))
|
||||
.and_then(Value::as_str)
|
||||
.unwrap_or("");
|
||||
if !matches!(media, "image/png" | "image/jpeg") || data.is_empty() {
|
||||
return Err((400, "image input must be inline PNG or JPEG base64".into()));
|
||||
}
|
||||
text.push_str(&crate::engine::vision_data_marker(&format!(
|
||||
"data:{media};base64,{data}"
|
||||
)));
|
||||
}
|
||||
"thinking" | "redacted_thinking" => reasoning.push_str(
|
||||
block
|
||||
.get("thinking")
|
||||
@@ -382,6 +399,24 @@ fn responses_content_text(value: &Value) -> Result<String, (u16, String)> {
|
||||
text.push_str(value);
|
||||
}
|
||||
}
|
||||
Value::Object(part)
|
||||
if part.get("type").and_then(Value::as_str) == Some("input_image") =>
|
||||
{
|
||||
let url = part
|
||||
.get("image_url")
|
||||
.or_else(|| part.get("url"))
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| (400, "invalid image input".into()))?;
|
||||
if !url.starts_with("data:image/png;base64,")
|
||||
&& !url.starts_with("data:image/jpeg;base64,")
|
||||
{
|
||||
return Err((
|
||||
400,
|
||||
"image input must be an inline PNG or JPEG data URI".into(),
|
||||
));
|
||||
}
|
||||
text.push_str(&crate::engine::vision_data_marker(url));
|
||||
}
|
||||
_ => return Err((400, "invalid JSON request".into())),
|
||||
}
|
||||
}
|
||||
@@ -574,7 +609,12 @@ fn request_reasoning(
|
||||
|| (explicit_thinking.is_none()
|
||||
&& matches!(
|
||||
model_id,
|
||||
"deepseek-chat" | "glm-5.2-chat" | "glm-5.2-no-think" | "glm-5.2-nothink"
|
||||
"deepseek-chat"
|
||||
| "glm-5.2-chat"
|
||||
| "glm-5.2-no-think"
|
||||
| "glm-5.2-nothink"
|
||||
| "glm-5.3-flash-chat"
|
||||
| "zai/glm-5.3-flash-chat"
|
||||
))
|
||||
{
|
||||
reasoning = ReasoningMode::Direct;
|
||||
|
||||
+37
-2
@@ -365,6 +365,7 @@ pub(super) fn render_messages(
|
||||
|
||||
let mut turns = Vec::<ChatTurn>::new();
|
||||
for message in messages {
|
||||
validate_inline_images(&message.content)?;
|
||||
let content = content_text(&message.content);
|
||||
match message.role.as_str() {
|
||||
"system" | "developer" => {
|
||||
@@ -426,6 +427,30 @@ pub(super) fn render_messages(
|
||||
Ok((system, turns))
|
||||
}
|
||||
|
||||
fn validate_inline_images(value: &Value) -> Result<(), (u16, String)> {
|
||||
let Some(parts) = value.as_array() else {
|
||||
return Ok(());
|
||||
};
|
||||
for part in parts {
|
||||
let Some(image) = part.get("image_url") else {
|
||||
continue;
|
||||
};
|
||||
let url = image
|
||||
.get("url")
|
||||
.or(Some(image))
|
||||
.and_then(Value::as_str)
|
||||
.ok_or_else(|| (400, "invalid image input".into()))?;
|
||||
if !url.starts_with("data:image/png;base64,") && !url.starts_with("data:image/jpeg;base64,")
|
||||
{
|
||||
return Err((
|
||||
400,
|
||||
"image input must be an inline PNG or JPEG data URI".into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(super) fn validate_tool_results(
|
||||
state: &State,
|
||||
messages: &[ApiMessage],
|
||||
@@ -779,8 +804,18 @@ pub(super) fn content_text(value: &Value) -> String {
|
||||
Value::Array(parts) => parts
|
||||
.iter()
|
||||
.filter_map(|part| match part {
|
||||
Value::String(text) => Some(text.as_str()),
|
||||
Value::Object(object) => object.get("text").and_then(Value::as_str),
|
||||
Value::String(text) => Some(text.clone()),
|
||||
Value::Object(object) => object
|
||||
.get("text")
|
||||
.and_then(Value::as_str)
|
||||
.map(str::to_owned)
|
||||
.or_else(|| {
|
||||
let url = object
|
||||
.get("image_url")
|
||||
.and_then(|value| value.get("url").or(Some(value)))
|
||||
.and_then(Value::as_str)?;
|
||||
Some(crate::engine::vision_data_marker(url))
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
.collect(),
|
||||
|
||||
Reference in new issue
Block a user