anthropic: Use separate Content type in requests and responses (#17163)
Some checks are pending
CI / Check formatting and spelling (push) Waiting to run
CI / (macOS) Run Clippy and tests (push) Waiting to run
CI / (Linux) Run Clippy and tests (push) Waiting to run
CI / (Windows) Run Clippy and tests (push) Waiting to run
CI / Create a macOS bundle (push) Blocked by required conditions
CI / Create a Linux bundle (push) Blocked by required conditions
CI / Create arm64 Linux bundle (push) Blocked by required conditions
Deploy Docs / Deploy Docs (push) Waiting to run
Docs / Check formatting (push) Waiting to run

This PR splits the `Content` type for Anthropic into two new types:
`RequestContent` and `ResponseContent`.

As I was going through the Anthropic API docs it seems that there are
different types of content that can be sent in requests vs what can be
returned in responses.

Using a separate type for each case tells the story a bit better and
makes it easier to understand, IMO.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-08-30 11:46:03 -04:00 committed by GitHub
parent 00eed768ce
commit 8901d926eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 13 deletions

View file

@ -337,7 +337,7 @@ pub fn extract_text_from_events(
match response {
Ok(response) => match response {
Event::ContentBlockStart { content_block, .. } => match content_block {
Content::Text { text, .. } => Some(Ok(text)),
ResponseContent::Text { text, .. } => Some(Ok(text)),
_ => None,
},
Event::ContentBlockDelta { delta, .. } => match delta {
@ -363,7 +363,7 @@ pub async fn extract_tool_args_from_events(
content_block,
} = event?
{
if let Content::ToolUse { name, .. } = content_block {
if let ResponseContent::ToolUse { name, .. } = content_block {
if name == tool_name {
tool_use_index = Some(index);
break;
@ -411,7 +411,7 @@ pub struct CacheControl {
#[derive(Debug, Serialize, Deserialize)]
pub struct Message {
pub role: Role,
pub content: Vec<Content>,
pub content: Vec<RequestContent>,
}
#[derive(Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
@ -423,7 +423,7 @@ pub enum Role {
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Content {
pub enum RequestContent {
#[serde(rename = "text")]
Text {
text: String,
@ -444,10 +444,22 @@ pub enum Content {
#[serde(skip_serializing_if = "Option::is_none")]
cache_control: Option<CacheControl>,
},
#[serde(rename = "tool_result")]
ToolResult {
tool_use_id: String,
content: String,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum ResponseContent {
#[serde(rename = "text")]
Text {
text: String,
#[serde(skip_serializing_if = "Option::is_none")]
cache_control: Option<CacheControl>,
},
#[serde(rename = "tool_use")]
ToolUse {
id: String,
name: String,
input: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
cache_control: Option<CacheControl>,
},
@ -525,7 +537,7 @@ pub struct Response {
#[serde(rename = "type")]
pub response_type: String,
pub role: Role,
pub content: Vec<Content>,
pub content: Vec<ResponseContent>,
pub model: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stop_reason: Option<String>,
@ -542,7 +554,7 @@ pub enum Event {
#[serde(rename = "content_block_start")]
ContentBlockStart {
index: usize,
content_block: Content,
content_block: ResponseContent,
},
#[serde(rename = "content_block_delta")]
ContentBlockDelta { index: usize, delta: ContentDelta },

View file

@ -304,17 +304,17 @@ impl LanguageModelRequest {
} else {
None
};
let anthropic_message_content: Vec<anthropic::Content> = message
let anthropic_message_content: Vec<anthropic::RequestContent> = message
.content
.into_iter()
.filter_map(|content| match content {
MessageContent::Text(t) if !t.is_empty() => {
Some(anthropic::Content::Text {
Some(anthropic::RequestContent::Text {
text: t,
cache_control,
})
}
MessageContent::Image(i) => Some(anthropic::Content::Image {
MessageContent::Image(i) => Some(anthropic::RequestContent::Image {
source: anthropic::ImageSource {
source_type: "base64".to_string(),
media_type: "image/png".to_string(),