Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
OpenDAS
vllm_cscc
Commits
d81abefd
Unverified
Commit
d81abefd
authored
Aug 24, 2024
by
Tyler Rockwood
Committed by
GitHub
Aug 23, 2024
Browse files
[Frontend] add json_schema support from OpenAI protocol (#7654)
parent
8da48e4d
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
59 additions
and
2 deletions
+59
-2
tests/entrypoints/openai/test_chat.py
tests/entrypoints/openai/test_chat.py
+33
-0
vllm/entrypoints/openai/protocol.py
vllm/entrypoints/openai/protocol.py
+12
-2
vllm/model_executor/guided_decoding/lm_format_enforcer_decoding.py
...l_executor/guided_decoding/lm_format_enforcer_decoding.py
+7
-0
vllm/model_executor/guided_decoding/outlines_decoding.py
vllm/model_executor/guided_decoding/outlines_decoding.py
+7
-0
No files found.
tests/entrypoints/openai/test_chat.py
View file @
d81abefd
...
@@ -837,6 +837,39 @@ async def test_response_format_json_object(client: openai.AsyncOpenAI):
...
@@ -837,6 +837,39 @@ async def test_response_format_json_object(client: openai.AsyncOpenAI):
assert
loaded
==
{
"result"
:
2
},
loaded
assert
loaded
==
{
"result"
:
2
},
loaded
@
pytest
.
mark
.
asyncio
async
def
test_response_format_json_schema
(
client
:
openai
.
AsyncOpenAI
):
for
_
in
range
(
2
):
resp
=
await
client
.
chat
.
completions
.
create
(
model
=
MODEL_NAME
,
messages
=
[{
"role"
:
"user"
,
"content"
:
(
'what is 1+1? please respond with a JSON object, '
'the format is {"result": 2}'
)
}],
response_format
=
{
"type"
:
"json_schema"
,
"json_schema"
:
{
"name"
:
"foo_test"
,
"schema"
:
{
"type"
:
"object"
,
"properties"
:
{
"result"
:
{
"type"
:
"integer"
},
},
},
}
})
content
=
resp
.
choices
[
0
].
message
.
content
assert
content
is
not
None
loaded
=
json
.
loads
(
content
)
assert
loaded
==
{
"result"
:
2
},
loaded
@
pytest
.
mark
.
asyncio
@
pytest
.
mark
.
asyncio
async
def
test_extra_fields
(
client
:
openai
.
AsyncOpenAI
):
async
def
test_extra_fields
(
client
:
openai
.
AsyncOpenAI
):
with
pytest
.
raises
(
BadRequestError
)
as
exc_info
:
with
pytest
.
raises
(
BadRequestError
)
as
exc_info
:
...
...
vllm/entrypoints/openai/protocol.py
View file @
d81abefd
...
@@ -85,9 +85,19 @@ class UsageInfo(OpenAIBaseModel):
...
@@ -85,9 +85,19 @@ class UsageInfo(OpenAIBaseModel):
completion_tokens
:
Optional
[
int
]
=
0
completion_tokens
:
Optional
[
int
]
=
0
class
JsonSchemaResponseFormat
(
OpenAIBaseModel
):
name
:
str
description
:
Optional
[
str
]
=
None
# schema is the field in openai but that causes conflicts with pydantic so
# instead use json_schema with an alias
json_schema
:
Optional
[
Dict
[
str
,
Any
]]
=
Field
(
default
=
None
,
alias
=
'schema'
)
strict
:
Optional
[
bool
]
=
None
class
ResponseFormat
(
OpenAIBaseModel
):
class
ResponseFormat
(
OpenAIBaseModel
):
# type must be "json_object" or "text"
# type must be "json_schema", "json_object" or "text"
type
:
Literal
[
"text"
,
"json_object"
]
type
:
Literal
[
"text"
,
"json_object"
,
"json_schema"
]
json_schema
:
Optional
[
JsonSchemaResponseFormat
]
=
None
class
StreamOptions
(
OpenAIBaseModel
):
class
StreamOptions
(
OpenAIBaseModel
):
...
...
vllm/model_executor/guided_decoding/lm_format_enforcer_decoding.py
View file @
d81abefd
...
@@ -49,6 +49,13 @@ async def get_lm_format_enforcer_guided_decoding_logits_processor(
...
@@ -49,6 +49,13 @@ async def get_lm_format_enforcer_guided_decoding_logits_processor(
and
request
.
response_format
.
type
==
"json_object"
):
and
request
.
response_format
.
type
==
"json_object"
):
character_level_parser
=
JsonSchemaParser
(
character_level_parser
=
JsonSchemaParser
(
None
)
# None means any json object
None
)
# None means any json object
elif
(
request
.
response_format
is
not
None
and
request
.
response_format
.
type
==
"json_schema"
and
request
.
response_format
.
json_schema
is
not
None
and
request
.
response_format
.
json_schema
.
json_schema
is
not
None
):
schema
=
_normalize_json_schema_object
(
request
.
response_format
.
json_schema
.
json_schema
)
character_level_parser
=
JsonSchemaParser
(
schema
)
else
:
else
:
return
None
return
None
...
...
vllm/model_executor/guided_decoding/outlines_decoding.py
View file @
d81abefd
...
@@ -127,6 +127,13 @@ def _get_guide_and_mode(
...
@@ -127,6 +127,13 @@ def _get_guide_and_mode(
and
request
.
response_format
is
not
None
and
request
.
response_format
is
not
None
and
request
.
response_format
.
type
==
"json_object"
):
and
request
.
response_format
.
type
==
"json_object"
):
return
JSON_GRAMMAR
,
GuidedDecodingMode
.
GRAMMAR
return
JSON_GRAMMAR
,
GuidedDecodingMode
.
GRAMMAR
elif
(
not
isinstance
(
request
,
GuidedDecodingRequest
)
and
request
.
response_format
is
not
None
and
request
.
response_format
.
type
==
"json_schema"
and
request
.
response_format
.
json_schema
is
not
None
and
request
.
response_format
.
json_schema
.
json_schema
is
not
None
):
json
=
json_dumps
(
request
.
response_format
.
json_schema
.
json_schema
)
return
json
,
GuidedDecodingMode
.
JSON
else
:
else
:
return
None
,
None
return
None
,
None
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment