chore: lint fix and test coverage (#19)
Co-authored-by: zhengweijun <weijun.zheng@aminer.cn>
This commit is contained in:
parent
f6ec3f2189
commit
e8a26d53e4
51 changed files with 319 additions and 267 deletions
|
|
@ -31,6 +31,7 @@ from .core import (
|
|||
_jwt_token,
|
||||
)
|
||||
|
||||
|
||||
class BaseClient(HttpClient):
|
||||
"""
|
||||
Main client for interacting with the ZAI API
|
||||
|
|
@ -92,6 +93,7 @@ class BaseClient(HttpClient):
|
|||
self.base_url = base_url
|
||||
|
||||
from ._version import __version__
|
||||
|
||||
super().__init__(
|
||||
version=__version__,
|
||||
base_url=base_url,
|
||||
|
|
@ -104,7 +106,7 @@ class BaseClient(HttpClient):
|
|||
|
||||
@property
|
||||
def default_base_url(self):
|
||||
raise NotImplementedError("Subclasses must define default_base_url")
|
||||
raise NotImplementedError('Subclasses must define default_base_url')
|
||||
|
||||
@cached_property
|
||||
def chat(self) -> Chat:
|
||||
|
|
@ -204,11 +206,13 @@ class BaseClient(HttpClient):
|
|||
|
||||
self.close()
|
||||
|
||||
|
||||
class ZaiClient(BaseClient):
|
||||
@property
|
||||
def default_base_url(self):
|
||||
return 'https://api.z.ai/api/paas/v4'
|
||||
|
||||
|
||||
class ZhipuAiClient(BaseClient):
|
||||
@property
|
||||
def default_base_url(self):
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class Audio(BaseAPI):
|
|||
Attributes:
|
||||
transcriptions (Transcriptions): Audio transcription operations
|
||||
"""
|
||||
|
||||
@cached_property
|
||||
def transcriptions(self) -> Transcriptions:
|
||||
return Transcriptions(self._client)
|
||||
|
|
|
|||
|
|
@ -30,11 +30,11 @@ if TYPE_CHECKING:
|
|||
from zai._client import ZaiClient
|
||||
|
||||
|
||||
|
||||
class Transcriptions(BaseAPI):
|
||||
"""
|
||||
API resource for audio transcription operations
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
from .batches import Batches
|
||||
|
||||
__all__ = ["Batches"]
|
||||
__all__ = ['Batches']
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class AsyncCompletions(BaseAPI):
|
|||
|
||||
Provides access to asynchronous chat completion operations.
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
@ -125,8 +126,8 @@ class AsyncCompletions(BaseAPI):
|
|||
'tool_choice': tool_choice,
|
||||
'meta': meta,
|
||||
'extra': maybe_transform(extra, code_geex_params.CodeGeexExtra),
|
||||
"response_format": response_format,
|
||||
"thinking": thinking
|
||||
'response_format': response_format,
|
||||
'thinking': thinking,
|
||||
}
|
||||
return self._post(
|
||||
'/async/chat/completions',
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class Chat(BaseAPI):
|
|||
|
||||
Provides access to chat completions and async completions.
|
||||
"""
|
||||
|
||||
@cached_property
|
||||
def completions(self) -> Completions:
|
||||
return Completions(self._client)
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ class Completions(BaseAPI):
|
|||
Attributes:
|
||||
client (ZaiClient): The ZAI client instance
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
@ -133,7 +134,7 @@ class Completions(BaseAPI):
|
|||
'meta': meta,
|
||||
'extra': maybe_transform(extra, code_geex_params.CodeGeexExtra),
|
||||
'response_format': response_format,
|
||||
"thinking": thinking
|
||||
'thinking': thinking,
|
||||
}
|
||||
)
|
||||
return self._post(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class Embeddings(BaseAPI):
|
|||
Attributes:
|
||||
client (ZaiClient): The ZAI client instance
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class Images(BaseAPI):
|
|||
"""
|
||||
API resource for image generation operations
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class Moderations(BaseAPI):
|
|||
"""
|
||||
API resource for content moderation operations
|
||||
"""
|
||||
|
||||
def __init__(self, client: ZaiClient) -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ class Tools(BaseAPI):
|
|||
|
||||
Provides access to various tool operations including web search.
|
||||
"""
|
||||
|
||||
def __init__(self, client: 'ZaiClient') -> None:
|
||||
super().__init__(client)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Optional, List
|
||||
from typing import TYPE_CHECKING, List, Optional
|
||||
|
||||
import httpx
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class BaseAPI:
|
|||
Attributes:
|
||||
_client (ZaiClient): The client instance for making API requests
|
||||
"""
|
||||
|
||||
_client: ZaiClient
|
||||
|
||||
def __init__(self, client: ZaiClient) -> None:
|
||||
|
|
|
|||
|
|
@ -83,9 +83,7 @@ class APIResponseValidationError(APIResponseError):
|
|||
|
||||
|
||||
class APIConnectionError(APIResponseError):
|
||||
def __init__(
|
||||
self, *, message: str = 'Connection error.', request: httpx.Request
|
||||
) -> None:
|
||||
def __init__(self, *, message: str = 'Connection error.', request: httpx.Request) -> None:
|
||||
super().__init__(message, request, json_data=None)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,20 +20,13 @@ from ._utils import is_mapping_t, is_sequence_t, is_tuple_t
|
|||
|
||||
def is_file_content(obj: object) -> TypeGuard[FileContent]:
|
||||
return (
|
||||
isinstance(obj, bytes)
|
||||
or isinstance(obj, tuple)
|
||||
or isinstance(obj, io.IOBase)
|
||||
or isinstance(obj, os.PathLike)
|
||||
isinstance(obj, bytes) or isinstance(obj, tuple) or isinstance(obj, io.IOBase) or isinstance(obj, os.PathLike)
|
||||
)
|
||||
|
||||
|
||||
def assert_is_file_content(obj: object, *, key: str | None = None) -> None:
|
||||
if not is_file_content(obj):
|
||||
prefix = (
|
||||
f'Expected entry at `{key}`'
|
||||
if key is not None
|
||||
else f'Expected file input `{obj!r}`'
|
||||
)
|
||||
prefix = f'Expected entry at `{key}`' if key is not None else f'Expected file input `{obj!r}`'
|
||||
raise RuntimeError(
|
||||
f'{prefix} to be bytes, an io.IOBase instance, PathLike or a tuple but received {type(obj)} instead. See https://github.com/openai/openai-python/tree/main#file-uploads'
|
||||
) from None
|
||||
|
|
@ -56,9 +49,7 @@ def to_httpx_files(files: RequestFiles | None) -> HttpxRequestFiles | None:
|
|||
elif is_sequence_t(files):
|
||||
files = [(key, _transform_file(file)) for key, file in files]
|
||||
else:
|
||||
raise TypeError(
|
||||
f'Unexpected file type input {type(files)}, expected mapping or sequence'
|
||||
)
|
||||
raise TypeError(f'Unexpected file type input {type(files)}, expected mapping or sequence')
|
||||
|
||||
return files
|
||||
|
||||
|
|
@ -74,9 +65,7 @@ def _transform_file(file: FileTypes) -> HttpxFileTypes:
|
|||
if is_tuple_t(file):
|
||||
return (file[0], _read_file_content(file[1]), *file[2:])
|
||||
|
||||
raise TypeError(
|
||||
'Expected file types input to be a FileContent type or to be a tuple'
|
||||
)
|
||||
raise TypeError('Expected file types input to be a FileContent type or to be a tuple')
|
||||
|
||||
|
||||
def _read_file_content(file: FileContent) -> HttpxFileContent:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ def generate_token(apikey: str):
|
|||
try:
|
||||
api_key, secret = apikey.split('.')
|
||||
except Exception as e:
|
||||
raise Exception('invalid api_key', e)
|
||||
raise Exception('Invalid API key', e)
|
||||
|
||||
payload = {
|
||||
'api_key': api_key,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class LoggerNameFilter(logging.Filter):
|
|||
|
||||
Currently allows all log records to pass through.
|
||||
"""
|
||||
|
||||
def filter(self, record):
|
||||
"""
|
||||
Determine if the specified record is to be logged.
|
||||
|
|
@ -38,15 +39,9 @@ def get_log_file(log_path: str, sub_dir: str):
|
|||
return os.path.join(log_dir, 'zai.log')
|
||||
|
||||
|
||||
def get_config_dict(
|
||||
log_level: str, log_file_path: str, log_backup_count: int, log_max_bytes: int
|
||||
) -> dict:
|
||||
def get_config_dict(log_level: str, log_file_path: str, log_backup_count: int, log_max_bytes: int) -> dict:
|
||||
# for windows, the path should be a raw string.
|
||||
log_file_path = (
|
||||
log_file_path.encode('unicode-escape').decode()
|
||||
if os.name == 'nt'
|
||||
else log_file_path
|
||||
)
|
||||
log_file_path = log_file_path.encode('unicode-escape').decode() if os.name == 'nt' else log_file_path
|
||||
log_level = log_level.upper()
|
||||
config_dict = {
|
||||
'version': 1,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class AgentsChoiceDelta(BaseModel):
|
|||
content (Optional[object]): The content delta
|
||||
role (Optional[str]): The role of the message sender
|
||||
"""
|
||||
|
||||
content: Optional[object] = None
|
||||
role: Optional[str] = None
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ class AgentsChoice(BaseModel):
|
|||
finish_reason (Optional[str]): Reason why the generation finished
|
||||
index (int): Index of this choice in the response
|
||||
"""
|
||||
|
||||
delta: AgentsChoiceDelta
|
||||
finish_reason: Optional[str] = None
|
||||
index: int
|
||||
|
|
@ -38,6 +40,7 @@ class AgentsCompletionUsage(BaseModel):
|
|||
completion_tokens (int): Number of tokens in the completion
|
||||
total_tokens (int): Total number of tokens used
|
||||
"""
|
||||
|
||||
prompt_tokens: int
|
||||
completion_tokens: int
|
||||
total_tokens: int
|
||||
|
|
@ -51,6 +54,7 @@ class AgentsError(BaseModel):
|
|||
code (Optional[str]): Error code
|
||||
message (Optional[str]): Error message
|
||||
"""
|
||||
|
||||
code: Optional[str] = None
|
||||
message: Optional[str] = None
|
||||
|
||||
|
|
@ -67,6 +71,7 @@ class AgentsCompletionChunk(BaseModel):
|
|||
usage (Optional[AgentsCompletionUsage]): Token usage statistics
|
||||
error (Optional[AgentsError]): Error information if any
|
||||
"""
|
||||
|
||||
agent_id: Optional[str] = None
|
||||
conversation_id: Optional[str] = None
|
||||
id: Optional[str] = None
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Usage(BaseModel):
|
|||
completion_tokens (int): Number of tokens in model output
|
||||
total_tokens (int): Total number of tokens used
|
||||
"""
|
||||
|
||||
prompt_tokens: int
|
||||
completion_tokens: int
|
||||
total_tokens: int
|
||||
|
|
@ -28,6 +29,7 @@ class ConversationUsage(BaseModel):
|
|||
update_time (int): Last update timestamp
|
||||
usage (Usage): Token usage statistics for this conversation
|
||||
"""
|
||||
|
||||
id: str
|
||||
assistant_id: str
|
||||
create_time: int
|
||||
|
|
@ -44,6 +46,7 @@ class ConversationUsageList(BaseModel):
|
|||
has_more (bool): Whether there are more pages available
|
||||
conversation_list (List[ConversationUsage]): List of conversation usage records
|
||||
"""
|
||||
|
||||
assistant_id: str
|
||||
has_more: bool
|
||||
conversation_list: List[ConversationUsage]
|
||||
|
|
@ -58,6 +61,7 @@ class ConversationUsageListResp(BaseModel):
|
|||
msg (str): Response message
|
||||
data (ConversationUsageList): Conversation usage data
|
||||
"""
|
||||
|
||||
code: int
|
||||
msg: str
|
||||
data: ConversationUsageList
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ class AssistantSupport(BaseModel):
|
|||
tools (List[str]): List of tool names supported by the assistant
|
||||
starter_prompts (List[str]): Recommended startup prompts for the assistant
|
||||
"""
|
||||
|
||||
assistant_id: str
|
||||
created_at: int
|
||||
updated_at: int
|
||||
|
|
@ -38,6 +39,7 @@ class AssistantSupportResp(BaseModel):
|
|||
msg (str): Response message
|
||||
data (List[AssistantSupport]): List of available assistants
|
||||
"""
|
||||
|
||||
code: int
|
||||
msg: str
|
||||
data: List[AssistantSupport]
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class AudioCustomizationParam(TypedDict, total=False):
|
|||
platform will generate default if not provided by client
|
||||
user_id (str): User ID
|
||||
"""
|
||||
|
||||
model: str
|
||||
input: str
|
||||
voice_text: str
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ class AudioSpeechParams(TypedDict, total=False):
|
|||
platform will generate default if not provided by client
|
||||
user_id (str): User ID
|
||||
"""
|
||||
|
||||
model: str
|
||||
input: str
|
||||
voice: str
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ class AsyncTaskStatus(BaseModel):
|
|||
model (Optional[str]): Model used for the task
|
||||
task_status (Optional[str]): Current status of the task
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
request_id: Optional[str] = None
|
||||
model: Optional[str] = None
|
||||
|
|
@ -32,6 +33,7 @@ class AsyncCompletion(BaseModel):
|
|||
choices (List[CompletionChoice]): List of completion choices
|
||||
usage (CompletionUsage): Token usage statistics
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
request_id: Optional[str] = None
|
||||
model: Optional[str] = None
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class Function(BaseModel):
|
|||
arguments: Function call arguments
|
||||
name: Function name
|
||||
"""
|
||||
|
||||
arguments: str
|
||||
name: str
|
||||
|
||||
|
|
@ -24,6 +25,7 @@ class CompletionMessageToolCall(BaseModel):
|
|||
function: Function call information
|
||||
type: Type of the tool call
|
||||
"""
|
||||
|
||||
id: str
|
||||
function: Function
|
||||
type: str
|
||||
|
|
@ -39,6 +41,7 @@ class CompletionMessage(BaseModel):
|
|||
reasoning_content: Reasoning content
|
||||
tool_calls: List of tool calls in the message
|
||||
"""
|
||||
|
||||
content: Optional[str] = None
|
||||
role: str
|
||||
reasoning_content: Optional[str] = None
|
||||
|
|
@ -52,8 +55,10 @@ class PromptTokensDetails(BaseModel):
|
|||
Attributes:
|
||||
cached_tokens: Number of tokens reused from cache
|
||||
"""
|
||||
|
||||
cached_tokens: int
|
||||
|
||||
|
||||
class CompletionTokensDetails(BaseModel):
|
||||
"""
|
||||
Detailed breakdown of token usage for the model completion
|
||||
|
|
@ -61,8 +66,10 @@ class CompletionTokensDetails(BaseModel):
|
|||
Attributes:
|
||||
reasoning_tokens: Number of tokens used for reasoning steps
|
||||
"""
|
||||
|
||||
reasoning_tokens: int
|
||||
|
||||
|
||||
class CompletionUsage(BaseModel):
|
||||
"""
|
||||
Token usage information for completion
|
||||
|
|
@ -74,6 +81,7 @@ class CompletionUsage(BaseModel):
|
|||
completion_tokens_details: Detailed breakdown of token usage for the model completion
|
||||
total_tokens: Total number of tokens used
|
||||
"""
|
||||
|
||||
prompt_tokens: int
|
||||
prompt_tokens_details: Optional[PromptTokensDetails] = None
|
||||
completion_tokens: int
|
||||
|
|
@ -90,6 +98,7 @@ class CompletionChoice(BaseModel):
|
|||
finish_reason: Reason why the completion finished
|
||||
message: Completion message
|
||||
"""
|
||||
|
||||
index: int
|
||||
finish_reason: str
|
||||
message: CompletionMessage
|
||||
|
|
@ -107,6 +116,7 @@ class Completion(BaseModel):
|
|||
id: Unique identifier for the completion
|
||||
usage: Token usage information
|
||||
"""
|
||||
|
||||
model: Optional[str] = None
|
||||
created: Optional[int] = None
|
||||
choices: List[CompletionChoice]
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class ChoiceDeltaFunctionCall(BaseModel):
|
|||
arguments: Function call arguments
|
||||
name: Function name
|
||||
"""
|
||||
|
||||
arguments: Optional[str] = None
|
||||
name: Optional[str] = None
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ class ChoiceDeltaToolCallFunction(BaseModel):
|
|||
arguments: Function call arguments
|
||||
name: Function name
|
||||
"""
|
||||
|
||||
arguments: Optional[str] = None
|
||||
name: Optional[str] = None
|
||||
|
||||
|
|
@ -37,6 +39,7 @@ class ChoiceDeltaToolCall(BaseModel):
|
|||
function: Function call information
|
||||
type: Type of the tool call
|
||||
"""
|
||||
|
||||
index: int
|
||||
id: Optional[str] = None
|
||||
function: Optional[ChoiceDeltaToolCallFunction] = None
|
||||
|
|
@ -52,6 +55,7 @@ class AudioCompletionChunk(BaseModel):
|
|||
data: Audio data content
|
||||
expires_at: Timestamp when the audio expires
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
data: Optional[str] = None
|
||||
expires_at: Optional[int] = None
|
||||
|
|
@ -68,6 +72,7 @@ class ChoiceDelta(BaseModel):
|
|||
tool_calls: List of tool call deltas
|
||||
audio: Audio completion chunk
|
||||
"""
|
||||
|
||||
content: Optional[str] = None
|
||||
role: Optional[str] = None
|
||||
reasoning_content: Optional[str] = None
|
||||
|
|
@ -84,6 +89,7 @@ class Choice(BaseModel):
|
|||
finish_reason: Reason why the completion finished
|
||||
index: Index of the choice
|
||||
"""
|
||||
|
||||
delta: ChoiceDelta
|
||||
finish_reason: Optional[str] = None
|
||||
index: int
|
||||
|
|
@ -98,6 +104,7 @@ class CompletionUsage(BaseModel):
|
|||
completion_tokens: Number of tokens in the completion
|
||||
total_tokens: Total number of tokens used
|
||||
"""
|
||||
|
||||
prompt_tokens: int
|
||||
completion_tokens: int
|
||||
total_tokens: int
|
||||
|
|
@ -115,6 +122,7 @@ class ChatCompletionChunk(BaseModel):
|
|||
usage: Token usage information
|
||||
extra_json: Additional JSON data
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
choices: List[Choice]
|
||||
created: Optional[int] = None
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ class FileCreateParams(TypedDict, total=False):
|
|||
knowledge_id: When the file upload purpose is retrieval, you need to specify the knowledge base ID to upload
|
||||
sentence_size: Sentence size parameter for retrieval purpose uploads
|
||||
"""
|
||||
|
||||
file: FileTypes
|
||||
upload_detail: List[UploadDetail]
|
||||
purpose: Required[Literal['fine-tune', 'retrieval', 'batch']]
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class FileObject(BaseModel):
|
|||
status (Optional[str]): Current status of the file
|
||||
status_details (Optional[str]): Additional details about the file status
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
bytes: Optional[int] = None
|
||||
created_at: Optional[int] = None
|
||||
|
|
@ -36,6 +37,7 @@ class ListOfFileObject(BaseModel):
|
|||
data (List[FileObject]): List of file objects
|
||||
has_more (Optional[bool]): Whether there are more files available
|
||||
"""
|
||||
|
||||
object: Optional[str] = None
|
||||
data: List[FileObject]
|
||||
has_more: Optional[bool] = None
|
||||
|
|
|
|||
|
|
@ -11,5 +11,6 @@ class Completion(BaseModel):
|
|||
model: The model used for moderation
|
||||
input: The input content for moderation (can be string, list of strings, or dictionary)
|
||||
"""
|
||||
|
||||
model: Optional[str] = None
|
||||
input: Optional[Union[str, List[str], Dict]] = None
|
||||
|
|
|
|||
|
|
@ -16,5 +16,6 @@ class SensitiveWordCheckRequest(TypedDict, total=False):
|
|||
contact business to obtain corresponding permissions, otherwise the disable
|
||||
setting will not take effect.
|
||||
"""
|
||||
|
||||
type: Optional[str]
|
||||
status: Optional[str]
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class ChoiceDeltaToolCall(BaseModel):
|
|||
search_recommend (Optional[SearchRecommend]): Search recommendations
|
||||
type (Optional[str]): Type of the tool call
|
||||
"""
|
||||
|
||||
index: int
|
||||
id: Optional[str] = None
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class ChoiceDelta(BaseModel):
|
|||
role (Optional[str]): The role of the message sender
|
||||
tool_calls (Optional[List[ChoiceDeltaToolCall]]): List of tool call deltas
|
||||
"""
|
||||
|
||||
role: Optional[str] = None
|
||||
tool_calls: Optional[List[ChoiceDeltaToolCall]] = None
|
||||
|
||||
|
|
@ -46,6 +48,7 @@ class Choice(BaseModel):
|
|||
finish_reason (Optional[str]): Reason why the generation finished
|
||||
index (int): Index of this choice in the response
|
||||
"""
|
||||
|
||||
delta: ChoiceDelta
|
||||
finish_reason: Optional[str] = None
|
||||
index: int
|
||||
|
|
@ -60,6 +63,7 @@ class WebSearchChunk(BaseModel):
|
|||
choices (List[Choice]): List of choices in this chunk
|
||||
created (Optional[int]): Timestamp when the chunk was created
|
||||
"""
|
||||
|
||||
id: Optional[str] = None
|
||||
choices: List[Choice]
|
||||
created: Optional[int] = None
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class VideoCreateParams(TypedDict, total=False):
|
|||
platform will generate default if not provided by client
|
||||
user_id (str): User ID
|
||||
"""
|
||||
|
||||
model: str
|
||||
prompt: str
|
||||
image_url: str | list[str] | dict
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class SearchIntentResp(BaseModel):
|
|||
intent (str): Determined intent type
|
||||
keywords (str): Search keywords
|
||||
"""
|
||||
|
||||
query: str
|
||||
intent: str
|
||||
keywords: str
|
||||
|
|
@ -30,6 +31,7 @@ class SearchResultResp(BaseModel):
|
|||
refer (str): Reference number [ref_1]
|
||||
publish_date (str): Publish date
|
||||
"""
|
||||
|
||||
title: str
|
||||
link: str
|
||||
content: str
|
||||
|
|
@ -50,6 +52,7 @@ class WebSearchResp(BaseModel):
|
|||
search_intent (Optional[SearchIntentResp]): Search intent response
|
||||
search_result (Optional[SearchResultResp]): Search result response
|
||||
"""
|
||||
|
||||
created: Optional[int] = None
|
||||
request_id: Optional[str] = None
|
||||
id: Optional[str] = None
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import logging.config
|
|||
import time
|
||||
|
||||
import zai
|
||||
from zai import ZaiClient, ZhipuAiClient
|
||||
from zai import ZaiClient
|
||||
|
||||
|
||||
def test_completions_sync(logging_conf):
|
||||
|
|
|
|||
|
|
@ -71,9 +71,12 @@ class TestZaiClientFileServer:
|
|||
|
||||
def test_delete_files(self, test_server):
|
||||
try:
|
||||
# Only delete files if they were successfully created
|
||||
if test_server.file_id1:
|
||||
delete1 = test_server.client.files.delete(file_id=test_server.file_id1)
|
||||
print(delete1)
|
||||
|
||||
if test_server.file_id2:
|
||||
delete2 = test_server.client.files.delete(file_id=test_server.file_id2)
|
||||
print(delete2)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,13 @@ from zai import ZaiClient
|
|||
|
||||
def test_completions_temp0(logging_conf):
|
||||
logging.config.dictConfig(logging_conf) # type: ignore
|
||||
client = ZaiClient(disable_token_cache=False) # Fill in your own API Key
|
||||
# Skip this test if no valid API key is provided
|
||||
import os
|
||||
if not os.environ.get('ZAI_API_KEY') or os.environ.get('ZAI_API_KEY') == '{your apikey}':
|
||||
import pytest
|
||||
pytest.skip("No valid API key provided for integration test")
|
||||
|
||||
client = ZaiClient(disable_token_cache=False)
|
||||
try:
|
||||
# Generate request_id
|
||||
request_id = time.time()
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import time
|
|||
import zai
|
||||
from zai import ZaiClient
|
||||
|
||||
|
||||
def test_chat_completion_with_thinking(logging_conf):
|
||||
logging.config.dictConfig(logging_conf) # type: ignore
|
||||
client = ZaiClient() # Fill in your own API Key
|
||||
|
|
@ -15,9 +16,7 @@ def test_chat_completion_with_thinking(logging_conf):
|
|||
response = client.chat.completions.create(
|
||||
request_id=request_id,
|
||||
model='glm-4.5',
|
||||
messages=[
|
||||
{'role': 'user', 'content': '请介绍一下Agent的原理,并给出详细的推理过程'}
|
||||
],
|
||||
messages=[{'role': 'user', 'content': '请介绍一下Agent的原理,并给出详细的推理过程'}],
|
||||
top_p=0.7,
|
||||
temperature=0.9,
|
||||
)
|
||||
|
|
@ -30,6 +29,7 @@ def test_chat_completion_with_thinking(logging_conf):
|
|||
except zai.core._errors.APIStatusError as err:
|
||||
print(err)
|
||||
|
||||
|
||||
def test_chat_completion_without_thinking(logging_conf):
|
||||
logging.config.dictConfig(logging_conf) # type: ignore
|
||||
client = ZaiClient() # Fill in your own API Key
|
||||
|
|
@ -40,14 +40,12 @@ def test_chat_completion_without_thinking(logging_conf):
|
|||
response = client.chat.completions.create(
|
||||
request_id=request_id,
|
||||
model='glm-4.5',
|
||||
messages=[
|
||||
{'role': 'user', 'content': '请介绍一下Agent的原理'}
|
||||
],
|
||||
messages=[{'role': 'user', 'content': '请介绍一下Agent的原理'}],
|
||||
top_p=0.7,
|
||||
temperature=0.9,
|
||||
thinking={
|
||||
"type": "disabled",
|
||||
}
|
||||
'type': 'disabled',
|
||||
},
|
||||
)
|
||||
print(response)
|
||||
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ def test_response_chat_model_cast(R: Type[BaseModel]) -> None:
|
|||
assert model.id == 'completion123'
|
||||
assert model.request_id == 'request456'
|
||||
assert model.model == 'model-name'
|
||||
assert model.created == None
|
||||
assert model.created is None
|
||||
assert isinstance(model.choices, list)
|
||||
assert isinstance(model.choices[0], ChatCompletionChoice)
|
||||
assert model.choices[0].index == 0
|
||||
|
|
@ -303,7 +303,7 @@ def test_response_file_list_model_cast(R: Type[BaseModel]) -> None:
|
|||
assert model.data[0].purpose == 'example purpose'
|
||||
assert model.data[0].status == 'uploaded'
|
||||
assert model.data[0].status_details == 'File uploaded successfully'
|
||||
assert model.has_more == True
|
||||
assert model.has_more
|
||||
|
||||
|
||||
@pytest.mark.parametrize('R', [ImagesResponded])
|
||||
|
|
|
|||
|
|
@ -1,35 +1,39 @@
|
|||
from zai.types.agents.agents_completion import AgentsCompletion, AgentsError, AgentsCompletionChoice, AgentsCompletionMessage, AgentsCompletionUsage
|
||||
from zai.types.agents.agents_completion import (
|
||||
AgentsCompletion,
|
||||
AgentsCompletionChoice,
|
||||
AgentsCompletionMessage,
|
||||
AgentsCompletionUsage,
|
||||
AgentsError,
|
||||
)
|
||||
|
||||
|
||||
def test_agents_completion_error_field():
|
||||
|
||||
# 构造一个 AgentsError
|
||||
error = AgentsError(code="404", message="Not Found")
|
||||
error = AgentsError(code='404', message='Not Found')
|
||||
|
||||
# 构造一个完整的 AgentsCompletion
|
||||
completion = AgentsCompletion(
|
||||
agent_id="test_agent",
|
||||
conversation_id="conv_1",
|
||||
status="failed",
|
||||
agent_id='test_agent',
|
||||
conversation_id='conv_1',
|
||||
status='failed',
|
||||
choices=[
|
||||
AgentsCompletionChoice(
|
||||
index=0,
|
||||
finish_reason="error",
|
||||
message=AgentsCompletionMessage(content="error", role="system")
|
||||
index=0, finish_reason='error', message=AgentsCompletionMessage(content='error', role='system')
|
||||
)
|
||||
],
|
||||
request_id="req_1",
|
||||
id="id_1",
|
||||
request_id='req_1',
|
||||
id='id_1',
|
||||
usage=AgentsCompletionUsage(prompt_tokens=1, completion_tokens=1, total_tokens=2),
|
||||
error=error
|
||||
error=error,
|
||||
)
|
||||
|
||||
# 检查 error 字段是否为 AgentsError 实例
|
||||
assert isinstance(completion.error, AgentsError)
|
||||
assert completion.error.code == "404"
|
||||
assert completion.error.message == "Not Found"
|
||||
assert completion.error.code == '404'
|
||||
assert completion.error.message == 'Not Found'
|
||||
|
||||
# 检查序列化
|
||||
as_dict = completion.model_dump()
|
||||
assert as_dict["error"]["code"] == "404"
|
||||
assert as_dict["error"]["message"] == "Not Found"
|
||||
print("test_agents_completion_error_field passed.")
|
||||
assert as_dict['error']['code'] == '404'
|
||||
assert as_dict['error']['message'] == 'Not Found'
|
||||
print('test_agents_completion_error_field passed.')
|
||||
|
|
|
|||
Loading…
Reference in a new issue