chore: 添加虚拟环境到仓库
- 添加 backend_service/venv 虚拟环境 - 包含所有Python依赖包 - 注意:虚拟环境约393MB,包含12655个文件
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
# yapf: disable
|
||||
|
||||
from dashscope.threads.messages.messages import Messages
|
||||
from dashscope.threads.runs.runs import Runs
|
||||
from dashscope.threads.runs.steps import Steps
|
||||
from dashscope.threads.thread_types import (MessageFile, Run, RunList, RunStep,
|
||||
RunStepList, Thread, ThreadMessage,
|
||||
ThreadMessageList)
|
||||
from dashscope.threads.threads import Threads
|
||||
|
||||
__all__ = [
|
||||
MessageFile,
|
||||
Messages,
|
||||
Run,
|
||||
Runs,
|
||||
RunList,
|
||||
Steps,
|
||||
RunStep,
|
||||
RunStepList,
|
||||
Threads,
|
||||
Thread,
|
||||
ThreadMessage,
|
||||
ThreadMessageList,
|
||||
]
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,113 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from dashscope.client.base_api import GetStatusMixin, ListObjectMixin
|
||||
from dashscope.common.error import InputRequired
|
||||
from dashscope.threads.thread_types import MessageFile, MessageFileList
|
||||
|
||||
__all__ = ['Files']
|
||||
|
||||
|
||||
class Files(ListObjectMixin, GetStatusMixin):
|
||||
SUB_PATH = 'messages' # useless
|
||||
|
||||
@classmethod
|
||||
def retrieve(cls,
|
||||
file_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
message_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> MessageFile:
|
||||
"""Retrieve the `MessageFile`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
message_id (str): The message id.
|
||||
file_id (str): The file id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
MessageFile: The `MessageFile` object.
|
||||
"""
|
||||
return cls.get(file_id,
|
||||
thread_id=thread_id,
|
||||
message_id=message_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def get(cls,
|
||||
file_id: str,
|
||||
*,
|
||||
message_id: str,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> MessageFile:
|
||||
"""Retrieve the `MessageFile`.
|
||||
|
||||
Args:
|
||||
assistant_id (str): The assistant id.
|
||||
message_id (str): The message id.
|
||||
file_id (str): The file id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
MessageFile: The `MessageFile` object.
|
||||
"""
|
||||
if not thread_id or not message_id or not file_id:
|
||||
raise InputRequired(
|
||||
'thread id, message id and file id are required!')
|
||||
response = super().get(
|
||||
message_id,
|
||||
path=f'threads/{thread_id}/messages/{message_id}/files/{file_id}',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return MessageFile(**response)
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
message_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
limit: int = None,
|
||||
order: str = None,
|
||||
after: str = None,
|
||||
before: str = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> MessageFileList:
|
||||
"""List message files.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
message_id (str): The message_id.
|
||||
limit (int, optional): How many assistant to retrieve. Defaults to None.
|
||||
order (str, optional): Sort order by created_at. Defaults to None.
|
||||
after (str, optional): Assistant id after. Defaults to None.
|
||||
before (str, optional): Assistant id before. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
MessageFileList: The `MessageFileList`.
|
||||
"""
|
||||
if not thread_id or not message_id:
|
||||
raise InputRequired('thread id, message id are required!')
|
||||
response = super().list(
|
||||
limit=limit,
|
||||
order=order,
|
||||
after=after,
|
||||
before=before,
|
||||
path=f'threads/{thread_id}/messages/{message_id}/files',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return MessageFileList(**response)
|
||||
@@ -0,0 +1,220 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from dashscope.client.base_api import (CreateMixin, GetStatusMixin,
|
||||
ListObjectMixin, UpdateMixin)
|
||||
from dashscope.common.error import InputRequired
|
||||
from dashscope.threads.thread_types import ThreadMessage, ThreadMessageList
|
||||
|
||||
__all__ = ['Messages']
|
||||
|
||||
|
||||
class Messages(CreateMixin, ListObjectMixin, GetStatusMixin, UpdateMixin):
|
||||
SUB_PATH = 'messages' # useless
|
||||
|
||||
@classmethod
|
||||
def call(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
content: str,
|
||||
role: str = 'user',
|
||||
file_ids: List[str] = [],
|
||||
metadata: Optional[object] = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessage:
|
||||
"""Create message of thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
content (str): The message content.
|
||||
role (str, optional): The message role. Defaults to 'user'.
|
||||
file_ids (List[str], optional): The file_ids include in message. Defaults to [].
|
||||
metadata (Optional[object], optional): The custom key/value pairs. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): The DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessage: The `ThreadMessage` object.
|
||||
"""
|
||||
return cls.create(thread_id,
|
||||
content=content,
|
||||
role=role,
|
||||
file_ids=file_ids,
|
||||
metadata=metadata,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def create(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
content: str,
|
||||
role: str = 'user',
|
||||
file_ids: List[str] = [],
|
||||
metadata: Optional[object] = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessage:
|
||||
"""Create message of thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
content (str): The message content.
|
||||
role (str, optional): The message role. Defaults to 'user'.
|
||||
file_ids (List[str], optional): The file_ids include in message. Defaults to [].
|
||||
metadata (Optional[object], optional): The custom key/value pairs. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): The DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessage: The `ThreadMessage` object.
|
||||
"""
|
||||
cls.SUB_PATH = '%s/messages' % thread_id
|
||||
data = {}
|
||||
if not thread_id or not content:
|
||||
raise InputRequired('thread_id and content are required!')
|
||||
data['content'] = content
|
||||
data['role'] = role
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
if file_ids:
|
||||
data['file_ids'] = file_ids
|
||||
response = super().call(data=data,
|
||||
path=f'threads/{thread_id}/messages',
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return ThreadMessage(**response)
|
||||
|
||||
@classmethod
|
||||
def retrieve(cls,
|
||||
message_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessage:
|
||||
"""Get the `ThreadMessage`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
message_id (str): The message id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessage: The `ThreadMessage` object.
|
||||
"""
|
||||
return cls.get(message_id,
|
||||
thread_id=thread_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def get(cls,
|
||||
message_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessage:
|
||||
"""Get the `ThreadMessage`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
message_id (str): The message id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessage: The `ThreadMessage` object.
|
||||
"""
|
||||
if not message_id or not thread_id:
|
||||
raise InputRequired('thread id, message id are required!')
|
||||
response = super().get(
|
||||
message_id,
|
||||
path=f'threads/{thread_id}/messages/{message_id}',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return ThreadMessage(**response)
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
limit: int = None,
|
||||
order: str = None,
|
||||
after: str = None,
|
||||
before: str = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessageList:
|
||||
"""List message of the thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
limit (int, optional): How many assistant to retrieve. Defaults to None.
|
||||
order (str, optional): Sort order by created_at. Defaults to None.
|
||||
after (str, optional): Assistant id after. Defaults to None.
|
||||
before (str, optional): Assistant id before. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessageList: The `ThreadMessageList` object.
|
||||
"""
|
||||
if not thread_id:
|
||||
raise InputRequired('thread id is required!')
|
||||
response = super().list(limit=limit,
|
||||
order=order,
|
||||
after=after,
|
||||
before=before,
|
||||
path=f'threads/{thread_id}/messages',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return ThreadMessageList(**response)
|
||||
|
||||
@classmethod
|
||||
def update(cls,
|
||||
message_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
metadata: Dict = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> ThreadMessage:
|
||||
"""Update an message of the thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
message_id (str): The message id.
|
||||
content (str): The message content.
|
||||
role (str, optional): The message role. Defaults to 'user'.
|
||||
file_ids (List[str], optional): The file_ids include in message. Defaults to [].
|
||||
metadata (Optional[object], optional): The custom key/value pairs. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): The DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
ThreadMessage: The `ThreadMessage` object.
|
||||
"""
|
||||
if not thread_id or not message_id:
|
||||
raise InputRequired('thread id and message id are required!')
|
||||
response = super().update(target=message_id,
|
||||
json={'metadata': metadata},
|
||||
path='threads/%s/messages/%s' %
|
||||
(thread_id, message_id),
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
flattened_output=True,
|
||||
method='post',
|
||||
**kwargs)
|
||||
return ThreadMessage(**response)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,501 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
import time
|
||||
from http import HTTPStatus
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from dashscope.client.base_api import (CancelMixin, CreateMixin,
|
||||
GetStatusMixin, ListObjectMixin,
|
||||
UpdateMixin)
|
||||
from dashscope.common.error import (AssistantError, InputRequired,
|
||||
TimeoutException)
|
||||
from dashscope.common.logging import logger
|
||||
from dashscope.threads.thread_types import (Run, RunList, RunStep,
|
||||
RunStepDelta, Thread,
|
||||
ThreadMessage, ThreadMessageDelta)
|
||||
|
||||
__all__ = ['Runs']
|
||||
|
||||
|
||||
class Runs(CreateMixin, CancelMixin, ListObjectMixin, GetStatusMixin,
|
||||
UpdateMixin):
|
||||
SUB_PATH = 'RUNS' # useless
|
||||
|
||||
@classmethod
|
||||
def create_thread_and_run(cls,
|
||||
*,
|
||||
assistant_id: str,
|
||||
thread: Optional[Dict] = None,
|
||||
model: Optional[str] = None,
|
||||
instructions: Optional[str] = None,
|
||||
additional_instructions: Optional[str] = None,
|
||||
tools: Optional[List[Dict]] = None,
|
||||
stream: Optional[bool] = False,
|
||||
metadata: Optional[Dict] = None,
|
||||
workspace: str = None,
|
||||
extra_body: Optional[Dict] = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
if not assistant_id:
|
||||
raise InputRequired('assistant_id is required')
|
||||
data = {'assistant_id': assistant_id}
|
||||
if thread:
|
||||
data['thread'] = thread
|
||||
if model:
|
||||
data['model'] = model
|
||||
if instructions:
|
||||
data['instructions'] = instructions
|
||||
if additional_instructions:
|
||||
data['additional_instructions'] = additional_instructions
|
||||
if tools:
|
||||
data['tools'] = tools
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
data['stream'] = stream
|
||||
if extra_body is not None and extra_body:
|
||||
data = {**data, **extra_body}
|
||||
|
||||
response = super().call(data=data,
|
||||
path='threads/runs',
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
stream=stream,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
if stream:
|
||||
return ((event_type, cls.convert_stream_object(event_type, item))
|
||||
for event_type, item in response)
|
||||
else:
|
||||
return Run(**response)
|
||||
|
||||
@classmethod
|
||||
def create(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
assistant_id: str,
|
||||
model: Optional[str] = None,
|
||||
instructions: Optional[str] = None,
|
||||
additional_instructions: Optional[str] = None,
|
||||
tools: Optional[List[Dict]] = None,
|
||||
metadata: Optional[Dict] = None,
|
||||
stream: Optional[bool] = False,
|
||||
workspace: str = None,
|
||||
extra_body: Optional[Dict] = None,
|
||||
api_key: str = None,
|
||||
top_p: Optional[float] = None,
|
||||
top_k: Optional[int] = None,
|
||||
temperature: Optional[float] = None,
|
||||
max_tokens: Optional[int] = None,
|
||||
**kwargs) -> Run:
|
||||
"""Create a run.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread to run.
|
||||
assistant_id (str): The assistant id to run.
|
||||
model (str): The model to use.
|
||||
instructions (str, optional): The system instructions this assistant uses. Defaults to None.
|
||||
additional_instructions (Optional[str], optional): Appends additional
|
||||
instructions at the end of the instructions for the run. This is
|
||||
useful for modifying the behavior on a per-run basis without
|
||||
overriding other instructions.. Defaults to None.
|
||||
tools (Optional[str], optional): List of tools to use.. Defaults to [].
|
||||
metadata (Dict, optional): Custom key-value pairs associate with run. Defaults to None.
|
||||
workspace (str): The DashScope workspace id.
|
||||
api_key (str, optional): The DashScope workspace id. Defaults to None.
|
||||
|
||||
Raises:
|
||||
InputRequired: thread and assistant is required.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
if not thread_id or not assistant_id:
|
||||
raise InputRequired('thread_id and assistant_id is required')
|
||||
data = {'assistant_id': assistant_id}
|
||||
if model:
|
||||
data['model'] = model
|
||||
if instructions:
|
||||
data['instructions'] = instructions
|
||||
if additional_instructions:
|
||||
data['additional_instructions'] = additional_instructions
|
||||
if tools:
|
||||
data['tools'] = tools
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
data['stream'] = stream
|
||||
if extra_body is not None and extra_body:
|
||||
data = {**data, **extra_body}
|
||||
|
||||
if top_p is not None:
|
||||
data['top_p'] = top_p
|
||||
if top_k is not None:
|
||||
data['top_k'] = top_k
|
||||
if temperature is not None:
|
||||
data['temperature'] = temperature
|
||||
if max_tokens is not None:
|
||||
data['max_tokens'] = max_tokens
|
||||
|
||||
response = super().call(data=data,
|
||||
path=f'threads/{thread_id}/runs',
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
stream=stream,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
if stream:
|
||||
return ((event_type, cls.convert_stream_object(event_type, item))
|
||||
for event_type, item in response)
|
||||
else:
|
||||
return Run(**response)
|
||||
|
||||
@classmethod
|
||||
def convert_stream_object(cls, event, item):
|
||||
event_object_map = {
|
||||
'thread.created': Thread,
|
||||
'thread.run.created': Run,
|
||||
'thread.run.queued': Run,
|
||||
'thread.run.in_progress': Run,
|
||||
'thread.run.requires_action': Run,
|
||||
'thread.run.completed': Run,
|
||||
'thread.run.failed': Run,
|
||||
'thread.run.cancelled': Run,
|
||||
'thread.run.expired': Run,
|
||||
'thread.run.step.created': RunStep,
|
||||
'thread.run.step.in_progress': RunStep,
|
||||
'thread.run.step.delta': RunStepDelta,
|
||||
'thread.run.step.completed': RunStep,
|
||||
'thread.run.step.failed': RunStep,
|
||||
'thread.run.step.cancelled': RunStep,
|
||||
'thread.run.step.expired': RunStep,
|
||||
'thread.message.created': ThreadMessage,
|
||||
'thread.message.in_progress': ThreadMessage,
|
||||
'thread.message.delta': ThreadMessageDelta,
|
||||
'thread.message.completed': ThreadMessage,
|
||||
'thread.message.incomplete': ThreadMessage,
|
||||
'error': AssistantError,
|
||||
}
|
||||
if (event in event_object_map):
|
||||
return event_object_map[event](**item)
|
||||
else:
|
||||
return item
|
||||
|
||||
@classmethod
|
||||
def call(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
assistant_id: str,
|
||||
model: Optional[str] = None,
|
||||
instructions: Optional[str] = None,
|
||||
additional_instructions: Optional[str] = None,
|
||||
tools: Optional[List[Dict]] = None,
|
||||
stream: Optional[bool] = False,
|
||||
metadata: Optional[Dict] = None,
|
||||
workspace: str = None,
|
||||
extra_body: Optional[Dict] = None,
|
||||
api_key: str = None,
|
||||
top_p: Optional[float] = None,
|
||||
top_k: Optional[int] = None,
|
||||
temperature: Optional[float] = None,
|
||||
max_tokens: Optional[int] = None,
|
||||
**kwargs) -> Run:
|
||||
"""Create a run.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread to run.
|
||||
assistant_id (str): The assistant id to run.
|
||||
model (str): The model to use.
|
||||
instructions (str, optional): The system instructions this assistant uses. Defaults to None.
|
||||
additional_instructions (Optional[str], optional): Appends additional
|
||||
instructions at the end of the instructions for the run. This is
|
||||
useful for modifying the behavior on a per-run basis without
|
||||
overriding other instructions.. Defaults to None.
|
||||
tools (Optional[str], optional): List of tools to use.. Defaults to [].
|
||||
metadata (Dict, optional): Custom key-value pairs associate with run. Defaults to None.
|
||||
workspace (str): The DashScope workspace id.
|
||||
api_key (str, optional): The DashScope workspace id. Defaults to None.
|
||||
|
||||
Raises:
|
||||
InputRequired: thread and assistant is required.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
return cls.create(thread_id,
|
||||
assistant_id=assistant_id,
|
||||
model=model,
|
||||
instructions=instructions,
|
||||
additional_instructions=additional_instructions,
|
||||
tools=tools,
|
||||
stream=stream,
|
||||
metadata=metadata,
|
||||
workspace=workspace,
|
||||
extra_body=extra_body,
|
||||
api_key=api_key,
|
||||
top_p=top_p,
|
||||
top_k=top_k,
|
||||
temperature=temperature,
|
||||
max_tokens=max_tokens,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
limit: int = None,
|
||||
order: str = None,
|
||||
after: str = None,
|
||||
before: str = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> RunList:
|
||||
"""List `Run`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
limit (int, optional): How many assistant to retrieve. Defaults to None.
|
||||
order (str, optional): Sort order by created_at. Defaults to None.
|
||||
after (str, optional): Assistant id after. Defaults to None.
|
||||
before (str, optional): Assistant id before. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
RunList: The list of runs.
|
||||
"""
|
||||
if not thread_id:
|
||||
raise InputRequired('thread_id is required!')
|
||||
response = super().list(limit=limit,
|
||||
order=order,
|
||||
after=after,
|
||||
before=before,
|
||||
path=f'threads/{thread_id}/runs',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return RunList(**response)
|
||||
|
||||
@classmethod
|
||||
def retrieve(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""Retrieve the `Run`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
if not thread_id or not run_id:
|
||||
raise InputRequired('thread_id and run_id are required!')
|
||||
response = super().get(run_id,
|
||||
path=f'threads/{thread_id}/runs/{run_id}',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return Run(**response)
|
||||
|
||||
@classmethod
|
||||
def get(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""Retrieve the `Run`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
return cls.retrieve(run_id,
|
||||
thread_id=thread_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def submit_tool_outputs(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
tool_outputs: List[Dict],
|
||||
stream: Optional[bool] = False,
|
||||
workspace: str = None,
|
||||
extra_body: Optional[Dict] = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""_summary_
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
tool_outputs (List[Dict]): The tool outputs.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Raises:
|
||||
InputRequired: The tool output thread id run id
|
||||
are required.
|
||||
|
||||
Returns:
|
||||
Run: The 'Run`.
|
||||
"""
|
||||
if not tool_outputs:
|
||||
raise InputRequired('tool_outputs is required!')
|
||||
if not thread_id or not run_id:
|
||||
raise InputRequired('thread_id and run_id are required!')
|
||||
|
||||
data = {'tool_outputs': tool_outputs}
|
||||
data['stream'] = stream
|
||||
if extra_body is not None and extra_body:
|
||||
data = {**data, **extra_body}
|
||||
|
||||
response = super().call(
|
||||
data,
|
||||
path=f'threads/{thread_id}/runs/{run_id}/submit_tool_outputs',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
stream=stream,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
if stream:
|
||||
return ((event_type, cls.convert_stream_object(event_type, item))
|
||||
for event_type, item in response)
|
||||
else:
|
||||
return Run(**response)
|
||||
|
||||
@classmethod
|
||||
def wait(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
timeout_seconds: float = float('inf'),
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""Wait for run to complete.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
timeout_seconds (int): The timeout seconds. Defaults inf.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Run: The run final status.
|
||||
"""
|
||||
if not run_id or not thread_id:
|
||||
raise InputRequired('run_id and thread_id are required!')
|
||||
start_time = time.perf_counter()
|
||||
while True:
|
||||
run = cls.get(run_id,
|
||||
thread_id=thread_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key)
|
||||
if run.status_code == HTTPStatus.OK:
|
||||
if hasattr(run, 'status'):
|
||||
if run.status in [
|
||||
'cancelled', 'failed', 'completed', 'expired',
|
||||
'requires_action'
|
||||
]:
|
||||
break
|
||||
else:
|
||||
time_eclipsed = time.perf_counter() - start_time
|
||||
if time_eclipsed > timeout_seconds:
|
||||
raise TimeoutException('Wait run complete timeout')
|
||||
time.sleep(1)
|
||||
else:
|
||||
logger.error('run has no status')
|
||||
break
|
||||
else:
|
||||
logger.error(
|
||||
'Get run thread_id: %s, run_id: %s failed, message: %s' %
|
||||
(thread_id, run_id, run.message))
|
||||
break
|
||||
return run
|
||||
|
||||
@classmethod
|
||||
def update(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
metadata: Optional[Dict] = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""Create a run.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread of the run id to be updated.
|
||||
run_id (str): The run id to update.
|
||||
model (str): The model to use.
|
||||
metadata (Dict, optional): Custom key-value pairs associate with run. Defaults to None.
|
||||
workspace (str): The DashScope workspace id.
|
||||
api_key (str, optional): The DashScope workspace id. Defaults to None.
|
||||
|
||||
Raises:
|
||||
InputRequired: thread id and run is required.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
if not thread_id or not run_id:
|
||||
raise InputRequired('thread id and run id are required!')
|
||||
response = super().update(run_id,
|
||||
json={'metadata': metadata},
|
||||
path='threads/%s/runs/%s' %
|
||||
(thread_id, run_id),
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
flattened_output=True,
|
||||
method='post',
|
||||
**kwargs)
|
||||
return Run(**response)
|
||||
|
||||
@classmethod
|
||||
def cancel(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
"""Cancel the `Run`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Run: The `Run` object.
|
||||
"""
|
||||
if not thread_id or not run_id:
|
||||
raise InputRequired('thread id and run id are required!')
|
||||
response = super().cancel(run_id,
|
||||
path='threads/%s/runs/%s/cancel' %
|
||||
(thread_id, run_id),
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
|
||||
return Run(**response)
|
||||
@@ -0,0 +1,112 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from dashscope.client.base_api import GetStatusMixin, ListObjectMixin
|
||||
from dashscope.common.error import InputRequired
|
||||
from dashscope.threads.thread_types import RunStep, RunStepList
|
||||
|
||||
__all__ = ['Steps']
|
||||
|
||||
|
||||
class Steps(ListObjectMixin, GetStatusMixin):
|
||||
SUB_PATH = 'RUNS' # useless
|
||||
|
||||
@classmethod
|
||||
def list(cls,
|
||||
run_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
limit: int = None,
|
||||
order: str = None,
|
||||
after: str = None,
|
||||
before: str = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> RunStepList:
|
||||
"""List `RunStep` of `Run`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
limit (int, optional): How many assistant to retrieve. Defaults to None.
|
||||
order (str, optional): Sort order by created_at. Defaults to None.
|
||||
after (str, optional): Assistant id after. Defaults to None.
|
||||
before (str, optional): Assistant id before. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
RunList: The list of runs.
|
||||
"""
|
||||
if not run_id:
|
||||
raise InputRequired('run_id is required!')
|
||||
response = super().list(
|
||||
limit=limit,
|
||||
order=order,
|
||||
after=after,
|
||||
before=before,
|
||||
path=f'threads/{thread_id}/runs/{run_id}/steps',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return RunStepList(**response)
|
||||
|
||||
@classmethod
|
||||
def retrieve(cls,
|
||||
step_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
run_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> RunStep:
|
||||
"""Retrieve the `RunStep`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
step_id (str): The step id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
RunStep: The `RunStep` object.
|
||||
"""
|
||||
if not thread_id or not run_id or not step_id:
|
||||
raise InputRequired('thread_id, run_id and step_id are required!')
|
||||
response = super().get(
|
||||
run_id,
|
||||
path=f'threads/{thread_id}/runs/{run_id}/steps/{step_id}',
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return RunStep(**response)
|
||||
|
||||
@classmethod
|
||||
def get(cls,
|
||||
step_id: str,
|
||||
*,
|
||||
thread_id: str,
|
||||
run_id: str,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> RunStep:
|
||||
"""Retrieve the `RunStep`.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
run_id (str): The run id.
|
||||
step_id (str): The step id.
|
||||
workspace (str): The dashscope workspace id.
|
||||
api_key (str, optional): The api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
RunStep: The `RunStep` object.
|
||||
"""
|
||||
return cls.retrieve(thread_id,
|
||||
run_id,
|
||||
step_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
@@ -0,0 +1,665 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
# adapter from openai sdk
|
||||
# yapf: disable
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, List, Literal, Optional, Union
|
||||
|
||||
from dashscope.assistants.assistant_types import (
|
||||
Tool, convert_tools_dict_to_objects)
|
||||
from dashscope.common.base_type import BaseList, BaseObjectMixin
|
||||
|
||||
__all__ = [
|
||||
'MessageFile', 'MessageFileList', 'Usage', 'ImageFile',
|
||||
'MessageContentImageFile', 'Text', 'MessageContentText', 'ThreadMessage',
|
||||
'ThreadMessageList', 'Thread', 'Function',
|
||||
'RequiredActionFunctionToolCall', 'RequiredActionSubmitToolOutputs',
|
||||
'RequiredAction', 'LastError', 'Run', 'RunList', 'MessageCreation',
|
||||
'MessageCreationStepDetails', 'CodeInterpreterOutputLogs',
|
||||
'CodeInterpreterOutputImageImage', 'CodeInterpreterOutputImage',
|
||||
'CodeInterpreter', 'CodeToolCall', 'RetrievalToolCall', 'FunctionToolCall',
|
||||
'ToolCallsStepDetails', 'RunStep', 'RunStepList'
|
||||
]
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageFile(BaseObjectMixin):
|
||||
id: str
|
||||
message_id: str
|
||||
created_at: int
|
||||
object: str
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageFileList(BaseList):
|
||||
data: List[MessageFile]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Usage(BaseObjectMixin):
|
||||
completion_tokens: int
|
||||
"""Number of completion tokens used over the course of the run."""
|
||||
|
||||
prompt_tokens: int
|
||||
"""Number of prompt tokens used over the course of the run."""
|
||||
|
||||
total_tokens: int
|
||||
"""Total number of tokens used (prompt + completion)."""
|
||||
|
||||
input_tokens: int
|
||||
"""Input tokens used (prompt)."""
|
||||
|
||||
output_tokens: int
|
||||
"""Output tokens used (completion)."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ImageFile(BaseObjectMixin):
|
||||
file_id: str
|
||||
|
||||
def __init__(self, file_id, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageContentImageFile(BaseObjectMixin):
|
||||
type: str = 'image_file'
|
||||
image_file: ImageFile
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.image_file = ImageFile(**kwargs.pop(self.type, {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
TextAnnotation = Union[Dict]
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Text(BaseObjectMixin):
|
||||
annotations: List[TextAnnotation]
|
||||
value: str
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
annotations = kwargs.pop('annotations', None)
|
||||
if annotations:
|
||||
self.annotations = []
|
||||
for annotation in annotations:
|
||||
self.annotations.append(annotation)
|
||||
else:
|
||||
self.annotations = annotations
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageContentText(BaseObjectMixin):
|
||||
text: Text
|
||||
type: str = 'text'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
input_text = kwargs.pop('text', {})
|
||||
if input_text:
|
||||
self.text = Text(**input_text)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
MESSAGE_SUPPORT_CONTENT = {
|
||||
'text': MessageContentText,
|
||||
'image_file': MessageContentImageFile,
|
||||
}
|
||||
|
||||
Content = Union[MessageContentImageFile, MessageContentText]
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ThreadMessageDeltaContent(BaseObjectMixin):
|
||||
content: Content
|
||||
role: str
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
contents = kwargs.pop('content', None)
|
||||
if contents:
|
||||
for item in contents:
|
||||
if item['type'] == 'text':
|
||||
self.content = MessageContentText(**item)
|
||||
elif item['type'] == 'image_file':
|
||||
self.content = MessageContentImageFile(**item)
|
||||
else:
|
||||
self.content = item
|
||||
else:
|
||||
self.content = contents
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ThreadMessageDelta(BaseObjectMixin):
|
||||
status_code: int
|
||||
id: str
|
||||
object: str = 'thread.message.delta'
|
||||
delta: ThreadMessageDeltaContent
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
content = kwargs.pop('delta', None)
|
||||
if content:
|
||||
self.delta = ThreadMessageDeltaContent(**content)
|
||||
else:
|
||||
self.delta = None
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ThreadMessage(BaseObjectMixin):
|
||||
status_code: int
|
||||
id: str
|
||||
created_at: int
|
||||
thread_id: str
|
||||
role: str
|
||||
content: List[Content]
|
||||
metadata: Optional[object] = None
|
||||
object: str = 'thread.message'
|
||||
assistant_id: Optional[str] = None
|
||||
file_ids: List[str] = None
|
||||
run_id: Optional[str] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
input_content = kwargs.pop('content', None)
|
||||
if input_content:
|
||||
content_list = []
|
||||
for content in input_content:
|
||||
if 'type' in content:
|
||||
content_type = MESSAGE_SUPPORT_CONTENT.get(
|
||||
content['type'], None)
|
||||
if content_type:
|
||||
content_list.append(content_type(**content))
|
||||
else:
|
||||
content_list.append(content)
|
||||
else:
|
||||
content_list.append(content)
|
||||
self.content = content_list
|
||||
else:
|
||||
self.content = input_content
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ThreadMessageList(BaseList):
|
||||
data: List[ThreadMessage]
|
||||
|
||||
def __init__(self,
|
||||
has_more: bool = None,
|
||||
last_id: Optional[str] = None,
|
||||
first_id: Optional[str] = None,
|
||||
data: List[ThreadMessage] = [],
|
||||
**kwargs):
|
||||
super().__init__(has_more=has_more,
|
||||
last_id=last_id,
|
||||
first_id=first_id,
|
||||
data=data,
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Thread(BaseObjectMixin):
|
||||
status_code: int
|
||||
id: str
|
||||
created_at: int
|
||||
metadata: Optional[object] = None
|
||||
object: str = 'thread'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Function(BaseObjectMixin):
|
||||
arguments: str
|
||||
name: str
|
||||
output: Optional[str] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RequiredActionFunctionToolCall(BaseObjectMixin):
|
||||
id: str
|
||||
|
||||
function: Function
|
||||
|
||||
type: str = 'function'
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.function = Function(**kwargs.pop('function', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RequiredActionSubmitToolOutputs(BaseObjectMixin):
|
||||
tool_calls: List[RequiredActionFunctionToolCall]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
tcs = kwargs.pop('tool_calls', [])
|
||||
if tcs:
|
||||
self.tool_calls = []
|
||||
for tc in tcs:
|
||||
self.tool_calls.append(RequiredActionFunctionToolCall(**tc))
|
||||
else:
|
||||
self.tool_calls = tcs
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RequiredAction(BaseObjectMixin):
|
||||
submit_tool_outputs: RequiredActionSubmitToolOutputs
|
||||
|
||||
type: Literal['submit_tool_outputs']
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.submit_tool_outputs = RequiredActionSubmitToolOutputs(
|
||||
**kwargs.pop('submit_tool_outputs', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class LastError(BaseObjectMixin):
|
||||
code: Literal['server_error', 'rate_limit_exceeded']
|
||||
message: str
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class Run(BaseObjectMixin):
|
||||
status_code: int
|
||||
id: str
|
||||
assistant_id: str
|
||||
cancelled_at: Optional[int] = None
|
||||
completed_at: Optional[int] = None
|
||||
created_at: int = None
|
||||
expires_at: int = None
|
||||
failed_at: Optional[int] = None
|
||||
file_ids: List[str] = None
|
||||
|
||||
instructions: str = None
|
||||
|
||||
metadata: Optional[object] = None
|
||||
last_error: Optional[LastError] = None
|
||||
model: str = None
|
||||
|
||||
object: str = 'thread.run'
|
||||
|
||||
required_action: Optional[RequiredAction] = None
|
||||
|
||||
started_at: Optional[int] = None
|
||||
|
||||
status: Literal['queued', 'in_progress', 'requires_action', 'cancelling',
|
||||
'cancelled', 'failed', 'completed', 'expired']
|
||||
|
||||
thread_id: str
|
||||
|
||||
tools: List[Tool]
|
||||
|
||||
top_p: Optional[float] = None
|
||||
top_k: Optional[int] = None
|
||||
temperature: Optional[float] = None
|
||||
max_tokens: Optional[int] = None
|
||||
|
||||
usage: Optional[Usage] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.tools = convert_tools_dict_to_objects(kwargs.pop('tools', []))
|
||||
actions = kwargs.pop('required_action', None)
|
||||
if actions:
|
||||
self.required_action = RequiredAction(**actions)
|
||||
else:
|
||||
self.required_action = actions
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RunList(BaseObjectMixin):
|
||||
data: List[Run]
|
||||
|
||||
def __init__(self,
|
||||
has_more: bool = None,
|
||||
last_id: Optional[str] = None,
|
||||
first_id: Optional[str] = None,
|
||||
data: List[Run] = [],
|
||||
**kwargs):
|
||||
super().__init__(has_more=has_more,
|
||||
last_id=last_id,
|
||||
first_id=first_id,
|
||||
data=data,
|
||||
**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageCreation(BaseObjectMixin):
|
||||
message_id: str
|
||||
"""The ID of the message that was created by this run step."""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class MessageCreationStepDetails(BaseObjectMixin):
|
||||
message_creation: MessageCreation
|
||||
|
||||
type: Literal['message_creation']
|
||||
"""Always `message_creation`."""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class CodeInterpreterOutputLogs(BaseObjectMixin):
|
||||
logs: str
|
||||
"""The text output from the Code Interpreter tool call."""
|
||||
|
||||
type: Literal['logs']
|
||||
"""Always `logs`."""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class CodeInterpreterOutputImageImage(BaseObjectMixin):
|
||||
file_id: str
|
||||
"""
|
||||
The [file](https://platform.openai.com/docs/api-reference/files) ID of the
|
||||
image.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class CodeInterpreterOutputImage(BaseObjectMixin):
|
||||
image: CodeInterpreterOutputImageImage
|
||||
|
||||
type: Literal['image']
|
||||
"""Always `image`."""
|
||||
def __init__(self, **kwargs):
|
||||
self.image = CodeInterpreterOutputImageImage(**kwargs.pop('image', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
CodeInterpreterOutput = Union[CodeInterpreterOutputLogs,
|
||||
CodeInterpreterOutputImage]
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class CodeInterpreter(BaseObjectMixin):
|
||||
input: str
|
||||
"""The input to the Code Interpreter tool call."""
|
||||
|
||||
outputs: List[CodeInterpreterOutput]
|
||||
"""The outputs from the Code Interpreter tool call.
|
||||
|
||||
Code Interpreter can output one or more items, including text (`logs`) or images
|
||||
(`image`). Each of these are represented by a different object type.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
self.outputs = []
|
||||
for output in kwargs.pop('outputs', []):
|
||||
self.outputs.append(CodeInterpreterOutput(**output))
|
||||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class CodeToolCall(BaseObjectMixin):
|
||||
id: str
|
||||
"""The ID of the tool call."""
|
||||
|
||||
code_interpreter: CodeInterpreter
|
||||
"""The Code Interpreter tool call definition."""
|
||||
|
||||
type: Literal['code_interpreter']
|
||||
"""The type of tool call.
|
||||
|
||||
This is always going to be `code_interpreter` for this type of tool call.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
self.code_interpreter = CodeInterpreter(
|
||||
**kwargs.pop('code_interpreter', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RetrievalToolCall(BaseObjectMixin):
|
||||
id: str
|
||||
"""The ID of the tool call object."""
|
||||
|
||||
retrieval: object
|
||||
"""For now, this is always going to be an empty object."""
|
||||
|
||||
type: Literal['quark_search']
|
||||
"""The type of tool call.
|
||||
|
||||
This is always going to be `quark_search` for this type of tool call.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class FunctionToolCall(BaseObjectMixin):
|
||||
id: str
|
||||
"""The ID of the tool call object."""
|
||||
|
||||
function: Function
|
||||
"""The definition of the function that was called."""
|
||||
|
||||
type: Literal['function']
|
||||
"""The type of tool call.
|
||||
|
||||
This is always going to be `function` for this type of tool call.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
self.function = Function(**kwargs.pop('function', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
ToolCall = Union[CodeToolCall, RetrievalToolCall, FunctionToolCall]
|
||||
|
||||
TOOL_CALL_TYPES = {
|
||||
'function': FunctionToolCall,
|
||||
'code_interpreter': CodeToolCall,
|
||||
'retrieval': RetrievalToolCall,
|
||||
}
|
||||
|
||||
|
||||
def convert_tool_calls_dict_to_object(tool_calls):
|
||||
tool_calls_object = []
|
||||
for tool_call in tool_calls:
|
||||
if 'type' in tool_call:
|
||||
tool_call_type = TOOL_CALL_TYPES.get(tool_call['type'], None)
|
||||
if tool_call_type:
|
||||
tool_calls_object.append(tool_call_type(**tool_call))
|
||||
else:
|
||||
tool_calls_object.append(tool_call)
|
||||
else:
|
||||
tool_calls_object.append(tool_call)
|
||||
return tool_calls_object
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class ToolCallsStepDetails(BaseObjectMixin):
|
||||
tool_calls: List[ToolCall]
|
||||
"""An array of tool calls the run step was involved in.
|
||||
|
||||
These can be associated with one of three types of tools: `code_interpreter`,
|
||||
`retrieval`, or `function`.
|
||||
"""
|
||||
|
||||
type: Literal['tool_calls']
|
||||
"""Always `tool_calls`."""
|
||||
def __init__(self, **kwargs):
|
||||
self.tool_calls = convert_tool_calls_dict_to_object(
|
||||
kwargs.pop('tool_calls', []))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
StepDetails = Union[MessageCreationStepDetails, ToolCallsStepDetails]
|
||||
STEP_TYPES = {
|
||||
'tool_calls': ToolCallsStepDetails,
|
||||
'message_creation': MessageCreationStepDetails,
|
||||
}
|
||||
|
||||
|
||||
def convert_step_details_dict_to_objects(step_details):
|
||||
if 'type' in step_details:
|
||||
tool_type = STEP_TYPES.get(step_details['type'], None)
|
||||
if tool_type:
|
||||
return tool_type(**step_details)
|
||||
return step_details
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RunStepDeltaContent(BaseObjectMixin):
|
||||
step_details: StepDetails
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.step_details = convert_step_details_dict_to_objects(
|
||||
kwargs.pop('step_details', {}))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RunStepDelta(BaseObjectMixin):
|
||||
id: str
|
||||
object: str = 'thread.run.step.delta'
|
||||
delta: RunStepDeltaContent
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
delta = kwargs.pop('delta', None)
|
||||
if delta:
|
||||
self.delta = RunStepDeltaContent(**delta)
|
||||
else:
|
||||
self.delta = delta
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RunStep(BaseObjectMixin):
|
||||
status_code: int = None
|
||||
id: str
|
||||
"""The identifier of the run step, which can be referenced in API endpoints."""
|
||||
|
||||
assistant_id: str
|
||||
"""
|
||||
The ID of the
|
||||
[assistant](https://platform.openai.com/docs/api-reference/assistants)
|
||||
associated with the run step.
|
||||
"""
|
||||
|
||||
cancelled_at: Optional[int] = None
|
||||
"""The Unix timestamp (in seconds) for when the run step was cancelled."""
|
||||
|
||||
completed_at: Optional[int] = None
|
||||
"""The Unix timestamp (in seconds) for when the run step completed."""
|
||||
|
||||
created_at: int
|
||||
"""The Unix timestamp (in seconds) for when the run step was created."""
|
||||
|
||||
expired_at: Optional[int] = None
|
||||
"""The Unix timestamp (in seconds) for when the run step expired.
|
||||
|
||||
A step is considered expired if the parent run is expired.
|
||||
"""
|
||||
|
||||
failed_at: Optional[int] = None
|
||||
"""The Unix timestamp (in seconds) for when the run step failed."""
|
||||
|
||||
last_error: Optional[LastError] = None
|
||||
"""The last error associated with this run step.
|
||||
|
||||
Will be `null` if there are no errors.
|
||||
"""
|
||||
|
||||
metadata: Optional[object] = None
|
||||
"""Set of 16 key-value pairs that can be attached to an object.
|
||||
|
||||
This can be useful for storing additional information about the object in a
|
||||
structured format. Keys can be a maximum of 64 characters long and values can be
|
||||
a maxium of 512 characters long.
|
||||
"""
|
||||
|
||||
object: Literal['thread.run.step']
|
||||
"""The object type, which is always `thread.run.step`."""
|
||||
|
||||
run_id: str
|
||||
"""
|
||||
The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that
|
||||
this run step is a part of.
|
||||
"""
|
||||
|
||||
status: Literal['in_progress', 'cancelled', 'failed', 'completed',
|
||||
'expired']
|
||||
"""
|
||||
The status of the run step, which can be either `in_progress`, `cancelled`,
|
||||
`failed`, `completed`, or `expired`.
|
||||
"""
|
||||
|
||||
step_details: StepDetails
|
||||
"""The details of the run step."""
|
||||
|
||||
thread_id: str
|
||||
"""
|
||||
The ID of the [thread](https://platform.openai.com/docs/api-reference/threads)
|
||||
that was run.
|
||||
"""
|
||||
|
||||
type: Literal['message_creation', 'tool_calls']
|
||||
"""The type of run step, which can be either `message_creation` or `tool_calls`."""
|
||||
|
||||
usage: Optional[Usage] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.step_details = convert_step_details_dict_to_objects(
|
||||
kwargs.pop('step_details', {}))
|
||||
if 'usage' in kwargs and kwargs['usage'] is not None and kwargs['usage']:
|
||||
self.usage = Usage(**kwargs.pop('usage', {}))
|
||||
else:
|
||||
self.usage = None
|
||||
last_error = kwargs.pop('last_error', None)
|
||||
if last_error:
|
||||
self.last_error = LastError(**last_error)
|
||||
else:
|
||||
last_error = last_error
|
||||
super().__init__(**kwargs)
|
||||
|
||||
|
||||
@dataclass(init=False)
|
||||
class RunStepList(BaseList):
|
||||
data: List[RunStep]
|
||||
|
||||
def __init__(self,
|
||||
has_more: bool = None,
|
||||
last_id: Optional[str] = None,
|
||||
first_id: Optional[str] = None,
|
||||
data: List[RunStep] = [],
|
||||
**kwargs):
|
||||
if data:
|
||||
steps = []
|
||||
for step in data:
|
||||
steps.append(RunStep(**step))
|
||||
self.data = steps
|
||||
else:
|
||||
self.data = []
|
||||
super().__init__(has_more=has_more,
|
||||
last_id=last_id,
|
||||
first_id=first_id,
|
||||
**kwargs)
|
||||
@@ -0,0 +1,212 @@
|
||||
# Copyright (c) Alibaba, Inc. and its affiliates.
|
||||
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from dashscope.assistants.assistant_types import DeleteResponse
|
||||
from dashscope.client.base_api import (CreateMixin, DeleteMixin,
|
||||
GetStatusMixin, UpdateMixin)
|
||||
from dashscope.common.error import InputRequired
|
||||
from dashscope.threads.thread_types import Run, Thread
|
||||
|
||||
__all__ = ['Threads']
|
||||
|
||||
|
||||
class Threads(CreateMixin, DeleteMixin, GetStatusMixin, UpdateMixin):
|
||||
SUB_PATH = 'threads'
|
||||
|
||||
@classmethod
|
||||
def call(cls,
|
||||
*,
|
||||
messages: List[Dict] = None,
|
||||
metadata: Dict = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Thread:
|
||||
"""Create a thread.
|
||||
|
||||
Args:
|
||||
messages (List[Dict], optional): List of messages to start thread. Defaults to None.
|
||||
metadata (Dict, optional): The key-value information associate with thread. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Thread: The thread object.
|
||||
"""
|
||||
return cls.create(messages=messages,
|
||||
metadata=metadata,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def create(cls,
|
||||
*,
|
||||
messages: List[Dict] = None,
|
||||
metadata: Dict = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Thread:
|
||||
"""Create a thread.
|
||||
|
||||
Args:
|
||||
messages (List[Dict], optional): List of messages to start thread. Defaults to None.
|
||||
metadata (Dict, optional): The key-value information associate with thread. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Thread: The thread object.
|
||||
"""
|
||||
data = {}
|
||||
if messages:
|
||||
data['messages'] = messages
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
response = super().call(data=data if data else '',
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return Thread(**response)
|
||||
|
||||
@classmethod
|
||||
def get(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Thread:
|
||||
"""Retrieve the thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The target thread.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Thread: The `Thread` information.
|
||||
"""
|
||||
return cls.retrieve(thread_id,
|
||||
workspace=workspace,
|
||||
api_key=api_key,
|
||||
**kwargs)
|
||||
|
||||
@classmethod
|
||||
def retrieve(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Thread:
|
||||
"""Retrieve the thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The target thread.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Thread: The `Thread` information.
|
||||
"""
|
||||
if not thread_id:
|
||||
raise InputRequired('thread_id is required!')
|
||||
response = super().get(thread_id,
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return Thread(**response)
|
||||
|
||||
@classmethod
|
||||
def update(cls,
|
||||
thread_id: str,
|
||||
*,
|
||||
metadata: Dict = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Thread:
|
||||
"""Update thread information.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id.
|
||||
metadata (Dict, optional): The thread key-value information. Defaults to None.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
Thread: The `Thread` information.
|
||||
"""
|
||||
if not thread_id:
|
||||
raise InputRequired('thread_id is required!')
|
||||
response = super().update(thread_id,
|
||||
json={'metadata': metadata},
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
flattened_output=True,
|
||||
method='post',
|
||||
**kwargs)
|
||||
return Thread(**response)
|
||||
|
||||
@classmethod
|
||||
def delete(cls,
|
||||
thread_id,
|
||||
*,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> DeleteResponse:
|
||||
"""Delete thread.
|
||||
|
||||
Args:
|
||||
thread_id (str): The thread id to delete.
|
||||
workspace (str, optional): The DashScope workspace id. Defaults to None.
|
||||
api_key (str, optional): Your DashScope api key. Defaults to None.
|
||||
|
||||
Returns:
|
||||
AssistantsDeleteResponse: The deleted information.
|
||||
"""
|
||||
if not thread_id:
|
||||
raise InputRequired('thread_id is required!')
|
||||
response = super().delete(thread_id,
|
||||
api_key=api_key,
|
||||
workspace=workspace,
|
||||
flattened_output=True,
|
||||
**kwargs)
|
||||
return DeleteResponse(**response)
|
||||
|
||||
@classmethod
|
||||
def create_and_run(cls,
|
||||
*,
|
||||
assistant_id: str,
|
||||
thread: Optional[Dict] = None,
|
||||
model: Optional[str] = None,
|
||||
instructions: Optional[str] = None,
|
||||
additional_instructions: Optional[str] = None,
|
||||
tools: Optional[List[Dict]] = None,
|
||||
metadata: Optional[Dict] = None,
|
||||
workspace: str = None,
|
||||
api_key: str = None,
|
||||
**kwargs) -> Run:
|
||||
if not assistant_id:
|
||||
raise InputRequired('assistant_id is required')
|
||||
data = {'assistant_id': assistant_id}
|
||||
if thread:
|
||||
data['thread'] = thread
|
||||
if model:
|
||||
data['model'] = model
|
||||
if instructions:
|
||||
data['instructions'] = instructions
|
||||
if additional_instructions:
|
||||
data['additional_instructions'] = additional_instructions
|
||||
if tools:
|
||||
data['tools'] = tools
|
||||
if metadata:
|
||||
data['metadata'] = metadata
|
||||
|
||||
response = super().call(data=data,
|
||||
path='threads/runs',
|
||||
api_key=api_key,
|
||||
flattened_output=True,
|
||||
workspace=workspace,
|
||||
**kwargs)
|
||||
return Run(**response)
|
||||
Reference in New Issue
Block a user