OpenAI function calling compatible support (#1888)

# What does this PR do?

<!-- Remove if not applicable -->

Fixes # (issue)
https://github.com/huggingface/text-generation-inference/issues/1887

## Before submitting
- [no ] This PR fixes a typo or improves the docs (you can dismiss the
other checks if that's the case).
- [yes] Did you read the [contributor
guideline](https://github.com/huggingface/transformers/blob/main/CONTRIBUTING.md#start-contributing-pull-requests),
      Pull Request section?
- [ yes] Was this discussed/approved via a Github issue or the
[forum](https://discuss.huggingface.co/)? Please add a link
      to it if that's the case.
- [yes ] Did you make sure to update the documentation with your
changes? Here are the
[documentation
guidelines](https://github.com/huggingface/transformers/tree/main/docs),
and
[here are tips on formatting
docstrings](https://github.com/huggingface/transformers/tree/main/docs#writing-source-documentation).
- [ yes] Did you write any new necessary tests?


## Who can review?

Anyone in the community is free to review the PR once the tests have
passed. Feel free to tag
members/contributors who may be interested in your PR.

@Narsil

 -->

---------

Co-authored-by: Bao Phan <baopg@inter-k.com>
This commit is contained in:
phangiabao98 2024-05-16 15:17:00 +07:00 committed by GitHub
parent 40213c957f
commit d8402eaf67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 4 deletions

View File

@ -979,24 +979,28 @@ mod tests {
content: Some("Hi!".to_string()), content: Some("Hi!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("Hello how can I help?".to_string()), content: Some("Hello how can I help?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("What is Deep Learning?".to_string()), content: Some("What is Deep Learning?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("magic!".to_string()), content: Some("magic!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
], ],
bos_token: Some("[BOS]"), bos_token: Some("[BOS]"),
@ -1049,30 +1053,35 @@ mod tests {
content: Some("Hi!".to_string()), content: Some("Hi!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("Hi again!".to_string()), content: Some("Hi again!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("Hello how can I help?".to_string()), content: Some("Hello how can I help?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("What is Deep Learning?".to_string()), content: Some("What is Deep Learning?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("magic!".to_string()), content: Some("magic!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
], ],
bos_token: Some("[BOS]"), bos_token: Some("[BOS]"),
@ -1130,24 +1139,28 @@ mod tests {
content: Some("Hi!".to_string()), content: Some("Hi!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("Hello how can I help?".to_string()), content: Some("Hello how can I help?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("What is Deep Learning?".to_string()), content: Some("What is Deep Learning?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("magic!".to_string()), content: Some("magic!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
], ],
bos_token: Some("[BOS]"), bos_token: Some("[BOS]"),
@ -1189,24 +1202,28 @@ mod tests {
content: Some("Hi!".to_string()), content: Some("Hi!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("Hello how can I help?".to_string()), content: Some("Hello how can I help?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("What is Deep Learning?".to_string()), content: Some("What is Deep Learning?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("magic!".to_string()), content: Some("magic!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
], ],
bos_token: Some("[BOS]"), bos_token: Some("[BOS]"),
@ -1234,18 +1251,21 @@ mod tests {
content: Some("Hello, how are you?".to_string()), content: Some("Hello, how are you?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "assistant".to_string(), role: "assistant".to_string(),
content: Some("I'm doing great. How can I help you today?".to_string()), content: Some("I'm doing great. How can I help you today?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("I'd like to show off how chat templating works!".to_string()), content: Some("I'd like to show off how chat templating works!".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
]; ];
@ -1257,6 +1277,7 @@ mod tests {
), ),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}] }]
.iter() .iter()
.chain(&example_chat) .chain(&example_chat)
@ -1401,12 +1422,14 @@ mod tests {
content: Some("You are a friendly chatbot who always responds in the style of a pirate".to_string()), content: Some("You are a friendly chatbot who always responds in the style of a pirate".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
Message { Message {
role: "user".to_string(), role: "user".to_string(),
content: Some("How many helicopters can a human eat in one sitting?".to_string()), content: Some("How many helicopters can a human eat in one sitting?".to_string()),
name: None, name: None,
tool_calls: None, tool_calls: None,
tool_call_id: None,
}, },
], ],
add_generation_prompt: true, add_generation_prompt: true,

View File

@ -546,6 +546,7 @@ impl ChatCompletion {
content: output, content: output,
name: None, name: None,
tool_calls, tool_calls,
tool_call_id: None,
}, },
logprobs: return_logprobs logprobs: return_logprobs
.then(|| ChatCompletionLogprobs::from((details.tokens, details.top_tokens))), .then(|| ChatCompletionLogprobs::from((details.tokens, details.top_tokens))),
@ -881,7 +882,7 @@ pub(crate) struct ChatTemplateInputs<'a> {
#[derive(Clone, Deserialize, Serialize, ToSchema, Default, Debug)] #[derive(Clone, Deserialize, Serialize, ToSchema, Default, Debug)]
pub(crate) struct ToolCall { pub(crate) struct ToolCall {
pub id: u32, pub id: String,
pub r#type: String, pub r#type: String,
pub function: FunctionDefinition, pub function: FunctionDefinition,
} }
@ -954,13 +955,16 @@ pub(crate) struct Message {
pub role: String, pub role: String,
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
#[schema(example = "My name is David and I")] #[schema(example = "My name is David and I")]
#[serde(deserialize_with = "message_content_serde::deserialize")] #[serde(default, deserialize_with = "message_content_serde::deserialize")]
pub content: Option<String>, pub content: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
#[schema(example = "\"David\"")] #[schema(example = "\"David\"")]
pub name: Option<String>, pub name: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")] #[serde(default, skip_serializing_if = "Option::is_none")]
pub tool_calls: Option<Vec<ToolCall>>, pub tool_calls: Option<Vec<ToolCall>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
#[schema(example = "\"get_weather\"")]
pub tool_call_id: Option<String>,
} }
#[derive(Clone, Debug, Deserialize, ToSchema)] #[derive(Clone, Debug, Deserialize, ToSchema)]

View File

@ -988,7 +988,6 @@ async fn chat_completions(
) -> Result<Response, (StatusCode, Json<ErrorResponse>)> { ) -> Result<Response, (StatusCode, Json<ErrorResponse>)> {
let span = tracing::Span::current(); let span = tracing::Span::current();
metrics::increment_counter!("tgi_request_count"); metrics::increment_counter!("tgi_request_count");
let ChatRequest { let ChatRequest {
logprobs, logprobs,
max_tokens, max_tokens,
@ -1160,7 +1159,7 @@ async fn chat_completions(
) )
})?; })?;
let tool_calls = vec![ToolCall { let tool_calls = vec![ToolCall {
id: 0, id: "0".to_string(),
r#type: "function".to_string(), r#type: "function".to_string(),
function: FunctionDefinition { function: FunctionDefinition {
description: None, description: None,