chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
from .conversation import Conversation, History, HistoryItem
|
||||
from .generation import Generation, AioGeneration
|
||||
from .image_synthesis import ImageSynthesis, AioImageSynthesis
|
||||
from .multimodal_conversation import MultiModalConversation, AioMultiModalConversation
|
||||
from .video_synthesis import VideoSynthesis, AioVideoSynthesis
|
||||
|
||||
__all__ = [
|
||||
Generation,
|
||||
AioGeneration,
|
||||
Conversation,
|
||||
HistoryItem,
|
||||
History,
|
||||
ImageSynthesis,
|
||||
AioImageSynthesis,
|
||||
MultiModalConversation,
|
||||
AioMultiModalConversation,
|
||||
VideoSynthesis,
|
||||
AioVideoSynthesis,
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,282 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
import json
|
||||
from typing import Any, Dict, Generator, List, Union
|
||||
|
||||
import dashscope
|
||||
from dashscope.aigc.generation import Generation
|
||||
from dashscope.api_entities.chat_completion_types import (ChatCompletion,
|
||||
ChatCompletionChunk)
|
||||
from dashscope.api_entities.dashscope_response import (GenerationResponse,
|
||||
Message)
|
||||
from dashscope.client.base_api import BaseAioApi, CreateMixin
|
||||
from dashscope.common.error import InputRequired, ModelRequired
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
|
||||
|
||||
class Completions(CreateMixin):
|
||||
"""Support openai compatible chat completion interface.
|
||||
|
||||
"""
|
||||
SUB_PATH = ''
|
||||
|
||||
@classmethod
|
||||
def create(
|
||||
cls,
|
||||
*,
|
||||
model: str,
|
||||
messages: List[Message],
|
||||
stream: bool = False,
|
||||
temperature: float = None,
|
||||
top_p: float = None,
|
||||
top_k: int = None,
|
||||
stop: Union[List[str], List[List[int]]] = None,
|
||||
max_tokens: int = None,
|
||||
repetition_penalty: float = None,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
extra_headers: Dict = None,
|
||||
extra_body: Dict = None,
|
||||
**kwargs
|
||||
) -> Union[ChatCompletion, Generator[ChatCompletionChunk, None, None]]:
|
||||
"""Call openai compatible chat completion model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as qwen-long
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[{'role': 'user',
|
||||
'content': 'The weather is fine today.'},
|
||||
{'role': 'assistant', 'content': 'Suitable for outings'}]
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
temperature(float, `optional`): Used to control the degree
|
||||
of randomness and diversity. Specifically, the temperature
|
||||
value controls the degree to which the probability distribution
|
||||
of each candidate word is smoothed when generating text.
|
||||
A higher temperature value will reduce the peak value of
|
||||
the probability, allowing more low-probability words to be
|
||||
selected, and the generated results will be more diverse;
|
||||
while a lower temperature value will enhance the peak value
|
||||
of the probability, making it easier for high-probability
|
||||
words to be selected, the generated results are more
|
||||
deterministic.
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered.
|
||||
top_k(int, `optional`): The size of the sample candidate set when generated. # noqa E501
|
||||
For example, when the value is 50, only the 50 highest-scoring tokens # noqa E501
|
||||
in a single generation form a randomly sampled candidate set. # noqa E501
|
||||
The larger the value, the higher the randomness generated; # noqa E501
|
||||
the smaller the value, the higher the certainty generated. # noqa E501
|
||||
The default value is 0, which means the top_k policy is # noqa E501
|
||||
not enabled. At this time, only the top_p policy takes effect. # noqa E501
|
||||
stop(list[str] or list[list[int]], `optional`): Used to control the generation to stop # noqa E501
|
||||
when encountering setting str or token ids, the result will not include # noqa E501
|
||||
stop words or tokens.
|
||||
max_tokens(int, `optional`): The maximum token num expected to be output. It should be # noqa E501
|
||||
noted that the length generated by the model will only be less than max_tokens, # noqa E501
|
||||
not necessarily equal to it. If max_tokens is set too large, the service will # noqa E501
|
||||
directly prompt that the length exceeds the limit. It is generally # noqa E501
|
||||
not recommended to set this value.
|
||||
repetition_penalty(float, `optional`): Used to control the repeatability when generating models. # noqa E501
|
||||
Increasing repetition_penalty can reduce the duplication of model generation. # noqa E501
|
||||
1.0 means no punishment.
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will get by default rule.
|
||||
workspace (str, optional): The bailian workspace id.
|
||||
**kwargs:
|
||||
timeout: set request timeout.
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[ChatCompletion,
|
||||
Generator[ChatCompletionChunk, None, None]]: If
|
||||
stream is True, return Generator, otherwise ChatCompletion.
|
||||
"""
|
||||
if messages is None or not messages:
|
||||
raise InputRequired('Messages is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
data = {}
|
||||
data['model'] = model
|
||||
data['messages'] = messages
|
||||
if temperature is not None:
|
||||
data['temperature'] = temperature
|
||||
if top_p is not None:
|
||||
data['top_p'] = top_p
|
||||
if top_k is not None:
|
||||
data['top_k'] = top_k
|
||||
if stop is not None:
|
||||
data['stop'] = stop
|
||||
if max_tokens is not None:
|
||||
data[max_tokens] = max_tokens
|
||||
if repetition_penalty is not None:
|
||||
data['repetition_penalty'] = repetition_penalty
|
||||
if extra_body is not None and extra_body:
|
||||
data = {**data, **extra_body}
|
||||
|
||||
if extra_headers is not None and extra_headers:
|
||||
kwargs = {
|
||||
'headers': extra_headers
|
||||
} if kwargs else {
|
||||
**kwargs,
|
||||
**{
|
||||
'headers': extra_headers
|
||||
}
|
||||
}
|
||||
|
||||
response = super().call(data=data,
|
||||
path='chat/completions',
|
||||
base_address=dashscope.base_compatible_api_url,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
stream=stream,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
if stream:
|
||||
return (ChatCompletionChunk(**item) for _, item in response)
|
||||
else:
|
||||
return ChatCompletion(**response)
|
||||
|
||||
|
||||
class AioGeneration(BaseAioApi):
|
||||
task = 'text-generation'
|
||||
"""API for AI-Generated Content(AIGC) models.
|
||||
|
||||
"""
|
||||
class Models:
|
||||
"""@deprecated, use qwen_turbo instead"""
|
||||
qwen_v1 = 'qwen-v1'
|
||||
"""@deprecated, use qwen_plus instead"""
|
||||
qwen_plus_v1 = 'qwen-plus-v1'
|
||||
|
||||
bailian_v1 = 'bailian-v1'
|
||||
dolly_12b_v2 = 'dolly-12b-v2'
|
||||
qwen_turbo = 'qwen-turbo'
|
||||
qwen_plus = 'qwen-plus'
|
||||
qwen_max = 'qwen-max'
|
||||
|
||||
@classmethod
|
||||
async def call(
|
||||
cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
history: list = None,
|
||||
api_key: str = None,
|
||||
messages: List[Message] = None,
|
||||
plugins: Union[str, Dict[str, Any]] = None,
|
||||
workspace: str = None,
|
||||
**kwargs
|
||||
) -> Union[GenerationResponse, Generator[GenerationResponse, None, None]]:
|
||||
"""Call generation model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as qwen-turbo
|
||||
prompt (Any): The input prompt.
|
||||
history (list):The user provided history, deprecated
|
||||
examples:
|
||||
[{'user':'The weather is fine today.',
|
||||
'bot': 'Suitable for outings'}].
|
||||
Defaults to None.
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will get by default rule(TODO: api key doc).
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[{'role': 'user',
|
||||
'content': 'The weather is fine today.'},
|
||||
{'role': 'assistant', 'content': 'Suitable for outings'}]
|
||||
plugins (Any): The plugin config. Can be plugins config str, or dict.
|
||||
**kwargs:
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
temperature(float, `optional`): Used to control the degree
|
||||
of randomness and diversity. Specifically, the temperature
|
||||
value controls the degree to which the probability distribution
|
||||
of each candidate word is smoothed when generating text.
|
||||
A higher temperature value will reduce the peak value of
|
||||
the probability, allowing more low-probability words to be
|
||||
selected, and the generated results will be more diverse;
|
||||
while a lower temperature value will enhance the peak value
|
||||
of the probability, making it easier for high-probability
|
||||
words to be selected, the generated results are more
|
||||
deterministic, range(0, 2) .[qwen-turbo,qwen-plus].
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered[qwen-turbo,bailian-v1].
|
||||
top_k(int, `optional`): The size of the sample candidate set when generated. # noqa E501
|
||||
For example, when the value is 50, only the 50 highest-scoring tokens # noqa E501
|
||||
in a single generation form a randomly sampled candidate set. # noqa E501
|
||||
The larger the value, the higher the randomness generated; # noqa E501
|
||||
the smaller the value, the higher the certainty generated. # noqa E501
|
||||
The default value is 0, which means the top_k policy is # noqa E501
|
||||
not enabled. At this time, only the top_p policy takes effect. # noqa E501
|
||||
enable_search(bool, `optional`): Whether to enable web search(quark). # noqa E501
|
||||
Currently works best only on the first round of conversation.
|
||||
Default to False, support model: [qwen-turbo].
|
||||
customized_model_id(str, required) The enterprise-specific
|
||||
large model id, which needs to be generated from the
|
||||
operation background of the enterprise-specific
|
||||
large model product, support model: [bailian-v1].
|
||||
result_format(str, `optional`): [message|text] Set result result format. # noqa E501
|
||||
Default result is text
|
||||
incremental_output(bool, `optional`): Used to control the streaming output mode. # noqa E501
|
||||
If true, the subsequent output will include the previously input content. # noqa E501
|
||||
Otherwise, the subsequent output will not include the previously output # noqa E501
|
||||
content. Default false.
|
||||
stop(list[str] or list[list[int]], `optional`): Used to control the generation to stop # noqa E501
|
||||
when encountering setting str or token ids, the result will not include # noqa E501
|
||||
stop words or tokens.
|
||||
max_tokens(int, `optional`): The maximum token num expected to be output. It should be # noqa E501
|
||||
noted that the length generated by the model will only be less than max_tokens, # noqa E501
|
||||
not necessarily equal to it. If max_tokens is set too large, the service will # noqa E501
|
||||
directly prompt that the length exceeds the limit. It is generally # noqa E501
|
||||
not recommended to set this value.
|
||||
repetition_penalty(float, `optional`): Used to control the repeatability when generating models. # noqa E501
|
||||
Increasing repetition_penalty can reduce the duplication of model generation. # noqa E501
|
||||
1.0 means no punishment.
|
||||
workspace (str): The dashscope workspace id.
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[GenerationResponse,
|
||||
Generator[GenerationResponse, None, None]]: If
|
||||
stream is True, return Generator, otherwise GenerationResponse.
|
||||
"""
|
||||
if (prompt is None or not prompt) and (messages is None
|
||||
or not messages):
|
||||
raise InputRequired('prompt or messages is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, function = _get_task_group_and_task(__name__)
|
||||
if plugins is not None:
|
||||
headers = kwargs.pop('headers', {})
|
||||
if isinstance(plugins, str):
|
||||
headers['X-DashScope-Plugin'] = plugins
|
||||
else:
|
||||
headers['X-DashScope-Plugin'] = json.dumps(plugins)
|
||||
kwargs['headers'] = headers
|
||||
input, parameters = Generation._build_input_parameters(
|
||||
model, prompt, history, messages, **kwargs)
|
||||
response = await super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=Generation.task,
|
||||
function=function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**parameters)
|
||||
is_stream = kwargs.get('stream', False)
|
||||
if is_stream:
|
||||
return (GenerationResponse.from_api_response(rsp)
|
||||
async for rsp in response)
|
||||
else:
|
||||
return GenerationResponse.from_api_response(response)
|
||||
@@ -0,0 +1,145 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from typing import Generator, List, Union
|
||||
|
||||
from dashscope.api_entities.dashscope_response import (DashScopeAPIResponse,
|
||||
DictMixin, Role)
|
||||
from dashscope.client.base_api import BaseApi
|
||||
from dashscope.common.constants import MESSAGE, SCENE
|
||||
from dashscope.common.error import InputRequired, ModelRequired
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
|
||||
|
||||
class MessageParam(DictMixin):
|
||||
role: str
|
||||
|
||||
def __init__(self, role: str, **kwargs):
|
||||
super().__init__(role=role, **kwargs)
|
||||
|
||||
|
||||
class UserRoleMessageParam(MessageParam):
|
||||
content: str
|
||||
|
||||
def __init__(self, content: str, **kwargs):
|
||||
super().__init__(role=Role.USER, content=content, **kwargs)
|
||||
|
||||
|
||||
class AttachmentRoleMessageParam(MessageParam):
|
||||
meta: dict
|
||||
|
||||
def __init__(self, meta: dict, **kwargs):
|
||||
super().__init__(role=Role.ATTACHMENT, meta=meta, **kwargs)
|
||||
|
||||
|
||||
class OtherRoleContentMessageParam(MessageParam):
|
||||
content: str
|
||||
|
||||
def __init__(self, role: str, content: str, **kwargs):
|
||||
super().__init__(role=role, content=content, **kwargs)
|
||||
|
||||
|
||||
class OtherRoleMetaMessageParam(MessageParam):
|
||||
meta: dict
|
||||
|
||||
def __init__(self, role: str, meta: dict, **kwargs):
|
||||
super().__init__(role=role, meta=meta, **kwargs)
|
||||
|
||||
|
||||
class CodeGeneration(BaseApi):
|
||||
function = 'generation'
|
||||
"""API for AI-Generated Content(AIGC) models.
|
||||
|
||||
"""
|
||||
class Models:
|
||||
tongyi_lingma_v1 = 'tongyi-lingma-v1'
|
||||
|
||||
class Scenes:
|
||||
custom = 'custom'
|
||||
nl2code = 'nl2code'
|
||||
code2comment = 'code2comment'
|
||||
code2explain = 'code2explain'
|
||||
commit2msg = 'commit2msg'
|
||||
unit_test = 'unittest'
|
||||
code_qa = 'codeqa'
|
||||
nl2sql = 'nl2sql'
|
||||
|
||||
@classmethod
|
||||
def call(
|
||||
cls,
|
||||
model: str,
|
||||
scene: str = None,
|
||||
api_key: str = None,
|
||||
message: List[MessageParam] = None,
|
||||
workspace: str = None,
|
||||
**kwargs
|
||||
) -> Union[DashScopeAPIResponse, Generator[DashScopeAPIResponse, None,
|
||||
None]]:
|
||||
"""Call generation model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as tongyi-lingma-v1
|
||||
scene (str): Scene type, single choice, such as custom
|
||||
examples:
|
||||
custom:User defined prompt
|
||||
nl2code:Natural language generated code
|
||||
code2comment:annotation
|
||||
code2explain:explain
|
||||
commit2msg:Automatically generate commit
|
||||
uinttest:Generating Unit Tests
|
||||
codeqa:Code Q&A
|
||||
nl2sql:Generate SQL code using natural language
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will get by default rule(TODO: api key doc).
|
||||
message (list): The generation messages.
|
||||
scene == custom, examples:
|
||||
[{"role": "user", "content": "根据下面的功能描述生成一个python函数。代码的功能是计算给定路径下所有文件的总大小。"}] # noqa E501
|
||||
scene == nl2code, examples:
|
||||
[{"role": "user", "content": "计算给定路径下所有文件的总大小"}, {"role": "attachment", "meta": {"language": "java"}}] # noqa E501
|
||||
scene == code2comment, examples:
|
||||
[{"role": "user", "content": "1. 生成中文注释\n2. 仅生成代码部分,不需要额外解释函数功能\n"}, {"role": "attachment", "meta": {"code": "\t\t@Override\n\t\tpublic CancelExportTaskResponse cancelExportTask(\n\t\t\t\tCancelExportTask cancelExportTask) {\n\t\t\tAmazonEC2SkeletonInterface ec2Service = ServiceProvider.getInstance().getServiceImpl(AmazonEC2SkeletonInterface.class);\n\t\t\treturn ec2Service.cancelExportTask(cancelExportTask);\n\t\t}", "language": "java"}}] # noqa E501
|
||||
scene == code2explain, examples:
|
||||
[{"role": "user", "content": "要求不低于200字"}, {"role": "attachment", "meta": {"code": "@Override\n public int getHeaderCacheSize()\n {\n return 0;\n }\n\n", "language": "java"}}] # noqa E501
|
||||
scene == commit2msg, examples:
|
||||
[{"role": "attachment", "meta": {"diff_list": [{"diff": "--- src/com/siondream/core/PlatformResolver.java\n+++ src/com/siondream/core/PlatformResolver.java\n@@ -1,11 +1,8 @@\npackage com.siondream.core;\n-\n-import com.badlogic.gdx.files.FileHandle;\n\npublic interface PlatformResolver {\npublic void openURL(String url);\npublic void rateApp();\npublic void sendFeedback();\n-\tpublic FileHandle[] listFolder(String path);\n}\n", "old_file_path": "src/com/siondream/core/PlatformResolver.java", "new_file_path": "src/com/siondream/core/PlatformResolver.java"}]}}] # noqa E501
|
||||
scene == unittest, examples:
|
||||
[{"role": "attachment", "meta": {"code": "public static <T> TimestampMap<T> parseTimestampMap(Class<T> typeClass, String input, DateTimeZone timeZone) throws IllegalArgumentException {\n if (typeClass == null) {\n throw new IllegalArgumentException(\"typeClass required\");\n }\n\n if (input == null) {\n return null;\n }\n\n TimestampMap result;\n\n typeClass = AttributeUtils.getStandardizedType(typeClass);\n if (typeClass.equals(String.class)) {\n result = new TimestampStringMap();\n } else if (typeClass.equals(Byte.class)) {\n result = new TimestampByteMap();\n } else if (typeClass.equals(Short.class)) {\n result = new TimestampShortMap();\n } else if (typeClass.equals(Integer.class)) {\n result = new TimestampIntegerMap();\n } else if (typeClass.equals(Long.class)) {\n result = new TimestampLongMap();\n } else if (typeClass.equals(Float.class)) {\n result = new TimestampFloatMap();\n } else if (typeClass.equals(Double.class)) {\n result = new TimestampDoubleMap();\n } else if (typeClass.equals(Boolean.class)) {\n result = new TimestampBooleanMap();\n } else if (typeClass.equals(Character.class)) {\n result = new TimestampCharMap();\n } else {\n throw new IllegalArgumentException(\"Unsupported type \" + typeClass.getClass().getCanonicalName());\n }\n\n if (input.equalsIgnoreCase(EMPTY_VALUE)) {\n return result;\n }\n\n StringReader reader = new StringReader(input + ' ');// Add 1 space so\n // reader.skip\n // function always\n // works when\n // necessary (end of\n // string not\n // reached).\n\n try {\n int r;\n char c;\n while ((r = reader.read()) != -1) {\n c = (char) r;\n switch (c) {\n case LEFT_BOUND_SQUARE_BRACKET:\n case LEFT_BOUND_BRACKET:\n parseTimestampAndValue(typeClass, reader, result, timeZone);\n break;\n default:\n // Ignore other chars outside of bounds\n }\n }\n } catch (IOException ex) {\n throw new RuntimeException(\"Unexpected expection while parsing timestamps\", ex);\n }\n\n return result;\n }", "language": "java"}}] # noqa E501
|
||||
scene == codeqa, examples:
|
||||
[{"role": "user", "content": "I'm writing a small web server in Python, using BaseHTTPServer and a custom subclass of BaseHTTPServer.BaseHTTPRequestHandler. Is it possible to make this listen on more than one port?\nWhat I'm doing now:\nclass MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):\n def doGET\n [...]\n\nclass ThreadingHTTPServer(ThreadingMixIn, HTTPServer): \n pass\n\nserver = ThreadingHTTPServer(('localhost', 80), MyRequestHandler)\nserver.serve_forever()"}] # noqa E501
|
||||
scene == nl2sql, examples:
|
||||
[{"role": "user", "content": "小明的总分数是多少"}, {"role": "attachment", "meta": {"synonym_infos": {"学生姓名": "姓名|名字|名称", "学生分数": "分数|得分"}, "recall_infos": [{"content": "student_score.id='小明'", "score": "0.83"}], "schema_infos": [{"table_id": "student_score", "table_desc": "学生分数表", "columns": [{"col_name": "id", "col_caption": "学生id", "col_desc": "例值为:1,2,3", "col_type": "string"}, {"col_name": "name", "col_caption": "学生姓名", "col_desc": "例值为:张三,李四,小明", "col_type": "string"}, {"col_name": "score", "col_caption": "学生分数", "col_desc": "例值为:98,100,66", "col_type": "string"}]}]}}] # noqa E501
|
||||
workspace (str): The dashscope workspace id.
|
||||
**kwargs:
|
||||
n(int, `optional`): The number of output results, currently only supports 1, with a default value of 1 # noqa E501
|
||||
|
||||
Returns:
|
||||
Union[DashScopeAPIResponse,
|
||||
Generator[DashScopeAPIResponse, None, None]]: If
|
||||
stream is True, return Generator, otherwise DashScopeAPIResponse.
|
||||
"""
|
||||
if (scene is None or not scene) or (message is None or not message):
|
||||
raise InputRequired('scene and message is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, task = _get_task_group_and_task(__name__)
|
||||
input, parameters = cls._build_input_parameters(
|
||||
model, scene, message, **kwargs)
|
||||
response = super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=task,
|
||||
function=CodeGeneration.function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**parameters)
|
||||
|
||||
is_stream = kwargs.get('stream', False)
|
||||
if is_stream:
|
||||
return (rsp for rsp in response)
|
||||
else:
|
||||
return response
|
||||
|
||||
@classmethod
|
||||
def _build_input_parameters(cls, model, scene, message, **kwargs):
|
||||
parameters = {'n': kwargs.pop('n', 1)}
|
||||
input = {SCENE: scene, MESSAGE: message}
|
||||
return input, {**parameters, **kwargs}
|
||||
@@ -0,0 +1,314 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
import json
|
||||
from copy import deepcopy
|
||||
from http import HTTPStatus
|
||||
from typing import Any, Dict, Generator, List, Union
|
||||
|
||||
from dashscope.api_entities.dashscope_response import (ConversationResponse,
|
||||
Message, Role)
|
||||
from dashscope.client.base_api import BaseApi
|
||||
from dashscope.common.constants import DEPRECATED_MESSAGE, HISTORY, PROMPT
|
||||
from dashscope.common.error import InputRequired, InvalidInput, ModelRequired
|
||||
from dashscope.common.logging import logger
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
|
||||
|
||||
class HistoryItem(dict):
|
||||
"""A conversation history item.
|
||||
|
||||
"""
|
||||
def __init__(self, role: str, text: str = None, **kwargs):
|
||||
"""Init a history item.
|
||||
|
||||
Args:
|
||||
role (str): The role name.
|
||||
text (str): The text history. Default ot None.
|
||||
kwargs: The key/value pair of history content.
|
||||
|
||||
Raises:
|
||||
InvalidInput: The key and value must pair.
|
||||
"""
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
self.role = role
|
||||
dict.__init__(self, {role: []})
|
||||
if text is not None:
|
||||
self[self.role].append({'text': text})
|
||||
for k, v in kwargs.items():
|
||||
self[self.role].append({k: v})
|
||||
|
||||
def add(self, key: str, content: Any):
|
||||
"""Add a key/value to history.
|
||||
|
||||
Args:
|
||||
key (str): The key of the content.
|
||||
value (Any): The history content.
|
||||
"""
|
||||
self[self.role].append({key: content})
|
||||
|
||||
|
||||
class History(list):
|
||||
"""Manage the conversation history.
|
||||
|
||||
"""
|
||||
def __init__(self, items: List[HistoryItem] = None):
|
||||
"""Init a history with list of HistoryItems.
|
||||
|
||||
Args:
|
||||
items (List[HistoryItem], optional): The history items.
|
||||
Defaults to None.
|
||||
"""
|
||||
if items is not None:
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
list.__init__(items)
|
||||
else:
|
||||
list.__init__([])
|
||||
|
||||
|
||||
def _history_to_qwen_format(history: History, n_history: int):
|
||||
"""Convert history to simple format.
|
||||
[{"user":"您好", "bot":"我是你的助手,很高兴为您服务"},
|
||||
{"user":"user input", "bot":"bot output"}]
|
||||
"""
|
||||
simple_history = []
|
||||
user = None
|
||||
bot = None
|
||||
|
||||
if n_history != -1 and len(history) >= 2 * n_history:
|
||||
history = history[len(history) - 2 * n_history:]
|
||||
|
||||
for item in history:
|
||||
if 'user' in item:
|
||||
user = item['user'][0]['text']
|
||||
if 'bot' in item:
|
||||
bot = item['bot'][0]['text']
|
||||
if user is not None and bot is not None:
|
||||
simple_history.append({'user': user, 'bot': bot})
|
||||
user = None
|
||||
bot = None
|
||||
return simple_history
|
||||
|
||||
|
||||
class Conversation(BaseApi):
|
||||
"""Conversational robot interface.
|
||||
"""
|
||||
task = 'generation'
|
||||
|
||||
class Models:
|
||||
"""@deprecated, use qwen_turbo instead"""
|
||||
qwen_v1 = 'qwen-v1'
|
||||
"""@deprecated, use qwen_plus instead"""
|
||||
qwen_plus_v1 = 'qwen-plus-v1'
|
||||
|
||||
qwen_turbo = 'qwen-turbo'
|
||||
qwen_plus = 'qwen-plus'
|
||||
qwen_max = 'qwen-max'
|
||||
|
||||
def __init__(self, history: History = None) -> None:
|
||||
"""Init a chat.
|
||||
|
||||
Args:
|
||||
history (dict): The conversation initialization settings.
|
||||
will be recorded in the system history list.
|
||||
Defaults to None.
|
||||
"""
|
||||
super().__init__()
|
||||
if history is None:
|
||||
self.history = History()
|
||||
else:
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
self.history = history
|
||||
|
||||
def call(
|
||||
self,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
history: History = None,
|
||||
auto_history: bool = False,
|
||||
n_history: int = -1,
|
||||
api_key: str = None,
|
||||
messages: List[Message] = None,
|
||||
plugins: Union[str, Dict[str, Any]] = None,
|
||||
workspace: str = None,
|
||||
**kwargs
|
||||
) -> Union[ConversationResponse, Generator[ConversationResponse, None,
|
||||
None]]:
|
||||
"""Call conversational robot generator a response.
|
||||
|
||||
Args:
|
||||
model (str): The request model.
|
||||
prompt (Any): The input prompt.
|
||||
history(History): The user provided history.
|
||||
Only works for this call, will not be recorded in the
|
||||
system history list. The ``history`` and ``auto_history``
|
||||
are mutually exclusive. Default to None.
|
||||
auto_history (bool): Call with the automatically maintenance
|
||||
conversation history list. The ``history`` and ``auto_history``
|
||||
are mutually exclusive.
|
||||
n_history (int): Number of latest history in conversation,
|
||||
-1 all history. Default to -1
|
||||
api_key (str, optional): The api api_key, if not present,
|
||||
will get by default rule(TODO: api key doc). Defaults to None.
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[{'role': 'user',
|
||||
'content': 'The weather is fine today.'},
|
||||
{'role': 'assistant', 'content': 'Suitable for outings'}]
|
||||
plugins (Any): The plugin config, Can be plugins config str, or dict.
|
||||
**kwargs(qwen-turbo, qwen-plus):
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially.
|
||||
temperature(float, `optional`): Used to control the degree
|
||||
of randomness and diversity. Specifically, the temperature
|
||||
value controls the degree to which the probability distribution
|
||||
of each candidate word is smoothed when generating text.
|
||||
A higher temperature value will reduce the peak value of
|
||||
the probability, allowing more low-probability words to be
|
||||
selected, and the generated results will be more diverse;
|
||||
while a lower temperature value will enhance the peak value
|
||||
of the probability, making it easier for high-probability
|
||||
words to be selected, the generated results are more
|
||||
deterministic,range(0, 2) .[qwen-turbo,qwen-plus].
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered.
|
||||
top_k(int, `optional`): The size of the sample candidate set when generated. # noqa E501
|
||||
For example, when the value is 50, only the 50 highest-scoring tokens # noqa E501
|
||||
in a single generation form a randomly sampled candidate set. # noqa E501
|
||||
The larger the value, the higher the randomness generated; # noqa E501
|
||||
the smaller the value, the higher the certainty generated. # noqa E501
|
||||
The default value is 0, which means the top_k policy is # noqa E501
|
||||
not enabled. At this time, only the top_p policy takes effect. # noqa E501
|
||||
enable_search(bool, `optional`): Whether to enable web search(quark). # noqa E501
|
||||
Currently works best only on the first round of conversation.
|
||||
Default to False, support model: [qwen-turbo].
|
||||
customized_model_id(str, required) The enterprise-specific
|
||||
large model id, which needs to be generated from the
|
||||
operation background of the enterprise-specific
|
||||
large model product, support model: [bailian-v1].
|
||||
result_format(str, `optional`): [message|text] Set result result format. # noqa E501
|
||||
Default result is text
|
||||
incremental_output(bool, `optional`): Used to control the streaming output mode. # noqa E501
|
||||
If true, the subsequent output will include the previously input content. # noqa E501
|
||||
Otherwise, the subsequent output will not include the previously output # noqa E501
|
||||
content. Default false.
|
||||
stop(list[str] or list[list[int]], `optional`): Used to control the generation to stop # noqa E501
|
||||
when encountering setting str or token ids, the result will not include # noqa E501
|
||||
stop words or tokens.
|
||||
max_tokens(int, `optional`): The maximum token num expected to be output. It should be # noqa E501
|
||||
noted that the length generated by the model will only be less than max_tokens, # noqa E501
|
||||
not necessarily equal to it. If max_tokens is set too large, the service will # noqa E501
|
||||
directly prompt that the length exceeds the limit. It is generally # noqa E501
|
||||
not recommended to set this value.
|
||||
repetition_penalty(float, `optional`): Used to control the repeatability when generating models. # noqa E501
|
||||
Increasing repetition_penalty can reduce the duplication of model generation. # noqa E501
|
||||
1.0 means no punishment.
|
||||
workspace (str): The dashscope workspace id.
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[ConversationResponse,
|
||||
Generator[ConversationResponse, None, None]]: If
|
||||
stream is True, return Generator, otherwise ConversationResponse.
|
||||
|
||||
"""
|
||||
if ((prompt is None or not prompt)
|
||||
and ((messages is None or not messages))):
|
||||
raise InputRequired('prompt or messages is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, _ = _get_task_group_and_task(__name__)
|
||||
if plugins is not None:
|
||||
headers = kwargs.pop('headers', {})
|
||||
if isinstance(plugins, str):
|
||||
headers['X-DashScope-Plugin'] = plugins
|
||||
else:
|
||||
headers['X-DashScope-Plugin'] = json.dumps(plugins)
|
||||
kwargs['headers'] = headers
|
||||
input, parameters = self._build_input_parameters(
|
||||
model, prompt, history, auto_history, n_history, messages,
|
||||
**kwargs)
|
||||
response = super().call(model=model,
|
||||
task_group=task_group,
|
||||
task='text-generation',
|
||||
function='generation',
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**parameters)
|
||||
is_stream = kwargs.get('stream', False)
|
||||
return self._handle_response(prompt, response, is_stream)
|
||||
|
||||
def _handle_stream_response(self, prompt, responses):
|
||||
for rsp in responses:
|
||||
rsp = ConversationResponse.from_api_response(rsp)
|
||||
yield rsp
|
||||
if rsp.status_code == HTTPStatus.OK and rsp.output.choices is None:
|
||||
user_item = HistoryItem('user', text=prompt)
|
||||
bot_history_item = HistoryItem('bot', text=rsp.output.text)
|
||||
self.history.append(user_item)
|
||||
self.history.append(bot_history_item)
|
||||
|
||||
def _handle_response(self, prompt, response, is_stream):
|
||||
if is_stream:
|
||||
return (rsp
|
||||
for rsp in self._handle_stream_response(prompt, response))
|
||||
else:
|
||||
response = ConversationResponse.from_api_response(response)
|
||||
if (response.status_code == HTTPStatus.OK
|
||||
and response.output.choices is None):
|
||||
user_item = HistoryItem('user', text=prompt)
|
||||
bot_history_item = HistoryItem('bot',
|
||||
text=response.output['text'])
|
||||
self.history.append(user_item)
|
||||
self.history.append(bot_history_item)
|
||||
return response
|
||||
|
||||
def _build_input_parameters(self, model, prompt, history, auto_history,
|
||||
n_history, messages, **kwargs):
|
||||
if model == Conversation.Models.qwen_v1:
|
||||
logger.warning(
|
||||
'Model %s is deprecated, use %s instead!' %
|
||||
(Conversation.Models.qwen_v1, Conversation.Models.qwen_turbo))
|
||||
if model == Conversation.Models.qwen_plus_v1:
|
||||
logger.warning('Model %s is deprecated, use %s instead!' %
|
||||
(Conversation.Models.qwen_plus_v1,
|
||||
Conversation.Models.qwen_plus))
|
||||
parameters = {}
|
||||
if history is not None and auto_history:
|
||||
raise InvalidInput('auto_history is True, history must None')
|
||||
if history is not None: # use user provided history or system.
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
input = {
|
||||
PROMPT:
|
||||
prompt,
|
||||
HISTORY:
|
||||
_history_to_qwen_format(history, n_history) if history else [],
|
||||
}
|
||||
elif auto_history:
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
input = {
|
||||
PROMPT: prompt,
|
||||
HISTORY: _history_to_qwen_format(self.history, n_history)
|
||||
}
|
||||
elif messages:
|
||||
msgs = deepcopy(messages)
|
||||
if prompt is not None and prompt:
|
||||
msgs.append({'role': Role.USER, 'content': prompt})
|
||||
input = {'messages': msgs}
|
||||
else:
|
||||
input = {
|
||||
PROMPT: prompt,
|
||||
}
|
||||
# parameters
|
||||
if model.startswith('qwen'):
|
||||
enable_search = kwargs.pop('enable_search', False)
|
||||
if enable_search:
|
||||
parameters['enable_search'] = enable_search
|
||||
|
||||
return input, {**parameters, **kwargs}
|
||||
@@ -0,0 +1,407 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
import copy
|
||||
import json
|
||||
from typing import Any, Dict, Generator, List, Union, AsyncGenerator
|
||||
|
||||
from dashscope.api_entities.dashscope_response import (GenerationResponse,
|
||||
Message, Role)
|
||||
from dashscope.client.base_api import BaseAioApi, BaseApi
|
||||
from dashscope.common.constants import (CUSTOMIZED_MODEL_ID,
|
||||
DEPRECATED_MESSAGE, HISTORY, MESSAGES,
|
||||
PROMPT)
|
||||
from dashscope.common.error import InputRequired, ModelRequired
|
||||
from dashscope.common.logging import logger
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
from dashscope.utils.param_utils import ParamUtil
|
||||
from dashscope.utils.message_utils import merge_single_response
|
||||
|
||||
|
||||
class Generation(BaseApi):
|
||||
task = 'text-generation'
|
||||
"""API for AI-Generated Content(AIGC) models.
|
||||
|
||||
"""
|
||||
class Models:
|
||||
"""@deprecated, use qwen_turbo instead"""
|
||||
qwen_v1 = 'qwen-v1'
|
||||
"""@deprecated, use qwen_plus instead"""
|
||||
qwen_plus_v1 = 'qwen-plus-v1'
|
||||
|
||||
bailian_v1 = 'bailian-v1'
|
||||
dolly_12b_v2 = 'dolly-12b-v2'
|
||||
qwen_turbo = 'qwen-turbo'
|
||||
qwen_plus = 'qwen-plus'
|
||||
qwen_max = 'qwen-max'
|
||||
|
||||
@classmethod
|
||||
def call(
|
||||
cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
history: list = None,
|
||||
api_key: str = None,
|
||||
messages: List[Message] = None,
|
||||
plugins: Union[str, Dict[str, Any]] = None,
|
||||
workspace: str = None,
|
||||
**kwargs
|
||||
) -> Union[GenerationResponse, Generator[GenerationResponse, None, None]]:
|
||||
"""Call generation model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as qwen-turbo
|
||||
prompt (Any): The input prompt.
|
||||
history (list):The user provided history, deprecated
|
||||
examples:
|
||||
[{'user':'The weather is fine today.',
|
||||
'bot': 'Suitable for outings'}].
|
||||
Defaults to None.
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will get by default rule(TODO: api key doc).
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[{'role': 'user',
|
||||
'content': 'The weather is fine today.'},
|
||||
{'role': 'assistant', 'content': 'Suitable for outings'}]
|
||||
plugins (Any): The plugin config. Can be plugins config str, or dict.
|
||||
**kwargs:
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
temperature(float, `optional`): Used to control the degree
|
||||
of randomness and diversity. Specifically, the temperature
|
||||
value controls the degree to which the probability distribution
|
||||
of each candidate word is smoothed when generating text.
|
||||
A higher temperature value will reduce the peak value of
|
||||
the probability, allowing more low-probability words to be
|
||||
selected, and the generated results will be more diverse;
|
||||
while a lower temperature value will enhance the peak value
|
||||
of the probability, making it easier for high-probability
|
||||
words to be selected, the generated results are more
|
||||
deterministic, range(0, 2) .[qwen-turbo,qwen-plus].
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered[qwen-turbo,bailian-v1].
|
||||
top_k(int, `optional`): The size of the sample candidate set when generated. # noqa E501
|
||||
For example, when the value is 50, only the 50 highest-scoring tokens # noqa E501
|
||||
in a single generation form a randomly sampled candidate set. # noqa E501
|
||||
The larger the value, the higher the randomness generated; # noqa E501
|
||||
the smaller the value, the higher the certainty generated. # noqa E501
|
||||
The default value is 0, which means the top_k policy is # noqa E501
|
||||
not enabled. At this time, only the top_p policy takes effect. # noqa E501
|
||||
enable_search(bool, `optional`): Whether to enable web search(quark). # noqa E501
|
||||
Currently works best only on the first round of conversation.
|
||||
Default to False, support model: [qwen-turbo].
|
||||
customized_model_id(str, required) The enterprise-specific
|
||||
large model id, which needs to be generated from the
|
||||
operation background of the enterprise-specific
|
||||
large model product, support model: [bailian-v1].
|
||||
result_format(str, `optional`): [message|text] Set result result format. # noqa E501
|
||||
Default result is text
|
||||
incremental_output(bool, `optional`): Used to control the streaming output mode. # noqa E501
|
||||
If true, the subsequent output will include the previously input content. # noqa E501
|
||||
Otherwise, the subsequent output will not include the previously output # noqa E501
|
||||
content. Default false.
|
||||
stop(list[str] or list[list[int]], `optional`): Used to control the generation to stop # noqa E501
|
||||
when encountering setting str or token ids, the result will not include # noqa E501
|
||||
stop words or tokens.
|
||||
max_tokens(int, `optional`): The maximum token num expected to be output. It should be # noqa E501
|
||||
noted that the length generated by the model will only be less than max_tokens, # noqa E501
|
||||
not necessarily equal to it. If max_tokens is set too large, the service will # noqa E501
|
||||
directly prompt that the length exceeds the limit. It is generally # noqa E501
|
||||
not recommended to set this value.
|
||||
repetition_penalty(float, `optional`): Used to control the repeatability when generating models. # noqa E501
|
||||
Increasing repetition_penalty can reduce the duplication of model generation. # noqa E501
|
||||
1.0 means no punishment.
|
||||
workspace (str): The dashscope workspace id.
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[GenerationResponse,
|
||||
Generator[GenerationResponse, None, None]]: If
|
||||
stream is True, return Generator, otherwise GenerationResponse.
|
||||
"""
|
||||
if (prompt is None or not prompt) and (messages is None
|
||||
or not messages):
|
||||
raise InputRequired('prompt or messages is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, function = _get_task_group_and_task(__name__)
|
||||
if plugins is not None:
|
||||
headers = kwargs.pop('headers', {})
|
||||
if isinstance(plugins, str):
|
||||
headers['X-DashScope-Plugin'] = plugins
|
||||
else:
|
||||
headers['X-DashScope-Plugin'] = json.dumps(plugins)
|
||||
kwargs['headers'] = headers
|
||||
input, parameters = cls._build_input_parameters(
|
||||
model, prompt, history, messages, **kwargs)
|
||||
|
||||
is_stream = parameters.get('stream', False)
|
||||
# Check if we need to merge incremental output
|
||||
is_incremental_output = kwargs.get('incremental_output', None)
|
||||
to_merge_incremental_output = False
|
||||
if (ParamUtil.should_modify_incremental_output(model) and
|
||||
is_stream and is_incremental_output is False):
|
||||
to_merge_incremental_output = True
|
||||
parameters['incremental_output'] = True
|
||||
|
||||
# Pass incremental_to_full flag via headers user-agent
|
||||
if 'headers' not in parameters:
|
||||
parameters['headers'] = {}
|
||||
flag = '1' if to_merge_incremental_output else '0'
|
||||
parameters['headers']['user-agent'] = f'incremental_to_full/{flag}'
|
||||
|
||||
response = super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=Generation.task,
|
||||
function=function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**parameters)
|
||||
if is_stream:
|
||||
if to_merge_incremental_output:
|
||||
# Extract n parameter for merge logic
|
||||
n = parameters.get('n', 1)
|
||||
return cls._merge_generation_response(response, n)
|
||||
else:
|
||||
return (GenerationResponse.from_api_response(rsp)
|
||||
for rsp in response)
|
||||
else:
|
||||
return GenerationResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def _build_input_parameters(cls, model, prompt, history, messages,
|
||||
**kwargs):
|
||||
if model == Generation.Models.qwen_v1:
|
||||
logger.warning(
|
||||
'Model %s is deprecated, use %s instead!' %
|
||||
(Generation.Models.qwen_v1, Generation.Models.qwen_turbo))
|
||||
if model == Generation.Models.qwen_plus_v1:
|
||||
logger.warning(
|
||||
'Model %s is deprecated, use %s instead!' %
|
||||
(Generation.Models.qwen_plus_v1, Generation.Models.qwen_plus))
|
||||
parameters = {}
|
||||
input = {}
|
||||
if history is not None:
|
||||
logger.warning(DEPRECATED_MESSAGE)
|
||||
input[HISTORY] = history
|
||||
if prompt is not None and prompt:
|
||||
input[PROMPT] = prompt
|
||||
elif messages is not None:
|
||||
msgs = copy.deepcopy(messages)
|
||||
if prompt is not None and prompt:
|
||||
msgs.append({'role': Role.USER, 'content': prompt})
|
||||
input = {MESSAGES: msgs}
|
||||
else:
|
||||
input[PROMPT] = prompt
|
||||
|
||||
if model.startswith('qwen'):
|
||||
enable_search = kwargs.pop('enable_search', False)
|
||||
if enable_search:
|
||||
parameters['enable_search'] = enable_search
|
||||
elif model.startswith('bailian'):
|
||||
customized_model_id = kwargs.pop('customized_model_id', None)
|
||||
if customized_model_id is None:
|
||||
raise InputRequired('customized_model_id is required for %s' %
|
||||
model)
|
||||
input[CUSTOMIZED_MODEL_ID] = customized_model_id
|
||||
|
||||
return input, {**parameters, **kwargs}
|
||||
|
||||
@classmethod
|
||||
def _merge_generation_response(cls, response, n=1) -> Generator[GenerationResponse, None, None]:
|
||||
"""Merge incremental response chunks to simulate non-incremental output."""
|
||||
accumulated_data = {}
|
||||
for rsp in response:
|
||||
parsed_response = GenerationResponse.from_api_response(rsp)
|
||||
result = merge_single_response(parsed_response, accumulated_data, n)
|
||||
if result is True:
|
||||
yield parsed_response
|
||||
elif isinstance(result, list):
|
||||
# Multiple responses to yield (for n>1 non-stop cases)
|
||||
for resp in result:
|
||||
yield resp
|
||||
|
||||
|
||||
class AioGeneration(BaseAioApi):
|
||||
task = 'text-generation'
|
||||
"""API for AI-Generated Content(AIGC) models.
|
||||
|
||||
"""
|
||||
class Models:
|
||||
"""@deprecated, use qwen_turbo instead"""
|
||||
qwen_v1 = 'qwen-v1'
|
||||
"""@deprecated, use qwen_plus instead"""
|
||||
qwen_plus_v1 = 'qwen-plus-v1'
|
||||
|
||||
bailian_v1 = 'bailian-v1'
|
||||
dolly_12b_v2 = 'dolly-12b-v2'
|
||||
qwen_turbo = 'qwen-turbo'
|
||||
qwen_plus = 'qwen-plus'
|
||||
qwen_max = 'qwen-max'
|
||||
|
||||
@classmethod
|
||||
async def call(
|
||||
cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
history: list = None,
|
||||
api_key: str = None,
|
||||
messages: List[Message] = None,
|
||||
plugins: Union[str, Dict[str, Any]] = None,
|
||||
workspace: str = None,
|
||||
**kwargs
|
||||
) -> Union[GenerationResponse, AsyncGenerator[GenerationResponse, None]]:
|
||||
"""Call generation model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as qwen-turbo
|
||||
prompt (Any): The input prompt.
|
||||
history (list):The user provided history, deprecated
|
||||
examples:
|
||||
[{'user':'The weather is fine today.',
|
||||
'bot': 'Suitable for outings'}].
|
||||
Defaults to None.
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will get by default rule(TODO: api key doc).
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[{'role': 'user',
|
||||
'content': 'The weather is fine today.'},
|
||||
{'role': 'assistant', 'content': 'Suitable for outings'}]
|
||||
plugins (Any): The plugin config. Can be plugins config str, or dict.
|
||||
**kwargs:
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
temperature(float, `optional`): Used to control the degree
|
||||
of randomness and diversity. Specifically, the temperature
|
||||
value controls the degree to which the probability distribution
|
||||
of each candidate word is smoothed when generating text.
|
||||
A higher temperature value will reduce the peak value of
|
||||
the probability, allowing more low-probability words to be
|
||||
selected, and the generated results will be more diverse;
|
||||
while a lower temperature value will enhance the peak value
|
||||
of the probability, making it easier for high-probability
|
||||
words to be selected, the generated results are more
|
||||
deterministic, range(0, 2) .[qwen-turbo,qwen-plus].
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered[qwen-turbo,bailian-v1].
|
||||
top_k(int, `optional`): The size of the sample candidate set when generated. # noqa E501
|
||||
For example, when the value is 50, only the 50 highest-scoring tokens # noqa E501
|
||||
in a single generation form a randomly sampled candidate set. # noqa E501
|
||||
The larger the value, the higher the randomness generated; # noqa E501
|
||||
the smaller the value, the higher the certainty generated. # noqa E501
|
||||
The default value is 0, which means the top_k policy is # noqa E501
|
||||
not enabled. At this time, only the top_p policy takes effect. # noqa E501
|
||||
enable_search(bool, `optional`): Whether to enable web search(quark). # noqa E501
|
||||
Currently works best only on the first round of conversation.
|
||||
Default to False, support model: [qwen-turbo].
|
||||
customized_model_id(str, required) The enterprise-specific
|
||||
large model id, which needs to be generated from the
|
||||
operation background of the enterprise-specific
|
||||
large model product, support model: [bailian-v1].
|
||||
result_format(str, `optional`): [message|text] Set result result format. # noqa E501
|
||||
Default result is text
|
||||
incremental_output(bool, `optional`): Used to control the streaming output mode. # noqa E501
|
||||
If true, the subsequent output will include the previously input content. # noqa E501
|
||||
Otherwise, the subsequent output will not include the previously output # noqa E501
|
||||
content. Default false.
|
||||
stop(list[str] or list[list[int]], `optional`): Used to control the generation to stop # noqa E501
|
||||
when encountering setting str or token ids, the result will not include # noqa E501
|
||||
stop words or tokens.
|
||||
max_tokens(int, `optional`): The maximum token num expected to be output. It should be # noqa E501
|
||||
noted that the length generated by the model will only be less than max_tokens, # noqa E501
|
||||
not necessarily equal to it. If max_tokens is set too large, the service will # noqa E501
|
||||
directly prompt that the length exceeds the limit. It is generally # noqa E501
|
||||
not recommended to set this value.
|
||||
repetition_penalty(float, `optional`): Used to control the repeatability when generating models. # noqa E501
|
||||
Increasing repetition_penalty can reduce the duplication of model generation. # noqa E501
|
||||
1.0 means no punishment.
|
||||
workspace (str): The dashscope workspace id.
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[GenerationResponse,
|
||||
AsyncGenerator[GenerationResponse, None]]: If
|
||||
stream is True, return AsyncGenerator, otherwise GenerationResponse.
|
||||
"""
|
||||
if (prompt is None or not prompt) and (messages is None
|
||||
or not messages):
|
||||
raise InputRequired('prompt or messages is required!')
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, function = _get_task_group_and_task(__name__)
|
||||
if plugins is not None:
|
||||
headers = kwargs.pop('headers', {})
|
||||
if isinstance(plugins, str):
|
||||
headers['X-DashScope-Plugin'] = plugins
|
||||
else:
|
||||
headers['X-DashScope-Plugin'] = json.dumps(plugins)
|
||||
kwargs['headers'] = headers
|
||||
input, parameters = Generation._build_input_parameters(
|
||||
model, prompt, history, messages, **kwargs)
|
||||
|
||||
is_stream = parameters.get('stream', False)
|
||||
# Check if we need to merge incremental output
|
||||
is_incremental_output = kwargs.get('incremental_output', None)
|
||||
to_merge_incremental_output = False
|
||||
if (ParamUtil.should_modify_incremental_output(model) and
|
||||
is_stream and is_incremental_output is False):
|
||||
to_merge_incremental_output = True
|
||||
parameters['incremental_output'] = True
|
||||
|
||||
# Pass incremental_to_full flag via headers user-agent
|
||||
if 'headers' not in parameters:
|
||||
parameters['headers'] = {}
|
||||
flag = '1' if to_merge_incremental_output else '0'
|
||||
parameters['headers']['user-agent'] = f'incremental_to_full/{flag}'
|
||||
|
||||
response = await super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=Generation.task,
|
||||
function=function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**parameters)
|
||||
if is_stream:
|
||||
if to_merge_incremental_output:
|
||||
# Extract n parameter for merge logic
|
||||
n = parameters.get('n', 1)
|
||||
return cls._merge_generation_response(response, n)
|
||||
else:
|
||||
return cls._stream_responses(response)
|
||||
else:
|
||||
return GenerationResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def _stream_responses(cls, response) -> AsyncGenerator[GenerationResponse, None]:
|
||||
"""Convert async response stream to GenerationResponse stream."""
|
||||
# Type hint: when stream=True, response is actually an AsyncIterable
|
||||
async for rsp in response: # type: ignore
|
||||
yield GenerationResponse.from_api_response(rsp)
|
||||
|
||||
@classmethod
|
||||
async def _merge_generation_response(cls, response, n=1) -> AsyncGenerator[GenerationResponse, None]:
|
||||
"""Async version of merge incremental response chunks."""
|
||||
accumulated_data = {}
|
||||
|
||||
async for rsp in response: # type: ignore
|
||||
parsed_response = GenerationResponse.from_api_response(rsp)
|
||||
result = merge_single_response(parsed_response, accumulated_data, n)
|
||||
if result is True:
|
||||
yield parsed_response
|
||||
elif isinstance(result, list):
|
||||
# Multiple responses to yield (for n>1 non-stop cases)
|
||||
for resp in result:
|
||||
yield resp
|
||||
@@ -0,0 +1,630 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
from dashscope.api_entities.dashscope_response import (DashScopeAPIResponse,
|
||||
ImageSynthesisResponse)
|
||||
from dashscope.client.base_api import BaseAsyncApi, BaseApi, BaseAsyncAioApi, BaseAioApi
|
||||
from dashscope.common.constants import IMAGES, NEGATIVE_PROMPT, PROMPT
|
||||
from dashscope.common.error import InputRequired
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
from dashscope.utils.oss_utils import check_and_upload_local
|
||||
|
||||
|
||||
class ImageSynthesis(BaseAsyncApi):
|
||||
task = 'text2image'
|
||||
"""API for image synthesis.
|
||||
"""
|
||||
class Models:
|
||||
wanx_v1 = 'wanx-v1'
|
||||
wanx_sketch_to_image_v1 = 'wanx-sketch-to-image-v1'
|
||||
|
||||
wanx_2_1_imageedit = 'wanx2.1-imageedit'
|
||||
|
||||
@classmethod
|
||||
def call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""Call image(s) synthesis service and get result.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for image(s) synthesis.
|
||||
negative_prompt (Any): The negative_prompt. Defaults to None.
|
||||
images (List[str]): The input list of images url,
|
||||
currently not supported.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
sketch_image_url (str, optional): Only for wanx-sketch-to-image-v1,
|
||||
can be local file.
|
||||
Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
function (str): The specific functions to be achieved. like:
|
||||
colorization,super_resolution,expand,remove_watermaker,doodle,
|
||||
description_edit_with_mask,description_edit,stylization_local,stylization_all
|
||||
base_image_url (str): Enter the URL address of the target edited image.
|
||||
mask_image_url (str): Provide the URL address of the image of the marked area by the user. It should be consistent with the image resolution of the base_image_url.
|
||||
**kwargs:
|
||||
n(int, `optional`): Number of images to synthesis.
|
||||
size(str, `optional`): The output image(s) size(width*height).
|
||||
similarity(float, `optional`): The similarity between the
|
||||
output image and the input image
|
||||
sketch_weight(int, optional): How much the input sketch
|
||||
affects the output image[0-10], only for wanx-sketch-to-image-v1. # noqa E501
|
||||
Default 10.
|
||||
realisticness(int, optional): The realisticness of the output
|
||||
image[0-10], only for wanx-sketch-to-image-v1. Default 5
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The image(s) synthesis result.
|
||||
"""
|
||||
return super().call(model,
|
||||
prompt,
|
||||
negative_prompt,
|
||||
images,
|
||||
api_key=api_key,
|
||||
sketch_image_url=sketch_image_url,
|
||||
ref_img=ref_img,
|
||||
workspace=workspace,
|
||||
extra_input=extra_input,
|
||||
task=task,
|
||||
function=function,
|
||||
mask_image_url=mask_image_url,
|
||||
base_image_url=base_image_url,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def sync_call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""
|
||||
Note: This method currently now only supports wan2.2-t2i-flash and wan2.2-t2i-plus.
|
||||
Using other models will result in an error,More raw image models may be added for use later
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = cls._get_input(model, prompt, negative_prompt,
|
||||
images, api_key, sketch_image_url,
|
||||
ref_img, extra_input, task, function,
|
||||
mask_image_url, base_image_url, **kwargs)
|
||||
response = BaseApi.call(model, inputs, task_group, task, f, api_key, workspace, **kwargs)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def _get_input(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs):
|
||||
if prompt is None or not prompt:
|
||||
raise InputRequired('prompt is required!')
|
||||
inputs = {PROMPT: prompt}
|
||||
has_upload = False
|
||||
if negative_prompt is not None:
|
||||
inputs[NEGATIVE_PROMPT] = negative_prompt
|
||||
if images is not None and images and len(images) > 0:
|
||||
new_images = []
|
||||
for image in images:
|
||||
is_upload, new_image = check_and_upload_local(
|
||||
model, image, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
new_images.append(new_image)
|
||||
inputs[IMAGES] = new_images
|
||||
if sketch_image_url is not None and sketch_image_url:
|
||||
is_upload, sketch_image_url = check_and_upload_local(
|
||||
model, sketch_image_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['sketch_image_url'] = sketch_image_url
|
||||
if ref_img is not None and ref_img:
|
||||
is_upload, ref_img = check_and_upload_local(
|
||||
model, ref_img, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['ref_img'] = ref_img
|
||||
|
||||
if function is not None and function:
|
||||
inputs['function'] = function
|
||||
|
||||
if mask_image_url is not None and mask_image_url:
|
||||
is_upload, res_mask_image_url = check_and_upload_local(
|
||||
model, mask_image_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['mask_image_url'] = res_mask_image_url
|
||||
|
||||
if base_image_url is not None and base_image_url:
|
||||
is_upload, res_base_image_url = check_and_upload_local(
|
||||
model, base_image_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['base_image_url'] = res_base_image_url
|
||||
|
||||
if extra_input is not None and extra_input:
|
||||
inputs = {**inputs, **extra_input}
|
||||
|
||||
if has_upload:
|
||||
headers = kwargs.pop('headers', {})
|
||||
headers['X-DashScope-OssResourceResolve'] = 'enable'
|
||||
kwargs['headers'] = headers
|
||||
|
||||
def __get_i2i_task(task, model) -> str:
|
||||
# 处理task参数:优先使用有效的task值
|
||||
if task is not None and task != "":
|
||||
return task
|
||||
|
||||
# 根据model确定任务类型
|
||||
if model is not None and model != "":
|
||||
if 'imageedit' in model or "wan2.5-i2i" in model:
|
||||
return 'image2image'
|
||||
|
||||
# 默认返回文本到图像任务
|
||||
return ImageSynthesis.task
|
||||
|
||||
task = __get_i2i_task(task, model)
|
||||
|
||||
return inputs, kwargs, task
|
||||
|
||||
@classmethod
|
||||
def async_call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""Create a image(s) synthesis task, and return task information.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for image(s) synthesis.
|
||||
negative_prompt (Any): The negative_prompt. Defaults to None.
|
||||
images (List[str]): The input list of images url.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
sketch_image_url (str, optional): Only for wanx-sketch-to-image-v1.
|
||||
Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
function (str): The specific functions to be achieved. like:
|
||||
colorization,super_resolution,expand,remove_watermaker,doodle,
|
||||
description_edit_with_mask,description_edit,stylization_local,stylization_all
|
||||
base_image_url (str): Enter the URL address of the target edited image.
|
||||
mask_image_url (str): Provide the URL address of the image of the marked area by the user. It should be consistent with the image resolution of the base_image_url.
|
||||
**kwargs(wanx-v1):
|
||||
n(int, `optional`): Number of images to synthesis.
|
||||
size: The output image(s) size, Default 1024*1024
|
||||
similarity(float, `optional`): The similarity between the
|
||||
output image and the input image.
|
||||
sketch_weight(int, optional): How much the input sketch
|
||||
affects the output image[0-10], only for wanx-sketch-to-image-v1. # noqa E501
|
||||
Default 10.
|
||||
realisticness(int, optional): The realisticness of the output
|
||||
image[0-10], only for wanx-sketch-to-image-v1. Default 5
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The image synthesis
|
||||
task id in the response.
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = cls._get_input(model, prompt, negative_prompt,
|
||||
images, api_key, sketch_image_url,
|
||||
ref_img, extra_input, task, function,
|
||||
mask_image_url, base_image_url, **kwargs)
|
||||
response = super().async_call(
|
||||
model=model,
|
||||
task_group=task_group,
|
||||
task=task,
|
||||
function=f,
|
||||
api_key=api_key,
|
||||
input=inputs,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def fetch(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> ImageSynthesisResponse:
|
||||
"""Fetch image(s) synthesis task status or result.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The task status or result.
|
||||
"""
|
||||
response = super().fetch(task, api_key=api_key, workspace=workspace)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def wait(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> ImageSynthesisResponse:
|
||||
"""Wait for image(s) synthesis task to complete, and return the result.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The task result.
|
||||
"""
|
||||
response = super().wait(task, api_key, workspace=workspace)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def cancel(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> DashScopeAPIResponse:
|
||||
"""Cancel image synthesis task.
|
||||
Only tasks whose status is PENDING can be canceled.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return super().cancel(task, api_key, workspace=workspace)
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
start_time: str = None,
|
||||
end_time: str = None,
|
||||
model_name: str = None,
|
||||
api_key_id: str = None,
|
||||
region: str = None,
|
||||
status: str = None,
|
||||
page_no: int = 1,
|
||||
page_size: int = 10,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> DashScopeAPIResponse:
|
||||
"""List async tasks.
|
||||
|
||||
Args:
|
||||
start_time (str, optional): The tasks start time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
end_time (str, optional): The tasks end time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
model_name (str, optional): The tasks model name. Defaults to None.
|
||||
api_key_id (str, optional): The tasks api-key-id. Defaults to None.
|
||||
region (str, optional): The service region,
|
||||
for example: cn-beijing. Defaults to None.
|
||||
status (str, optional): The status of tasks[PENDING,
|
||||
RUNNING, SUCCEEDED, FAILED, CANCELED]. Defaults to None.
|
||||
page_no (int, optional): The page number. Defaults to 1.
|
||||
page_size (int, optional): The page size. Defaults to 10.
|
||||
api_key (str, optional): The user api-key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return super().list(start_time=start_time,
|
||||
end_time=end_time,
|
||||
model_name=model_name,
|
||||
api_key_id=api_key_id,
|
||||
region=region,
|
||||
status=status,
|
||||
page_no=page_no,
|
||||
page_size=page_size,
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
|
||||
class AioImageSynthesis(BaseAsyncAioApi):
|
||||
@classmethod
|
||||
async def call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""Call image(s) synthesis service and get result.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for image(s) synthesis.
|
||||
negative_prompt (Any): The negative_prompt. Defaults to None.
|
||||
images (List[str]): The input list of images url,
|
||||
currently not supported.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
sketch_image_url (str, optional): Only for wanx-sketch-to-image-v1,
|
||||
can be local file.
|
||||
Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
function (str): The specific functions to be achieved. like:
|
||||
colorization,super_resolution,expand,remove_watermaker,doodle,
|
||||
description_edit_with_mask,description_edit,stylization_local,stylization_all
|
||||
base_image_url (str): Enter the URL address of the target edited image.
|
||||
mask_image_url (str): Provide the URL address of the image of the marked area by the user. It should be consistent with the image resolution of the base_image_url.
|
||||
**kwargs:
|
||||
n(int, `optional`): Number of images to synthesis.
|
||||
size(str, `optional`): The output image(s) size(width*height).
|
||||
similarity(float, `optional`): The similarity between the
|
||||
output image and the input image
|
||||
sketch_weight(int, optional): How much the input sketch
|
||||
affects the output image[0-10], only for wanx-sketch-to-image-v1. # noqa E501
|
||||
Default 10.
|
||||
realisticness(int, optional): The realisticness of the output
|
||||
image[0-10], only for wanx-sketch-to-image-v1. Default 5
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The image(s) synthesis result.
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = ImageSynthesis._get_input(model, prompt, negative_prompt,
|
||||
images, api_key, sketch_image_url,
|
||||
ref_img, extra_input, task, function,
|
||||
mask_image_url, base_image_url, **kwargs)
|
||||
response = await super().call(model, inputs, task_group, task, f, api_key, workspace, **kwargs)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def sync_call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""
|
||||
Note: This method currently now only supports wan2.2-t2i-flash and wan2.2-t2i-plus.
|
||||
Using other models will result in an error,More raw image models may be added for use later
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = ImageSynthesis._get_input(model, prompt, negative_prompt,
|
||||
images, api_key, sketch_image_url,
|
||||
ref_img, extra_input, task, function,
|
||||
mask_image_url, base_image_url, **kwargs)
|
||||
response = await BaseAioApi.call(model, inputs, task_group, task, f, api_key, workspace, **kwargs)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def async_call(cls,
|
||||
model: str,
|
||||
prompt: Any,
|
||||
negative_prompt: Any = None,
|
||||
images: List[str] = None,
|
||||
api_key: str = None,
|
||||
sketch_image_url: str = None,
|
||||
ref_img: str = None,
|
||||
workspace: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
mask_image_url: str = None,
|
||||
base_image_url: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""Create a image(s) synthesis task, and return task information.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for image(s) synthesis.
|
||||
negative_prompt (Any): The negative_prompt. Defaults to None.
|
||||
images (List[str]): The input list of images url.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
sketch_image_url (str, optional): Only for wanx-sketch-to-image-v1.
|
||||
Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
function (str): The specific functions to be achieved. like:
|
||||
colorization,super_resolution,expand,remove_watermaker,doodle,
|
||||
description_edit_with_mask,description_edit,stylization_local,stylization_all
|
||||
base_image_url (str): Enter the URL address of the target edited image.
|
||||
mask_image_url (str): Provide the URL address of the image of the marked area by the user. It should be consistent with the image resolution of the base_image_url.
|
||||
**kwargs(wanx-v1):
|
||||
n(int, `optional`): Number of images to synthesis.
|
||||
size: The output image(s) size, Default 1024*1024
|
||||
similarity(float, `optional`): The similarity between the
|
||||
output image and the input image.
|
||||
sketch_weight(int, optional): How much the input sketch
|
||||
affects the output image[0-10], only for wanx-sketch-to-image-v1. # noqa E501
|
||||
Default 10.
|
||||
realisticness(int, optional): The realisticness of the output
|
||||
image[0-10], only for wanx-sketch-to-image-v1. Default 5
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The image synthesis
|
||||
task id in the response.
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = ImageSynthesis._get_input(model, prompt, negative_prompt,
|
||||
images, api_key, sketch_image_url,
|
||||
ref_img, extra_input, task, function,
|
||||
mask_image_url, base_image_url, **kwargs)
|
||||
response = await super().async_call(model, inputs, task_group, task, f, api_key, workspace, **kwargs)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def fetch(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs,) -> ImageSynthesisResponse:
|
||||
"""Fetch image(s) synthesis task status or result.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The task status or result.
|
||||
"""
|
||||
response = await super().fetch(task, api_key=api_key, workspace=workspace)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def wait(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> ImageSynthesisResponse:
|
||||
"""Wait for image(s) synthesis task to complete, and return the result.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
ImageSynthesisResponse: The task result.
|
||||
"""
|
||||
response = await super().wait(task, api_key, workspace=workspace)
|
||||
return ImageSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def cancel(cls,
|
||||
task: Union[str, ImageSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs,) -> DashScopeAPIResponse:
|
||||
"""Cancel image synthesis task.
|
||||
Only tasks whose status is PENDING can be canceled.
|
||||
|
||||
Args:
|
||||
task (Union[str, ImageSynthesisResponse]): The task_id or
|
||||
ImageSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return await super().cancel(task, api_key, workspace=workspace)
|
||||
|
||||
@classmethod
|
||||
async def list(cls,
|
||||
start_time: str = None,
|
||||
end_time: str = None,
|
||||
model_name: str = None,
|
||||
api_key_id: str = None,
|
||||
region: str = None,
|
||||
status: str = None,
|
||||
page_no: int = 1,
|
||||
page_size: int = 10,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> DashScopeAPIResponse:
|
||||
"""List async tasks.
|
||||
|
||||
Args:
|
||||
start_time (str, optional): The tasks start time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
end_time (str, optional): The tasks end time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
model_name (str, optional): The tasks model name. Defaults to None.
|
||||
api_key_id (str, optional): The tasks api-key-id. Defaults to None.
|
||||
region (str, optional): The service region,
|
||||
for example: cn-beijing. Defaults to None.
|
||||
status (str, optional): The status of tasks[PENDING,
|
||||
RUNNING, SUCCEEDED, FAILED, CANCELED]. Defaults to None.
|
||||
page_no (int, optional): The page number. Defaults to 1.
|
||||
page_size (int, optional): The page size. Defaults to 10.
|
||||
api_key (str, optional): The user api-key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return await super().list(start_time=start_time,
|
||||
end_time=end_time,
|
||||
model_name=model_name,
|
||||
api_key_id=api_key_id,
|
||||
region=region,
|
||||
status=status,
|
||||
page_no=page_no,
|
||||
page_size=page_size,
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
@@ -0,0 +1,371 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
import copy
|
||||
from typing import AsyncGenerator, Generator, List, Union
|
||||
|
||||
from dashscope.api_entities.dashscope_response import \
|
||||
MultiModalConversationResponse
|
||||
from dashscope.client.base_api import BaseAioApi, BaseApi
|
||||
from dashscope.common.error import InputRequired, ModelRequired
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
from dashscope.utils.oss_utils import preprocess_message_element
|
||||
from dashscope.utils.param_utils import ParamUtil
|
||||
from dashscope.utils.message_utils import merge_multimodal_single_response
|
||||
|
||||
|
||||
class MultiModalConversation(BaseApi):
|
||||
"""MultiModal conversational robot interface.
|
||||
"""
|
||||
task = 'multimodal-generation'
|
||||
function = 'generation'
|
||||
|
||||
class Models:
|
||||
qwen_vl_chat_v1 = 'qwen-vl-chat-v1'
|
||||
|
||||
@classmethod
|
||||
def call(
|
||||
cls,
|
||||
model: str,
|
||||
messages: List = None,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
text: str = None,
|
||||
voice: str = None,
|
||||
language_type: str = None,
|
||||
**kwargs
|
||||
) -> Union[MultiModalConversationResponse, Generator[
|
||||
MultiModalConversationResponse, None, None]]:
|
||||
"""Call the conversation model service.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as 'qwen-multimodal-v1'
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[
|
||||
{
|
||||
"role": "system",
|
||||
"content": [
|
||||
{"text": "你是达摩院的生活助手机器人。"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"image": "http://XXXX"},
|
||||
{"text": "这个图片是哪里?"},
|
||||
]
|
||||
}
|
||||
]
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will retrieve by rule [1].
|
||||
[1]: https://help.aliyun.com/zh/dashscope/developer-reference/api-key-settings. # noqa E501
|
||||
workspace (str): The dashscope workspace id.
|
||||
text (str): The text to generate.
|
||||
voice (str): The voice name of qwen tts, include 'Cherry'/'Ethan'/'Sunny'/'Dylan' and so on,
|
||||
you can get the total voice list : https://help.aliyun.com/zh/model-studio/qwen-tts.
|
||||
language_type (str): The synthesized language type, default is 'auto', useful for [qwen3-tts].
|
||||
**kwargs:
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
max_length(int, `optional`): The maximum length of tokens to
|
||||
generate. The token count of your prompt plus max_length
|
||||
cannot exceed the model's context length. Most models
|
||||
have a context length of 2000 tokens[qwen-turbo,bailian-v1]. # noqa E501
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered[qwen-turbo,bailian-v1].
|
||||
top_k(float, `optional`):
|
||||
|
||||
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[MultiModalConversationResponse,
|
||||
Generator[MultiModalConversationResponse, None, None]]: If
|
||||
stream is True, return Generator, otherwise MultiModalConversationResponse.
|
||||
"""
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, _ = _get_task_group_and_task(__name__)
|
||||
input = {}
|
||||
msg_copy = None
|
||||
|
||||
if messages is not None and messages:
|
||||
msg_copy = copy.deepcopy(messages)
|
||||
has_upload = cls._preprocess_messages(model, msg_copy, api_key)
|
||||
if has_upload:
|
||||
headers = kwargs.pop('headers', {})
|
||||
headers['X-DashScope-OssResourceResolve'] = 'enable'
|
||||
kwargs['headers'] = headers
|
||||
|
||||
if text is not None and text:
|
||||
input.update({'text': text})
|
||||
if voice is not None and voice:
|
||||
input.update({'voice': voice})
|
||||
if language_type is not None and language_type:
|
||||
input.update({'language_type': language_type})
|
||||
if msg_copy is not None:
|
||||
input.update({'messages': msg_copy})
|
||||
|
||||
# Check if we need to merge incremental output
|
||||
is_incremental_output = kwargs.get('incremental_output', None)
|
||||
to_merge_incremental_output = False
|
||||
is_stream = kwargs.get('stream', False)
|
||||
if (ParamUtil.should_modify_incremental_output(model) and
|
||||
is_stream and is_incremental_output is not None and is_incremental_output is False):
|
||||
to_merge_incremental_output = True
|
||||
kwargs['incremental_output'] = True
|
||||
|
||||
# Pass incremental_to_full flag via headers user-agent
|
||||
if 'headers' not in kwargs:
|
||||
kwargs['headers'] = {}
|
||||
flag = '1' if to_merge_incremental_output else '0'
|
||||
kwargs['headers']['user-agent'] = f'incremental_to_full/{flag}'
|
||||
|
||||
response = super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=MultiModalConversation.task,
|
||||
function=MultiModalConversation.function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
if is_stream:
|
||||
if to_merge_incremental_output:
|
||||
# Extract n parameter for merge logic
|
||||
n = kwargs.get('n', 1)
|
||||
return cls._merge_multimodal_response(response, n)
|
||||
else:
|
||||
return (MultiModalConversationResponse.from_api_response(rsp)
|
||||
for rsp in response)
|
||||
else:
|
||||
return MultiModalConversationResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def _preprocess_messages(cls, model: str, messages: List[dict],
|
||||
api_key: str):
|
||||
"""
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"image": ""},
|
||||
{"text": ""},
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
has_upload = False
|
||||
for message in messages:
|
||||
content = message['content']
|
||||
for elem in content:
|
||||
if not isinstance(elem,
|
||||
(int, float, bool, str, bytes, bytearray)):
|
||||
is_upload = preprocess_message_element(
|
||||
model, elem, api_key)
|
||||
if is_upload and not has_upload:
|
||||
has_upload = True
|
||||
return has_upload
|
||||
|
||||
@classmethod
|
||||
def _merge_multimodal_response(cls, response, n=1) -> Generator[MultiModalConversationResponse, None, None]:
|
||||
"""Merge incremental response chunks to simulate non-incremental output."""
|
||||
accumulated_data = {}
|
||||
|
||||
for rsp in response:
|
||||
parsed_response = MultiModalConversationResponse.from_api_response(rsp)
|
||||
result = merge_multimodal_single_response(parsed_response, accumulated_data, n)
|
||||
if result is True:
|
||||
yield parsed_response
|
||||
elif isinstance(result, list):
|
||||
# Multiple responses to yield (for n>1 non-stop cases)
|
||||
for resp in result:
|
||||
yield resp
|
||||
|
||||
|
||||
class AioMultiModalConversation(BaseAioApi):
|
||||
"""Async MultiModal conversational robot interface.
|
||||
"""
|
||||
task = 'multimodal-generation'
|
||||
function = 'generation'
|
||||
|
||||
class Models:
|
||||
qwen_vl_chat_v1 = 'qwen-vl-chat-v1'
|
||||
|
||||
@classmethod
|
||||
async def call(
|
||||
cls,
|
||||
model: str,
|
||||
messages: List = None,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
text: str = None,
|
||||
voice: str = None,
|
||||
language_type: str = None,
|
||||
**kwargs
|
||||
) -> Union[MultiModalConversationResponse, AsyncGenerator[
|
||||
MultiModalConversationResponse, None]]:
|
||||
"""Call the conversation model service asynchronously.
|
||||
|
||||
Args:
|
||||
model (str): The requested model, such as 'qwen-multimodal-v1'
|
||||
messages (list): The generation messages.
|
||||
examples:
|
||||
[
|
||||
{
|
||||
"role": "system",
|
||||
"content": [
|
||||
{"text": "你是达摩院的生活助手机器人。"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"image": "http://XXXX"},
|
||||
{"text": "这个图片是哪里?"},
|
||||
]
|
||||
}
|
||||
]
|
||||
api_key (str, optional): The api api_key, can be None,
|
||||
if None, will retrieve by rule [1].
|
||||
[1]: https://help.aliyun.com/zh/dashscope/developer-reference/api-key-settings. # noqa E501
|
||||
workspace (str): The dashscope workspace id.
|
||||
text (str): The text to generate.
|
||||
voice (str): The voice name of qwen tts, include 'Cherry'/'Ethan'/'Sunny'/'Dylan' and so on,
|
||||
you can get the total voice list : https://help.aliyun.com/zh/model-studio/qwen-tts.
|
||||
language_type (str): The synthesized language type, default is 'auto', useful for [qwen3-tts].
|
||||
**kwargs:
|
||||
stream(bool, `optional`): Enable server-sent events
|
||||
(ref: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) # noqa E501
|
||||
the result will back partially[qwen-turbo,bailian-v1].
|
||||
max_length(int, `optional`): The maximum length of tokens to
|
||||
generate. The token count of your prompt plus max_length
|
||||
cannot exceed the model's context length. Most models
|
||||
have a context length of 2000 tokens[qwen-turbo,bailian-v1]. # noqa E501
|
||||
top_p(float, `optional`): A sampling strategy, called nucleus
|
||||
sampling, where the model considers the results of the
|
||||
tokens with top_p probability mass. So 0.1 means only
|
||||
the tokens comprising the top 10% probability mass are
|
||||
considered[qwen-turbo,bailian-v1].
|
||||
top_k(float, `optional`):
|
||||
|
||||
Raises:
|
||||
InvalidInput: The history and auto_history are mutually exclusive.
|
||||
|
||||
Returns:
|
||||
Union[MultiModalConversationResponse,
|
||||
AsyncGenerator[MultiModalConversationResponse, None]]: If
|
||||
stream is True, return AsyncGenerator, otherwise MultiModalConversationResponse.
|
||||
"""
|
||||
if model is None or not model:
|
||||
raise ModelRequired('Model is required!')
|
||||
task_group, _ = _get_task_group_and_task(__name__)
|
||||
input = {}
|
||||
msg_copy = None
|
||||
|
||||
if messages is not None and messages:
|
||||
msg_copy = copy.deepcopy(messages)
|
||||
has_upload = cls._preprocess_messages(model, msg_copy, api_key)
|
||||
if has_upload:
|
||||
headers = kwargs.pop('headers', {})
|
||||
headers['X-DashScope-OssResourceResolve'] = 'enable'
|
||||
kwargs['headers'] = headers
|
||||
|
||||
if text is not None and text:
|
||||
input.update({'text': text})
|
||||
if voice is not None and voice:
|
||||
input.update({'voice': voice})
|
||||
if language_type is not None and language_type:
|
||||
input.update({'language_type': language_type})
|
||||
if msg_copy is not None:
|
||||
input.update({'messages': msg_copy})
|
||||
|
||||
# Check if we need to merge incremental output
|
||||
is_incremental_output = kwargs.get('incremental_output', None)
|
||||
to_merge_incremental_output = False
|
||||
is_stream = kwargs.get('stream', False)
|
||||
if (ParamUtil.should_modify_incremental_output(model) and
|
||||
is_stream and is_incremental_output is not None and is_incremental_output is False):
|
||||
to_merge_incremental_output = True
|
||||
kwargs['incremental_output'] = True
|
||||
|
||||
# Pass incremental_to_full flag via headers user-agent
|
||||
if 'headers' not in kwargs:
|
||||
kwargs['headers'] = {}
|
||||
flag = '1' if to_merge_incremental_output else '0'
|
||||
kwargs['headers']['user-agent'] = (
|
||||
kwargs['headers'].get('user-agent', '') +
|
||||
f'; incremental_to_full/{flag}'
|
||||
)
|
||||
|
||||
response = await super().call(model=model,
|
||||
task_group=task_group,
|
||||
task=AioMultiModalConversation.task,
|
||||
function=AioMultiModalConversation.function,
|
||||
api_key=api_key,
|
||||
input=input,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
if is_stream:
|
||||
if to_merge_incremental_output:
|
||||
# Extract n parameter for merge logic
|
||||
n = kwargs.get('n', 1)
|
||||
return cls._merge_multimodal_response(response, n)
|
||||
else:
|
||||
return cls._stream_responses(response)
|
||||
else:
|
||||
return MultiModalConversationResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def _preprocess_messages(cls, model: str, messages: List[dict],
|
||||
api_key: str):
|
||||
"""
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"image": ""},
|
||||
{"text": ""},
|
||||
]
|
||||
}
|
||||
]
|
||||
"""
|
||||
has_upload = False
|
||||
for message in messages:
|
||||
content = message['content']
|
||||
for elem in content:
|
||||
if not isinstance(elem,
|
||||
(int, float, bool, str, bytes, bytearray)):
|
||||
is_upload = preprocess_message_element(
|
||||
model, elem, api_key)
|
||||
if is_upload and not has_upload:
|
||||
has_upload = True
|
||||
return has_upload
|
||||
|
||||
@classmethod
|
||||
async def _stream_responses(cls, response) -> AsyncGenerator[MultiModalConversationResponse, None]:
|
||||
"""Convert async response stream to MultiModalConversationResponse stream."""
|
||||
# Type hint: when stream=True, response is actually an AsyncIterable
|
||||
async for rsp in response: # type: ignore
|
||||
yield MultiModalConversationResponse.from_api_response(rsp)
|
||||
|
||||
@classmethod
|
||||
async def _merge_multimodal_response(cls, response, n=1) -> AsyncGenerator[MultiModalConversationResponse, None]:
|
||||
"""Async version of merge incremental response chunks."""
|
||||
accumulated_data = {}
|
||||
|
||||
async for rsp in response:
|
||||
parsed_response = MultiModalConversationResponse.from_api_response(rsp)
|
||||
result = merge_multimodal_single_response(parsed_response, accumulated_data, n)
|
||||
if result is True:
|
||||
yield parsed_response
|
||||
elif isinstance(result, list):
|
||||
# Multiple responses to yield (for n>1 non-stop cases)
|
||||
for resp in result:
|
||||
yield resp
|
||||
|
||||
|
||||
@@ -0,0 +1,573 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from typing import Any, Dict, Union
|
||||
|
||||
from dashscope.api_entities.dashscope_response import (DashScopeAPIResponse,
|
||||
VideoSynthesisResponse)
|
||||
from dashscope.client.base_api import BaseAsyncApi, BaseAsyncAioApi
|
||||
from dashscope.common.constants import PROMPT
|
||||
from dashscope.common.utils import _get_task_group_and_task
|
||||
from dashscope.utils.oss_utils import check_and_upload_local
|
||||
|
||||
|
||||
class VideoSynthesis(BaseAsyncApi):
|
||||
task = 'video-generation'
|
||||
"""API for video synthesis.
|
||||
"""
|
||||
class Models:
|
||||
"""@deprecated, use wanx2.1-t2v-plus instead"""
|
||||
wanx_txt2video_pro = 'wanx-txt2video-pro'
|
||||
"""@deprecated, use wanx2.1-i2v-plus instead"""
|
||||
wanx_img2video_pro = 'wanx-img2video-pro'
|
||||
|
||||
wanx_2_1_t2v_turbo = 'wanx2.1-t2v-turbo'
|
||||
wanx_2_1_t2v_plus = 'wanx2.1-t2v-plus'
|
||||
|
||||
wanx_2_1_i2v_plus = 'wanx2.1-i2v-plus'
|
||||
wanx_2_1_i2v_turbo = 'wanx2.1-i2v-turbo'
|
||||
|
||||
wanx_2_1_kf2v_plus = 'wanx2.1-kf2v-plus'
|
||||
wanx_kf2v = 'wanx-kf2v'
|
||||
|
||||
@classmethod
|
||||
def call(cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
# """@deprecated, use prompt_extend in parameters """
|
||||
extend_prompt: bool = True,
|
||||
negative_prompt: str = None,
|
||||
template: str = None,
|
||||
img_url: str = None,
|
||||
audio_url: str = None,
|
||||
api_key: str = None,
|
||||
extra_input: Dict = None,
|
||||
workspace: str = None,
|
||||
task: str = None,
|
||||
head_frame: str = None,
|
||||
tail_frame: str = None,
|
||||
first_frame_url: str = None,
|
||||
last_frame_url: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Call video synthesis service and get result.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for video synthesis.
|
||||
extend_prompt (bool): @deprecated, use prompt_extend in parameters
|
||||
negative_prompt (str): The negative prompt is the opposite of the prompt meaning.
|
||||
template (str): LoRa input, such as gufeng, katong, etc.
|
||||
img_url (str): The input image url, Generate the URL of the image referenced by the video.
|
||||
audio_url (str): The input audio url
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
first_frame_url (str): The URL of the first frame image for generating the video.
|
||||
last_frame_url (str): The URL of the last frame image for generating the video.
|
||||
**kwargs:
|
||||
size(str, `optional`): The output video size(width*height).
|
||||
duration(int, optional): The duration. Duration of video generation. The default value is 5, in seconds.
|
||||
seed(int, optional): The seed. The random seed for video generation. The default value is 5.
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The video synthesis result.
|
||||
"""
|
||||
return super().call(model,
|
||||
prompt,
|
||||
img_url=img_url,
|
||||
audio_url=audio_url,
|
||||
api_key=api_key,
|
||||
extend_prompt=extend_prompt,
|
||||
negative_prompt=negative_prompt,
|
||||
template=template,
|
||||
workspace=workspace,
|
||||
extra_input=extra_input,
|
||||
task=task,
|
||||
head_frame=head_frame,
|
||||
tail_frame=tail_frame,
|
||||
first_frame_url=first_frame_url,
|
||||
last_frame_url=last_frame_url,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def _get_input(cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
img_url: str = None,
|
||||
audio_url: str = None,
|
||||
# """@deprecated, use prompt_extend in parameters """
|
||||
extend_prompt: bool = True,
|
||||
negative_prompt: str = None,
|
||||
template: str = None,
|
||||
api_key: str = None,
|
||||
extra_input: Dict = None,
|
||||
task: str = None,
|
||||
function: str = None,
|
||||
head_frame: str = None,
|
||||
tail_frame: str = None,
|
||||
first_frame_url: str = None,
|
||||
last_frame_url: str = None,
|
||||
**kwargs):
|
||||
|
||||
inputs = {PROMPT: prompt, 'extend_prompt': extend_prompt}
|
||||
if negative_prompt:
|
||||
inputs['negative_prompt'] = negative_prompt
|
||||
if template:
|
||||
inputs['template'] = template
|
||||
if function:
|
||||
inputs['function'] = function
|
||||
|
||||
has_upload = False
|
||||
|
||||
if img_url is not None and img_url:
|
||||
is_upload, res_img_url = check_and_upload_local(
|
||||
model, img_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['img_url'] = res_img_url
|
||||
|
||||
if audio_url is not None and audio_url:
|
||||
is_upload, res_audio_url = check_and_upload_local(
|
||||
model, audio_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['audio_url'] = res_audio_url
|
||||
|
||||
if head_frame is not None and head_frame:
|
||||
is_upload, res_head_frame = check_and_upload_local(
|
||||
model, head_frame, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['head_frame'] = res_head_frame
|
||||
|
||||
if tail_frame is not None and tail_frame:
|
||||
is_upload, res_tail_frame = check_and_upload_local(
|
||||
model, tail_frame, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['tail_frame'] = res_tail_frame
|
||||
|
||||
if first_frame_url is not None and first_frame_url:
|
||||
is_upload, res_first_frame_url = check_and_upload_local(
|
||||
model, first_frame_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['first_frame_url'] = res_first_frame_url
|
||||
|
||||
if last_frame_url is not None and last_frame_url:
|
||||
is_upload, res_last_frame_url = check_and_upload_local(
|
||||
model, last_frame_url, api_key)
|
||||
if is_upload:
|
||||
has_upload = True
|
||||
inputs['last_frame_url'] = res_last_frame_url
|
||||
|
||||
if extra_input is not None and extra_input:
|
||||
inputs = {**inputs, **extra_input}
|
||||
if has_upload:
|
||||
headers = kwargs.pop('headers', {})
|
||||
headers['X-DashScope-OssResourceResolve'] = 'enable'
|
||||
kwargs['headers'] = headers
|
||||
|
||||
if task is None:
|
||||
task = VideoSynthesis.task
|
||||
if model is not None and model and 'kf2v' in model:
|
||||
task = 'image2video'
|
||||
|
||||
return inputs, kwargs, task
|
||||
|
||||
@classmethod
|
||||
def async_call(cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
img_url: str = None,
|
||||
audio_url: str = None,
|
||||
# """@deprecated, use prompt_extend in parameters """
|
||||
extend_prompt: bool = True,
|
||||
negative_prompt: str = None,
|
||||
template: str = None,
|
||||
api_key: str = None,
|
||||
extra_input: Dict = None,
|
||||
workspace: str = None,
|
||||
task: str = None,
|
||||
head_frame: str = None,
|
||||
tail_frame: str = None,
|
||||
first_frame_url: str = None,
|
||||
last_frame_url: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Create a video synthesis task, and return task information.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for video synthesis.
|
||||
extend_prompt (bool): @deprecated, use prompt_extend in parameters
|
||||
negative_prompt (str): The negative prompt is the opposite of the prompt meaning.
|
||||
template (str): LoRa input, such as gufeng, katong, etc.
|
||||
img_url (str): The input image url, Generate the URL of the image referenced by the video.
|
||||
audio_url (str): The input audio url.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
first_frame_url (str): The URL of the first frame image for generating the video.
|
||||
last_frame_url (str): The URL of the last frame image for generating the video.
|
||||
**kwargs:
|
||||
size(str, `optional`): The output video size(width*height).
|
||||
duration(int, optional): The duration. Duration of video generation. The default value is 5, in seconds.
|
||||
seed(int, optional): The seed. The random seed for video generation. The default value is 5.
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The video synthesis
|
||||
task id in the response.
|
||||
"""
|
||||
task_group, function = _get_task_group_and_task(__name__)
|
||||
|
||||
inputs, kwargs, task = cls._get_input(
|
||||
model, prompt, img_url, audio_url, extend_prompt, negative_prompt, template, api_key,
|
||||
extra_input, task, function, head_frame, tail_frame,
|
||||
first_frame_url, last_frame_url, **kwargs)
|
||||
|
||||
response = super().async_call(
|
||||
model=model,
|
||||
task_group=task_group,
|
||||
task=VideoSynthesis.task if task is None else task,
|
||||
function=function,
|
||||
api_key=api_key,
|
||||
input=inputs,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def fetch(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> VideoSynthesisResponse:
|
||||
"""Fetch video synthesis task status or result.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The task status or result.
|
||||
"""
|
||||
response = super().fetch(task, api_key=api_key, workspace=workspace)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def wait(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> VideoSynthesisResponse:
|
||||
"""Wait for video synthesis task to complete, and return the result.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The task result.
|
||||
"""
|
||||
response = super().wait(task, api_key, workspace=workspace)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
def cancel(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None) -> DashScopeAPIResponse:
|
||||
"""Cancel video synthesis task.
|
||||
Only tasks whose status is PENDING can be canceled.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return super().cancel(task, api_key, workspace=workspace)
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
start_time: str = None,
|
||||
end_time: str = None,
|
||||
model_name: str = None,
|
||||
api_key_id: str = None,
|
||||
region: str = None,
|
||||
status: str = None,
|
||||
page_no: int = 1,
|
||||
page_size: int = 10,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> DashScopeAPIResponse:
|
||||
"""List async tasks.
|
||||
|
||||
Args:
|
||||
start_time (str, optional): The tasks start time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
end_time (str, optional): The tasks end time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
model_name (str, optional): The tasks model name. Defaults to None.
|
||||
api_key_id (str, optional): The tasks api-key-id. Defaults to None.
|
||||
region (str, optional): The service region,
|
||||
for example: cn-beijing. Defaults to None.
|
||||
status (str, optional): The status of tasks[PENDING,
|
||||
RUNNING, SUCCEEDED, FAILED, CANCELED]. Defaults to None.
|
||||
page_no (int, optional): The page number. Defaults to 1.
|
||||
page_size (int, optional): The page size. Defaults to 10.
|
||||
api_key (str, optional): The user api-key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return super().list(start_time=start_time,
|
||||
end_time=end_time,
|
||||
model_name=model_name,
|
||||
api_key_id=api_key_id,
|
||||
region=region,
|
||||
status=status,
|
||||
page_no=page_no,
|
||||
page_size=page_size,
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
|
||||
class AioVideoSynthesis(BaseAsyncAioApi):
|
||||
@classmethod
|
||||
async def call(cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
img_url: str = None,
|
||||
audio_url: str = None,
|
||||
# """@deprecated, use prompt_extend in parameters """
|
||||
extend_prompt: bool = True,
|
||||
negative_prompt: str = None,
|
||||
template: str = None,
|
||||
api_key: str = None,
|
||||
extra_input: Dict = None,
|
||||
workspace: str = None,
|
||||
task: str = None,
|
||||
head_frame: str = None,
|
||||
tail_frame: str = None,
|
||||
first_frame_url: str = None,
|
||||
last_frame_url: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Call video synthesis service and get result.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for video synthesis.
|
||||
extend_prompt (bool): @deprecated, use prompt_extend in parameters
|
||||
negative_prompt (str): The negative prompt is the opposite of the prompt meaning.
|
||||
template (str): LoRa input, such as gufeng, katong, etc.
|
||||
img_url (str): The input image url, Generate the URL of the image referenced by the video.
|
||||
audio_url (str): The input audio url.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
first_frame_url (str): The URL of the first frame image for generating the video.
|
||||
last_frame_url (str): The URL of the last frame image for generating the video.
|
||||
**kwargs:
|
||||
size(str, `optional`): The output video size(width*height).
|
||||
duration(int, optional): The duration. Duration of video generation. The default value is 5, in seconds.
|
||||
seed(int, optional): The seed. The random seed for video generation. The default value is 5.
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The video synthesis result.
|
||||
"""
|
||||
task_group, f = _get_task_group_and_task(__name__)
|
||||
inputs, kwargs, task = VideoSynthesis._get_input(
|
||||
model, prompt, img_url, audio_url, extend_prompt, negative_prompt, template, api_key,
|
||||
extra_input, task, f, head_frame, tail_frame,
|
||||
first_frame_url, last_frame_url, **kwargs)
|
||||
response = await super().call(model, inputs, task_group, task, f, api_key, workspace, **kwargs)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def async_call(cls,
|
||||
model: str,
|
||||
prompt: Any = None,
|
||||
img_url: str = None,
|
||||
audio_url: str = None,
|
||||
# """@deprecated, use prompt_extend in parameters """
|
||||
extend_prompt: bool = True,
|
||||
negative_prompt: str = None,
|
||||
template: str = None,
|
||||
api_key: str = None,
|
||||
extra_input: Dict = None,
|
||||
workspace: str = None,
|
||||
task: str = None,
|
||||
head_frame: str = None,
|
||||
tail_frame: str = None,
|
||||
first_frame_url: str = None,
|
||||
last_frame_url: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Create a video synthesis task, and return task information.
|
||||
|
||||
Args:
|
||||
model (str): The model, reference ``Models``.
|
||||
prompt (Any): The prompt for video synthesis.
|
||||
extend_prompt (bool): @deprecated, use prompt_extend in parameters
|
||||
negative_prompt (str): The negative prompt is the opposite of the prompt meaning.
|
||||
template (str): LoRa input, such as gufeng, katong, etc.
|
||||
img_url (str): The input image url, Generate the URL of the image referenced by the video.
|
||||
audio_url (str): The input audio url.
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
extra_input (Dict): The extra input parameters.
|
||||
task (str): The task of api, ref doc.
|
||||
first_frame_url (str): The URL of the first frame image for generating the video.
|
||||
last_frame_url (str): The URL of the last frame image for generating the video.
|
||||
**kwargs:
|
||||
size(str, `optional`): The output video size(width*height).
|
||||
duration(int, optional): The duration. Duration of video generation. The default value is 5, in seconds.
|
||||
seed(int, optional): The seed. The random seed for video generation. The default value is 5.
|
||||
|
||||
Raises:
|
||||
InputRequired: The prompt cannot be empty.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The video synthesis
|
||||
task id in the response.
|
||||
"""
|
||||
task_group, function = _get_task_group_and_task(__name__)
|
||||
|
||||
inputs, kwargs, task = VideoSynthesis._get_input(
|
||||
model, prompt, img_url, audio_url, extend_prompt, negative_prompt, template, api_key,
|
||||
extra_input, task, function, head_frame, tail_frame,
|
||||
first_frame_url, last_frame_url, **kwargs)
|
||||
|
||||
response = await super().async_call(
|
||||
model=model,
|
||||
task_group=task_group,
|
||||
task=VideoSynthesis.task if task is None else task,
|
||||
function=function,
|
||||
api_key=api_key,
|
||||
input=inputs,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def fetch(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Fetch video synthesis task status or result.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The task status or result.
|
||||
"""
|
||||
response = await super().fetch(task, api_key=api_key, workspace=workspace)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def wait(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> VideoSynthesisResponse:
|
||||
"""Wait for video synthesis task to complete, and return the result.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
VideoSynthesisResponse: The task result.
|
||||
"""
|
||||
response = await super().wait(task, api_key, workspace=workspace)
|
||||
return VideoSynthesisResponse.from_api_response(response)
|
||||
|
||||
@classmethod
|
||||
async def cancel(cls,
|
||||
task: Union[str, VideoSynthesisResponse],
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> DashScopeAPIResponse:
|
||||
"""Cancel video synthesis task.
|
||||
Only tasks whose status is PENDING can be canceled.
|
||||
|
||||
Args:
|
||||
task (Union[str, VideoSynthesisResponse]): The task_id or
|
||||
VideoSynthesisResponse return by async_call().
|
||||
api_key (str, optional): The api api_key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return await super().cancel(task, api_key, workspace=workspace)
|
||||
|
||||
@classmethod
|
||||
async def list(cls,
|
||||
start_time: str = None,
|
||||
end_time: str = None,
|
||||
model_name: str = None,
|
||||
api_key_id: str = None,
|
||||
region: str = None,
|
||||
status: str = None,
|
||||
page_no: int = 1,
|
||||
page_size: int = 10,
|
||||
api_key: str = None,
|
||||
workspace: str = None,
|
||||
**kwargs) -> DashScopeAPIResponse:
|
||||
"""List async tasks.
|
||||
|
||||
Args:
|
||||
start_time (str, optional): The tasks start time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
end_time (str, optional): The tasks end time,
|
||||
for example: 20230420000000. Defaults to None.
|
||||
model_name (str, optional): The tasks model name. Defaults to None.
|
||||
api_key_id (str, optional): The tasks api-key-id. Defaults to None.
|
||||
region (str, optional): The service region,
|
||||
for example: cn-beijing. Defaults to None.
|
||||
status (str, optional): The status of tasks[PENDING,
|
||||
RUNNING, SUCCEEDED, FAILED, CANCELED]. Defaults to None.
|
||||
page_no (int, optional): The page number. Defaults to 1.
|
||||
page_size (int, optional): The page size. Defaults to 10.
|
||||
api_key (str, optional): The user api-key. Defaults to None.
|
||||
workspace (str): The dashscope workspace id.
|
||||
|
||||
Returns:
|
||||
DashScopeAPIResponse: The response data.
|
||||
"""
|
||||
return await super().list(start_time=start_time,
|
||||
end_time=end_time,
|
||||
model_name=model_name,
|
||||
api_key_id=api_key_id,
|
||||
region=region,
|
||||
status=status,
|
||||
page_no=page_no,
|
||||
page_size=page_size,
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
Reference in New Issue
Block a user