client
client copied to clipboard
Undefined array key "content" (MS OpenAI Content Filtering issue)
When using using the Azure OpenAI API, if content filtering is kicked off an error is returned Undefined array key "content"
as there is no content parameter in the array within CreateResponseMessage.php
/**
* @param array{role: string, content: ?string, function_call: ?array{name: string, arguments: string}} $attributes
*/
public static function from(array $attributes): self
{
return new self(
$attributes['role'],
$attributes['content'],
isset($attributes['function_call']) ? CreateResponseFunctionCall::from($attributes['function_call']) : null,
);
}
The choices array looks something like this,
"choices": [
{
"index": 0,
"finish_reason": "content_filter",
"message": {
"role": "assistant"
},
"content_filter_results": {
"hate": {
"filtered": false,
"severity": "safe"
},
"self_harm": {
"filtered": false,
"severity": "safe"
},
"sexual": {
"filtered": true,
"severity": "medium"
},
"violence": {
"filtered": false,
"severity": "safe"
}
}
}
],
That example above has the "sexual" filter triggered, hence why there is no content back from the assistant.
It would be great if this lib handled the content filtering issues (e.g. threw an exception with a message etc)
Hi @chrisrickard
Could you provide a path to replicate this issue? Maybe an example prompt leading to this behaviour?
Looks like have of the problem has been fixed here: https://github.com/openai-php/client/pull/184
But the content_filter_results
will not be available through this library. Therefore your prompts would still be helpful.
hey @gehrisandro ah nice pickup, that PR should at least stop the error from being thrown.
Annoyingly I cannot seem to find an example prompt that replicated this behaviour without exposing my very large (private) prompt I'm afraid,
Most times I try and force the content filter I get back:
{
"error": {
"message": "The response was filtered due to the prompt triggering Azure OpenAI’s content management policy. Please modify your prompt and retry. To learn more about our content filtering policies please read our documentation: https://go.microsoft.com/fwlink/?linkid=2198766",
"type": null,
"param": "prompt",
"code": "content_filter",
"status": 400,
"innererror": {
"code": "ResponsibleAIPolicyViolation",
"content_filter_result": {
"hate": {
"filtered": false,
"severity": "safe"
},
"self_harm": {
"filtered": false,
"severity": "safe"
},
"sexual": {
"filtered": true,
"severity": "medium"
},
"violence": {
"filtered": false,
"severity": "safe"
}
}
}
}
}
But that's fine, as the lib correctly throws an exception with that error.
However with my specific prompt (sorry I cannot supply this), I simply get
{
"id": "chatcmpl-7shSxtAcFghboE1TxuEjr4MZDYtNc",
"object": "chat.completion",
"created": 1693271151,
"model": "gpt-4",
"prompt_annotations": [
{
"prompt_index": 0,
"content_filter_results": {
"hate": {
"filtered": false,
"severity": "safe"
},
"self_harm": {
"filtered": false,
"severity": "safe"
},
"sexual": {
"filtered": false,
"severity": "safe"
},
"violence": {
"filtered": false,
"severity": "safe"
}
}
}
],
"choices": [
{
"index": 0,
"finish_reason": "content_filter",
"message": {
"role": "assistant"
},
"content_filter_results": {
"hate": {
"filtered": false,
"severity": "safe"
},
"self_harm": {
"filtered": false,
"severity": "safe"
},
"sexual": {
"filtered": true,
"severity": "medium"
},
"violence": {
"filtered": false,
"severity": "safe"
}
}
}
],
"usage": {
"completion_tokens": 2277,
"prompt_tokens": 3034,
"total_tokens": 5311
}
}
Hi @chrisrickard
Thank you for the information provided. I fully understand that you are not able to share everything with us.
I took a bit deeper look into the Azure stuff now, because I've never worked with Azure so far.
For me it looks like there are various things on the Azure API not available through the regular OpenAI API. For example this prompt_annotations
is only visible in the latest preview of the Azure documentation: https://github.com/Azure/azure-rest-api-specs/blob/0762e82bcccef4a032e29dda5e4c07fd7cc822a6/specification/cognitiveservices/data-plane/AzureOpenAI/inference/preview/2023-08-01-preview/generated.json#L607
Do you or anyone else know more about the way Azure and OpenAI are behaving together? Will the APIs stay to be consistent where one of them is sometimes updated earlier then the other or are they going to divert more and more? The reason I am asking is, because I am not sure if we should implement support for this "Azure only" features within this package or if we should build a separate package for Azure (extending this library).
Hi @gehrisandro, that's a good question - I know OpenAI and MS have a partnership, and I hazard a guess that is because MS has invested 18+Billion, but I don't know if the API's will stay in sync etc.
I know that the Azure Open AI Offering is currently more of an enterprise play, and offers some more compliance than OpenAI for larger companies - and I believe the content filter is one of these.
Whether OpenAI will also integrate this into their API's I'm not sure.
So as you say, it may make sense to have a separate repo that augments the core functionality with Azure? 🤷♂️
Hi @chrisrickard
Thanks for your response.
I will leave this issue open and try to figure out some more information about OpenAI and Azure.
This can also be reproduced directly with OpenAI credentials, without azure:
$client = $container->get(\OpenAI\Client::class);
$client->chat()->create([
'model' => 'gpt-4-0613',
'messages' => [['role' => 'system', 'content' => 'call my_function']],
'functions' => [['name' => 'my_function', 'parameters' => ['type' => 'object', 'properties' => (object)[]]]],
'function_call' => ['name' => 'my_function'],
]);
And here is a var_dump
of $result
, at the start of the response processing code here:
$response = $this->transporter->requestStream($payload);
return new StreamResponse(CreateStreamedResponse::class, $response);
$response = [
'id' => 'chatcmpl-xxxxxxx',
'object' => 'chat.completion',
'created' => 1697598503,
'model' => 'gpt-4-0613',
'choices' => [
[
'index' => 0,
'message' => [
'role' => 'assistant',
'content' => null,
'function_call' => [
'name' => 'my_function',
'arguments' => '{}',
],
],
'finish_reason' => 'stop',
],
],
'usage' => [
'prompt_tokens' => 37,
'completion_tokens' => 1,
'total_tokens' => 38,
],
];
@Sam152 I ran your code but I don't know, what you mean by that. Could you please explain what exactly you can reproduce?