-
Notifications
You must be signed in to change notification settings - Fork 486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check server input #2719
Check server input #2719
Changes from 2 commits
3e257de
ad0ea23
9d3face
91504e2
a6a9a3b
ddeec0e
c4c4b7f
efc2599
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,22 +12,23 @@ | |
from fastapi.middleware.cors import CORSMiddleware | ||
from fastapi.responses import JSONResponse, Response, StreamingResponse | ||
from fastapi.security.http import HTTPAuthorizationCredentials, HTTPBearer | ||
from pydantic import ValidationError | ||
|
||
from lmdeploy.archs import get_task | ||
from lmdeploy.messages import (GenerationConfig, LogitsProcessor, | ||
PytorchEngineConfig, TurbomindEngineConfig) | ||
from lmdeploy.model import ChatTemplateConfig | ||
from lmdeploy.serve.async_engine import AsyncEngine | ||
from lmdeploy.serve.openai.protocol import ( # noqa: E501 | ||
ChatCompletionRequest, ChatCompletionResponse, | ||
ChatCompletionResponseChoice, ChatCompletionResponseStreamChoice, | ||
ChatCompletionStreamResponse, ChatCompletionTokenLogprob, ChatMessage, | ||
ChoiceLogprobs, CompletionRequest, CompletionResponse, | ||
CompletionResponseChoice, CompletionResponseStreamChoice, | ||
CompletionStreamResponse, DeltaMessage, EmbeddingsRequest, EncodeRequest, | ||
EncodeResponse, ErrorResponse, FunctionResponse, GenerateRequest, | ||
GenerateResponse, LogProbs, ModelCard, ModelList, ModelPermission, | ||
ToolCall, TopLogprob, UsageInfo) | ||
ChatCompletionRequest, ChatCompletionRequestMessage, | ||
ChatCompletionResponse, ChatCompletionResponseChoice, | ||
ChatCompletionResponseStreamChoice, ChatCompletionStreamResponse, | ||
ChatCompletionTokenLogprob, ChatMessage, ChoiceLogprobs, CompletionRequest, | ||
CompletionResponse, CompletionResponseChoice, | ||
CompletionResponseStreamChoice, CompletionStreamResponse, DeltaMessage, | ||
EmbeddingsRequest, EncodeRequest, EncodeResponse, ErrorResponse, | ||
FunctionResponse, GenerateRequest, GenerateResponse, LogProbs, ModelCard, | ||
ModelList, ModelPermission, ToolCall, TopLogprob, UsageInfo) | ||
from lmdeploy.tokenizer import DetokenizeState, Tokenizer | ||
from lmdeploy.utils import get_logger | ||
|
||
|
@@ -334,6 +335,13 @@ async def chat_completions_v1(request: ChatCompletionRequest, | |
error_check_ret = await check_request(request) | ||
if error_check_ret is not None: | ||
return error_check_ret | ||
try: | ||
_ = ChatCompletionRequestMessage(messages=request.messages) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can just replace the type hint https://github.com/irexyc/lmdeploy/blob/cc142150780351aebd9dac00539cd74e76d7a369/lmdeploy/serve/openai/protocol.py#L113 . It will check if it is valid itself. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The messages will converted to list of class if replace the type hint, however the messages2prompt function needs the messages to be list of dict. |
||
except ValidationError as error: | ||
return create_error_response( | ||
HTTPStatus.BAD_REQUEST, | ||
f'Invalid input, input={request.messages}, error={error}') | ||
|
||
if VariableInterface.async_engine.id2step.get(str(request.session_id), | ||
0) != 0: | ||
return create_error_response( | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -114,7 +114,7 @@ class ChatCompletionRequest(BaseModel): | |
temperature: Optional[float] = 0.7 | ||
top_p: Optional[float] = 1.0 | ||
tools: Optional[List[Tool]] = Field(default=None, examples=[None]) | ||
tool_choice: Union[ToolChoice, Literal['auto', 'required','none']] = Field(default='auto', examples=['none']) # noqa | ||
tool_choice: Union[ToolChoice, Literal['auto', 'required', 'none']] = Field(default='auto', examples=['none']) # noqa | ||
logprobs: Optional[bool] = False | ||
top_logprobs: Optional[int] = None | ||
n: Optional[int] = 1 | ||
|
@@ -139,6 +139,45 @@ class ChatCompletionRequest(BaseModel): | |
seed: Optional[int] = None | ||
|
||
|
||
class ContentPartTextParam(BaseModel): | ||
type: Literal['text'] | ||
text: str | ||
|
||
|
||
class ImageURL(BaseModel): | ||
url: str | ||
|
||
|
||
class ContentPartImageParam(BaseModel): | ||
type: Literal['image_url'] | ||
image_url: ImageURL | ||
|
||
|
||
ContentPartParam = Union[ContentPartTextParam, ContentPartImageParam] | ||
|
||
|
||
class AssistantMessage(BaseModel): | ||
role: Literal['assistant'] | ||
content: Union[str, List[ContentPartTextParam]] | ||
|
||
|
||
class SystemMessage(BaseModel): | ||
role: Literal['system'] | ||
content: Union[str, List[ContentPartTextParam]] | ||
|
||
|
||
class UserMessage(BaseModel): | ||
role: Literal['user'] | ||
content: Union[str, List[ContentPartParam]] | ||
|
||
|
||
ChatCompletionMessage = Union[SystemMessage, UserMessage, AssistantMessage] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is the best way to validate them. There are also other roles like |
||
|
||
|
||
class ChatCompletionRequestMessage(BaseModel): | ||
messages: Union[str, List[ChatCompletionMessage]] | ||
|
||
|
||
class FunctionResponse(BaseModel): | ||
"""Function response.""" | ||
name: str | ||
|
@@ -240,7 +279,6 @@ class CompletionRequest(BaseModel): | |
stream_options: Optional[StreamOptions] = Field(default=None, | ||
examples=[None]) | ||
top_p: Optional[float] = 1.0 | ||
logprobs: Optional[int] = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is is as expected? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there is a duplicated |
||
echo: Optional[bool] = False | ||
presence_penalty: Optional[float] = 0.0 | ||
frequency_penalty: Optional[float] = 0.0 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import pytest | ||
from pydantic import ValidationError | ||
|
||
from lmdeploy.serve.openai.protocol import ChatCompletionRequestMessage | ||
|
||
|
||
def test_single_str_input(): | ||
messages = 'hello' | ||
_ = ChatCompletionRequestMessage(messages=messages) | ||
|
||
|
||
@pytest.mark.parametrize('role', ['system', 'user', 'assistant']) | ||
def test_list_str_input(role): | ||
content = 'hello' | ||
messages = [dict(role=role, content=content)] | ||
_ = ChatCompletionRequestMessage(messages=messages) | ||
|
||
|
||
@pytest.mark.parametrize('role', ['system', 'user', 'assistant']) | ||
def test_list_content_input(role): | ||
content = [dict(type='text', text='hello')] | ||
messages = [dict(role=role, content=content)] | ||
_ = ChatCompletionRequestMessage(messages=messages) | ||
|
||
|
||
def test_user_image_input(): | ||
content = [dict(type='image_url', image_url=dict(url='xxx'))] | ||
messages = [dict(role='user', content=content)] | ||
_ = ChatCompletionRequestMessage(messages=messages) | ||
|
||
|
||
@pytest.mark.parametrize('role', ['system', 'assistant']) | ||
def test_system_assistant_image_input(role): | ||
content = [dict(type='image_url', image_url=dict(url='xxx'))] | ||
messages = [dict(role=role, content=content)] | ||
with pytest.raises(ValidationError): | ||
_ = ChatCompletionRequestMessage(messages=messages) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it for the GPT4V messages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the content part could be str or ChatCompletionContentPartTextParam