Skip to content

Commit

Permalink
Update multi-modal support and platform compatibility (#25)
Browse files Browse the repository at this point in the history
Co-authored-by: wangyuxin <[email protected]>
  • Loading branch information
wangyuxinwhy and wangyuxin authored Feb 5, 2024
1 parent d54299a commit 5bbc5f0
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 12 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ Generate Package 允许用户通过统一的 api 访问跨平台的生成式模

## Features

* **多模态**,支持文本生成,图像生成以及语音生成
* **跨平台**,完整支持 OpenAI,Azure,Minimax 在内的国内外多家平台
* **One API**,统一了不同平台的消息格式,推理参数,接口封装,返回解析
* **多模态**,支持文本生成,多模态文本生成,结构体生成,图像生成,语音生成...
* **跨平台**,完整支持 OpenAI,Azure,Minimax,智谱,文心一言 在内的国内外多家平台
* **One API**,统一了不同平台的消息格式,推理参数,接口封装,返回解析,让用户无需关心不同平台的差异
* **异步和流式**,提供流式调用,非流式调用,同步调用,异步调用,异步批量调用,适配不同的应用场景
* **自带电池**,提供输入检查,参数检查,计费,*ChatEngine*, *Limit*, *Structure*, *function* 等功能
* **自带电池**,提供输入检查,参数检查,计费,速率控制,*ChatEngine*, *function call* 等功能
* **高质量代码**,100% typehints,pylance strict, ruff lint & format, test coverage > 85% ...

> 完整支持是指,只要是平台提供的功能和参数,`generate` 包都原生支持,不打折扣!比如,OpenAI 的 Function Call, Tool Calls,MinimaxPro 的 Plugins 等
Expand Down
2 changes: 2 additions & 0 deletions generate/chat_completion/message/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
AssistantMessage,
FunctionCall,
FunctionMessage,
ImagePart,
ImageUrl,
ImageUrlPart,
Message,
Expand Down Expand Up @@ -32,6 +33,7 @@
'ensure_messages',
'FunctionCall',
'FunctionMessage',
'ImagePart',
'Message',
'Messages',
'Prompt',
Expand Down
7 changes: 6 additions & 1 deletion generate/chat_completion/message/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,14 @@ class ImageUrlPart(BaseModel):
image_url: ImageUrl


class ImagePart(BaseModel):
image: bytes
image_format: Optional[str] = None


class UserMultiPartMessage(Message):
role: Literal['user'] = 'user'
content: List[Union[TextPart, ImageUrlPart]]
content: List[Union[TextPart, ImageUrlPart, ImagePart]]


class FunctionMessage(Message):
Expand Down
2 changes: 1 addition & 1 deletion generate/chat_completion/models/dashscope.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ def _convert_message_to_multimodal_chat_message(message: Message) -> DashScopeMu
elif isinstance(part, ImageUrlPart):
content.append({'image': part.image_url.url})
else:
raise TypeError(f'Unknown part type: {part}')
raise TypeError(f'Unsupported part type: {part}')
return {'role': 'user', 'content': content}
allowed_message_type = (UserMessage, AssistantMessage, SystemMessage, UserMultiPartMessage)
raise MessageTypeError(message, allowed_message_type=allowed_message_type)
Expand Down
17 changes: 12 additions & 5 deletions generate/chat_completion/models/openai.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import base64
import json
from functools import partial
from typing import Any, AsyncIterator, Callable, ClassVar, Dict, Iterator, List, Literal, Optional, Type, Union, cast
Expand All @@ -13,6 +14,7 @@
AssistantMessage,
FunctionCall,
FunctionMessage,
ImagePart,
Message,
Messages,
MessageTypeError,
Expand Down Expand Up @@ -123,14 +125,19 @@ def _to_user_multipart_message_dict(message: UserMultiPartMessage) -> OpenAIMess
if isinstance(part, TextPart):
content.append({'type': 'text', 'text': part.text})
else:
if isinstance(part, ImagePart):
image_format = part.image_format or 'png'
url: str = f'data:image/{image_format};base64,{base64.b64encode(part.image).decode()}'
image_url_dict = {'url': url}
else:
image_url_dict = {}
image_url_dict['url'] = part.image_url.url
if part.image_url.detail:
image_url_dict['detail'] = part.image_url.detail
image_url_part_dict: dict[str, Any] = {
'type': 'image_url',
'image_url': {
'url': part.image_url.url,
},
'image_url': image_url_dict,
}
if part.image_url.detail:
image_url_part_dict['image_url']['detail'] = part.image_url.detail
content.append(image_url_part_dict)
return {
'role': 'user',
Expand Down
15 changes: 14 additions & 1 deletion generate/chat_completion/models/zhipu.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import base64
import json
from typing import Any, AsyncIterator, ClassVar, Dict, Iterator, List, Literal, Optional, Union

Expand All @@ -10,17 +11,20 @@
from generate.chat_completion.message import (
AssistantMessage,
FunctionCall,
ImagePart,
ImageUrlPart,
Message,
Messages,
MessageTypeError,
Prompt,
SystemMessage,
TextPart,
ToolCall,
ToolMessage,
UserMessage,
UserMultiPartMessage,
ensure_messages,
)
from generate.chat_completion.message.core import ImageUrlPart, TextPart, ToolMessage
from generate.chat_completion.model_output import ChatCompletionOutput, ChatCompletionStreamOutput, Stream
from generate.http import (
HttpClient,
Expand Down Expand Up @@ -140,6 +144,15 @@ def convert_to_zhipu_message(message: Message) -> ZhipuMessage:
},
}
)
elif isinstance(part, ImagePart):
content.append(
{
'type': 'image_url',
'image_url': {
'url': base64.b64encode(part.image).decode(),
},
}
)
return {'role': 'user', 'content': content}

if isinstance(message, AssistantMessage):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ ignore = [
"PLR0913", # Too many arguments in function definition
"TRY003", # Avoid specifying long messages outside the exception class
"PLC0414", # reimport
'PLR0912', # too many branches
]
exclude = ["playground", "api_docs"]
target-version = "py38"
Expand Down

0 comments on commit 5bbc5f0

Please sign in to comment.