fix(openai): implement role-based content mapping for Responses API
This commit is contained in:
@@ -115,17 +115,20 @@ impl super::Provider for OpenAIProvider {
|
|||||||
let role = m["role"].as_str().unwrap_or("user");
|
let role = m["role"].as_str().unwrap_or("user");
|
||||||
let mut content = m.get("content").cloned().unwrap_or(serde_json::json!([]));
|
let mut content = m.get("content").cloned().unwrap_or(serde_json::json!([]));
|
||||||
|
|
||||||
// Map "text" -> "input_text" and "image_url" -> "input_image" for Responses API
|
// Map content types based on role for Responses API
|
||||||
if let Some(content_array) = content.as_array_mut() {
|
if let Some(content_array) = content.as_array_mut() {
|
||||||
for part in content_array {
|
for part in content_array {
|
||||||
if let Some(part_obj) = part.as_object_mut() {
|
if let Some(part_obj) = part.as_object_mut() {
|
||||||
if let Some(t) = part_obj.get("type").and_then(|v| v.as_str()) {
|
if let Some(t) = part_obj.get("type").and_then(|v| v.as_str()) {
|
||||||
match t {
|
match t {
|
||||||
"text" => {
|
"text" => {
|
||||||
part_obj.insert("type".to_string(), serde_json::json!("input_text"));
|
let new_type = if role == "assistant" { "output_text" } else { "input_text" };
|
||||||
|
part_obj.insert("type".to_string(), serde_json::json!(new_type));
|
||||||
}
|
}
|
||||||
"image_url" => {
|
"image_url" => {
|
||||||
part_obj.insert("type".to_string(), serde_json::json!("input_image"));
|
// Assistant typically doesn't have image_url in history this way, but for safety:
|
||||||
|
let new_type = if role == "assistant" { "output_image" } else { "input_image" };
|
||||||
|
part_obj.insert("type".to_string(), serde_json::json!(new_type));
|
||||||
if let Some(img_url) = part_obj.remove("image_url") {
|
if let Some(img_url) = part_obj.remove("image_url") {
|
||||||
part_obj.insert("image".to_string(), img_url);
|
part_obj.insert("image".to_string(), img_url);
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,8 @@ impl super::Provider for OpenAIProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(text) = content.as_str() {
|
} else if let Some(text) = content.as_str() {
|
||||||
content = serde_json::json!([{ "type": "input_text", "text": text }]);
|
let new_type = if role == "assistant" { "output_text" } else { "input_text" };
|
||||||
|
content = serde_json::json!([{ "type": new_type, "text": text }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_parts.push(serde_json::json!({
|
input_parts.push(serde_json::json!({
|
||||||
@@ -350,17 +354,20 @@ impl super::Provider for OpenAIProvider {
|
|||||||
let role = m["role"].as_str().unwrap_or("user");
|
let role = m["role"].as_str().unwrap_or("user");
|
||||||
let mut content = m.get("content").cloned().unwrap_or(serde_json::json!([]));
|
let mut content = m.get("content").cloned().unwrap_or(serde_json::json!([]));
|
||||||
|
|
||||||
// Map "text" -> "input_text" and "image_url" -> "input_image" for Responses API
|
// Map content types based on role for Responses API
|
||||||
if let Some(content_array) = content.as_array_mut() {
|
if let Some(content_array) = content.as_array_mut() {
|
||||||
for part in content_array {
|
for part in content_array {
|
||||||
if let Some(part_obj) = part.as_object_mut() {
|
if let Some(part_obj) = part.as_object_mut() {
|
||||||
if let Some(t) = part_obj.get("type").and_then(|v| v.as_str()) {
|
if let Some(t) = part_obj.get("type").and_then(|v| v.as_str()) {
|
||||||
match t {
|
match t {
|
||||||
"text" => {
|
"text" => {
|
||||||
part_obj.insert("type".to_string(), serde_json::json!("input_text"));
|
let new_type = if role == "assistant" { "output_text" } else { "input_text" };
|
||||||
|
part_obj.insert("type".to_string(), serde_json::json!(new_type));
|
||||||
}
|
}
|
||||||
"image_url" => {
|
"image_url" => {
|
||||||
part_obj.insert("type".to_string(), serde_json::json!("input_image"));
|
// Assistant typically doesn't have image_url in history this way, but for safety:
|
||||||
|
let new_type = if role == "assistant" { "output_image" } else { "input_image" };
|
||||||
|
part_obj.insert("type".to_string(), serde_json::json!(new_type));
|
||||||
if let Some(img_url) = part_obj.remove("image_url") {
|
if let Some(img_url) = part_obj.remove("image_url") {
|
||||||
part_obj.insert("image".to_string(), img_url);
|
part_obj.insert("image".to_string(), img_url);
|
||||||
}
|
}
|
||||||
@@ -371,7 +378,8 @@ impl super::Provider for OpenAIProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(text) = content.as_str() {
|
} else if let Some(text) = content.as_str() {
|
||||||
content = serde_json::json!([{ "type": "input_text", "text": text }]);
|
let new_type = if role == "assistant" { "output_text" } else { "input_text" };
|
||||||
|
content = serde_json::json!([{ "type": new_type, "text": text }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
input_parts.push(serde_json::json!({
|
input_parts.push(serde_json::json!({
|
||||||
|
|||||||
Reference in New Issue
Block a user