diff --git a/src/zai/_client.py b/src/zai/_client.py index 390efaa..5ee4be3 100644 --- a/src/zai/_client.py +++ b/src/zai/_client.py @@ -31,6 +31,7 @@ _jwt_token, ) + class BaseClient(HttpClient): """ Main client for interacting with the ZAI API @@ -92,6 +93,7 @@ def __init__( self.base_url = base_url from ._version import __version__ + super().__init__( version=__version__, base_url=base_url, @@ -104,7 +106,7 @@ def __init__( @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,12 +206,14 @@ def __del__(self) -> None: 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): - return 'https://open.bigmodel.cn/api/paas/v4' \ No newline at end of file + return 'https://open.bigmodel.cn/api/paas/v4' diff --git a/src/zai/api_resource/audio/audio.py b/src/zai/api_resource/audio/audio.py index a98108a..3ec6c91 100644 --- a/src/zai/api_resource/audio/audio.py +++ b/src/zai/api_resource/audio/audio.py @@ -30,10 +30,11 @@ class Audio(BaseAPI): """ API resource for audio operations - + Attributes: transcriptions (Transcriptions): Audio transcription operations """ + @cached_property def transcriptions(self) -> Transcriptions: return Transcriptions(self._client) @@ -57,7 +58,7 @@ def speech( ) -> HttpxBinaryResponseContent: """ Generate speech audio from text input - + Arguments: model (str): The model to use for speech generation input (str): The text to convert to speech @@ -105,7 +106,7 @@ def customization( ) -> HttpxBinaryResponseContent: """ Generate customized speech audio with voice cloning - + Arguments: model (str): The model to use for speech generation input (str): The text to convert to speech diff --git a/src/zai/api_resource/audio/transcriptions.py b/src/zai/api_resource/audio/transcriptions.py index 5b1d371..5eff96d 100644 --- a/src/zai/api_resource/audio/transcriptions.py +++ b/src/zai/api_resource/audio/transcriptions.py @@ -30,11 +30,11 @@ from zai._client import ZaiClient - class Transcriptions(BaseAPI): """ API resource for audio transcription operations """ + def __init__(self, client: 'ZaiClient') -> None: super().__init__(client) @@ -54,7 +54,7 @@ def create( ) -> Completion | StreamResponse[ChatCompletionChunk]: """ Transcribe audio files to text - + Arguments: file (FileTypes): Audio file to transcribe model (str): The model to use for transcription diff --git a/src/zai/api_resource/batch/__init__.py b/src/zai/api_resource/batch/__init__.py index af38eb2..0730b48 100644 --- a/src/zai/api_resource/batch/__init__.py +++ b/src/zai/api_resource/batch/__init__.py @@ -1,3 +1,3 @@ from .batches import Batches -__all__ = ["Batches"] \ No newline at end of file +__all__ = ['Batches'] diff --git a/src/zai/api_resource/chat/__init__.py b/src/zai/api_resource/chat/__init__.py index 01fc412..34d66bd 100644 --- a/src/zai/api_resource/chat/__init__.py +++ b/src/zai/api_resource/chat/__init__.py @@ -6,4 +6,4 @@ 'AsyncCompletions', 'Chat', 'Completions', -] \ No newline at end of file +] diff --git a/src/zai/api_resource/chat/async_completions.py b/src/zai/api_resource/chat/async_completions.py index 9f3980e..ec632ea 100644 --- a/src/zai/api_resource/chat/async_completions.py +++ b/src/zai/api_resource/chat/async_completions.py @@ -32,6 +32,7 @@ class AsyncCompletions(BaseAPI): Provides access to asynchronous chat completion operations. """ + def __init__(self, client: 'ZaiClient') -> None: super().__init__(client) @@ -61,7 +62,7 @@ def create( ) -> AsyncTaskStatus: """ Create an asynchronous chat completion task - + Arguments: model (str): Model name to use for completion request_id (Optional[str]): Request identifier @@ -125,8 +126,8 @@ def create( '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', @@ -145,7 +146,7 @@ def retrieve_completion_result( ) -> Union[AsyncCompletion, AsyncTaskStatus]: """ Retrieve the result of an asynchronous chat completion task - + Arguments: id (str): The task ID to retrieve results for extra_headers (Headers): Additional HTTP headers diff --git a/src/zai/api_resource/chat/chat.py b/src/zai/api_resource/chat/chat.py index 745bd25..033ea41 100644 --- a/src/zai/api_resource/chat/chat.py +++ b/src/zai/api_resource/chat/chat.py @@ -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) diff --git a/src/zai/api_resource/chat/completions.py b/src/zai/api_resource/chat/completions.py index 1c02424..9aa0bb8 100644 --- a/src/zai/api_resource/chat/completions.py +++ b/src/zai/api_resource/chat/completions.py @@ -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 @@ def create( 'meta': meta, 'extra': maybe_transform(extra, code_geex_params.CodeGeexExtra), 'response_format': response_format, - "thinking": thinking + 'thinking': thinking, } ) return self._post( diff --git a/src/zai/api_resource/embeddings/__init__.py b/src/zai/api_resource/embeddings/__init__.py index 63ed16d..e6a7320 100644 --- a/src/zai/api_resource/embeddings/__init__.py +++ b/src/zai/api_resource/embeddings/__init__.py @@ -1,3 +1,3 @@ from .embeddings import Embeddings -__all__ = ['Embeddings'] \ No newline at end of file +__all__ = ['Embeddings'] diff --git a/src/zai/api_resource/embeddings/embeddings.py b/src/zai/api_resource/embeddings/embeddings.py index 1a1d462..5b8f26f 100644 --- a/src/zai/api_resource/embeddings/embeddings.py +++ b/src/zai/api_resource/embeddings/embeddings.py @@ -18,6 +18,7 @@ class Embeddings(BaseAPI): Attributes: client (ZaiClient): The ZAI client instance """ + def __init__(self, client: 'ZaiClient') -> None: super().__init__(client) diff --git a/src/zai/api_resource/files/__init__.py b/src/zai/api_resource/files/__init__.py index f0afffe..4aa4a17 100644 --- a/src/zai/api_resource/files/__init__.py +++ b/src/zai/api_resource/files/__init__.py @@ -1,3 +1,3 @@ from .files import Files, FilesWithRawResponse -__all__ = ['Files', 'FilesWithRawResponse'] \ No newline at end of file +__all__ = ['Files', 'FilesWithRawResponse'] diff --git a/src/zai/api_resource/images/__init__.py b/src/zai/api_resource/images/__init__.py index a28a491..b603f0d 100644 --- a/src/zai/api_resource/images/__init__.py +++ b/src/zai/api_resource/images/__init__.py @@ -1,3 +1,3 @@ from .images import Images -__all__ = ['Images'] \ No newline at end of file +__all__ = ['Images'] diff --git a/src/zai/api_resource/images/images.py b/src/zai/api_resource/images/images.py index 807a07a..bda7556 100644 --- a/src/zai/api_resource/images/images.py +++ b/src/zai/api_resource/images/images.py @@ -16,6 +16,7 @@ class Images(BaseAPI): """ API resource for image generation operations """ + def __init__(self, client: 'ZaiClient') -> None: super().__init__(client) @@ -40,7 +41,7 @@ def generations( ) -> ImagesResponded: """ Generate images from text prompts - + Arguments: prompt (str): Text description of the desired image model (str): The model to use for image generation diff --git a/src/zai/api_resource/moderations/moderations.py b/src/zai/api_resource/moderations/moderations.py index 9468071..642043d 100644 --- a/src/zai/api_resource/moderations/moderations.py +++ b/src/zai/api_resource/moderations/moderations.py @@ -16,6 +16,7 @@ class Moderations(BaseAPI): """ API resource for content moderation operations """ + def __init__(self, client: ZaiClient) -> None: super().__init__(client) @@ -27,7 +28,7 @@ def create( ) -> Completion: """ Moderate content for safety and compliance - + Arguments: model (str): The moderation model to use input (Union[str, List[str], Dict]): Content to moderate diff --git a/src/zai/api_resource/tools/tools.py b/src/zai/api_resource/tools/tools.py index c19a402..023afe8 100644 --- a/src/zai/api_resource/tools/tools.py +++ b/src/zai/api_resource/tools/tools.py @@ -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) @@ -50,7 +51,7 @@ def web_search( ) -> WebSearch | StreamResponse[WebSearchChunk]: """ Perform web search using AI models - + Arguments: model (str): The model to use for web search request_id (Optional[str]): Unique identifier for the request diff --git a/src/zai/api_resource/videos/videos.py b/src/zai/api_resource/videos/videos.py index fc0298d..c4525de 100644 --- a/src/zai/api_resource/videos/videos.py +++ b/src/zai/api_resource/videos/videos.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, List +from typing import TYPE_CHECKING, List, Optional import httpx diff --git a/src/zai/core/_base_api.py b/src/zai/core/_base_api.py index 4021119..7f7c93c 100644 --- a/src/zai/core/_base_api.py +++ b/src/zai/core/_base_api.py @@ -16,6 +16,7 @@ class BaseAPI: Attributes: _client (ZaiClient): The client instance for making API requests """ + _client: ZaiClient def __init__(self, client: ZaiClient) -> None: diff --git a/src/zai/core/_errors.py b/src/zai/core/_errors.py index ad32a83..24cfb08 100644 --- a/src/zai/core/_errors.py +++ b/src/zai/core/_errors.py @@ -83,9 +83,7 @@ def __init__( 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) diff --git a/src/zai/core/_files.py b/src/zai/core/_files.py index 5dcc232..7fce884 100644 --- a/src/zai/core/_files.py +++ b/src/zai/core/_files.py @@ -20,20 +20,13 @@ 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: diff --git a/src/zai/core/_jwt_token.py b/src/zai/core/_jwt_token.py index 4f7db0b..f9c3eef 100644 --- a/src/zai/core/_jwt_token.py +++ b/src/zai/core/_jwt_token.py @@ -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, diff --git a/src/zai/core/logs.py b/src/zai/core/logs.py index fd390a4..22ae915 100644 --- a/src/zai/core/logs.py +++ b/src/zai/core/logs.py @@ -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, diff --git a/src/zai/types/agents/__init__.py b/src/zai/types/agents/__init__.py index 78592e0..5367802 100644 --- a/src/zai/types/agents/__init__.py +++ b/src/zai/types/agents/__init__.py @@ -4,12 +4,12 @@ from .chat_completions_create_param import Reference __all__ = [ - 'AgentsCompletion', - 'AgentsCompletionUsage', - 'AgentsCompletionChunkUsage', - 'AgentsCompletionChunk', - 'AgentsChoice', - 'AgentsChoiceDelta', - 'AgentsError', - 'Reference', + 'AgentsCompletion', + 'AgentsCompletionUsage', + 'AgentsCompletionChunkUsage', + 'AgentsCompletionChunk', + 'AgentsChoice', + 'AgentsChoiceDelta', + 'AgentsError', + 'Reference', ] diff --git a/src/zai/types/agents/agents_completion_chunk.py b/src/zai/types/agents/agents_completion_chunk.py index 5612e75..715c534 100644 --- a/src/zai/types/agents/agents_completion_chunk.py +++ b/src/zai/types/agents/agents_completion_chunk.py @@ -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 diff --git a/src/zai/types/assistant/__init__.py b/src/zai/types/assistant/__init__.py index affbe47..8fc98d3 100644 --- a/src/zai/types/assistant/__init__.py +++ b/src/zai/types/assistant/__init__.py @@ -2,33 +2,33 @@ from .assistant_conversation_params import ConversationParameters from .assistant_conversation_resp import ConversationUsage, ConversationUsageList, ConversationUsageListResp, Usage from .assistant_create_params import ( - AssistantAttachments, - AssistantParameters, - ConversationMessage, - ExtraParameters, - MessageContent, - MessageTextContent, - TranslateParameters, + AssistantAttachments, + AssistantParameters, + ConversationMessage, + ExtraParameters, + MessageContent, + MessageTextContent, + TranslateParameters, ) from .assistant_support_resp import AssistantSupport, AssistantSupportResp __all__ = [ - 'AssistantCompletion', - 'CompletionUsage', - 'ErrorInfo', - 'AssistantChoice', - 'ConversationUsageListResp', - 'ConversationUsage', - 'ConversationUsageList', - 'Usage', - 'AssistantSupportResp', - 'AssistantSupport', - 'AssistantAttachments', - 'MessageTextContent', - 'MessageContent', - 'ConversationMessage', - 'AssistantParameters', - 'TranslateParameters', - 'ExtraParameters', - 'ConversationParameters', + 'AssistantCompletion', + 'CompletionUsage', + 'ErrorInfo', + 'AssistantChoice', + 'ConversationUsageListResp', + 'ConversationUsage', + 'ConversationUsageList', + 'Usage', + 'AssistantSupportResp', + 'AssistantSupport', + 'AssistantAttachments', + 'MessageTextContent', + 'MessageContent', + 'ConversationMessage', + 'AssistantParameters', + 'TranslateParameters', + 'ExtraParameters', + 'ConversationParameters', ] diff --git a/src/zai/types/assistant/assistant_completion.py b/src/zai/types/assistant/assistant_completion.py index 71bfd88..68d0cd4 100644 --- a/src/zai/types/assistant/assistant_completion.py +++ b/src/zai/types/assistant/assistant_completion.py @@ -62,7 +62,7 @@ class AssistantCompletion(BaseModel): assistant_id (str): Assistant identifier created (int): Request creation time as Unix timestamp status (str): Response status (completed: generation finished, - in_progress: generating, failed: generation exception) + in_progress: generating, failed: generation exception) last_error (Optional[ErrorInfo]): Error information if generation failed choices (List[AssistantChoice]): List of response choices with incremental information metadata (Optional[Dict[str, Any]]): Optional metadata extension field diff --git a/src/zai/types/assistant/assistant_conversation_resp.py b/src/zai/types/assistant/assistant_conversation_resp.py index bd56866..c97f2b7 100644 --- a/src/zai/types/assistant/assistant_conversation_resp.py +++ b/src/zai/types/assistant/assistant_conversation_resp.py @@ -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 diff --git a/src/zai/types/assistant/assistant_support_resp.py b/src/zai/types/assistant/assistant_support_resp.py index 9275ce9..82d3b63 100644 --- a/src/zai/types/assistant/assistant_support_resp.py +++ b/src/zai/types/assistant/assistant_support_resp.py @@ -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] diff --git a/src/zai/types/assistant/message/tools/__init__.py b/src/zai/types/assistant/message/tools/__init__.py index e5bbdc5..98529b5 100644 --- a/src/zai/types/assistant/message/tools/__init__.py +++ b/src/zai/types/assistant/message/tools/__init__.py @@ -6,10 +6,10 @@ from .web_browser_delta_block import WebBrowserToolBlock __all__ = [ - 'CodeInterpreterToolBlock', - 'DrawingToolBlock', - 'FunctionToolBlock', - 'RetrievalToolBlock', - 'WebBrowserToolBlock', - 'ToolsType', -] \ No newline at end of file + 'CodeInterpreterToolBlock', + 'DrawingToolBlock', + 'FunctionToolBlock', + 'RetrievalToolBlock', + 'WebBrowserToolBlock', + 'ToolsType', +] diff --git a/src/zai/types/audio/audio_customization_param.py b/src/zai/types/audio/audio_customization_param.py index 3a038bf..f34798d 100644 --- a/src/zai/types/audio/audio_customization_param.py +++ b/src/zai/types/audio/audio_customization_param.py @@ -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 diff --git a/src/zai/types/audio/audio_speech_params.py b/src/zai/types/audio/audio_speech_params.py index 0a0d160..c8eb538 100644 --- a/src/zai/types/audio/audio_speech_params.py +++ b/src/zai/types/audio/audio_speech_params.py @@ -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 diff --git a/src/zai/types/batch/__init__.py b/src/zai/types/batch/__init__.py index 09c3bb1..384f067 100644 --- a/src/zai/types/batch/__init__.py +++ b/src/zai/types/batch/__init__.py @@ -5,10 +5,10 @@ from .batch_request_counts import BatchRequestCounts __all__ = [ - 'Batch', - 'Errors', - 'BatchCreateParams', - 'BatchError', - 'BatchListParams', - 'BatchRequestCounts', -] \ No newline at end of file + 'Batch', + 'Errors', + 'BatchCreateParams', + 'BatchError', + 'BatchListParams', + 'BatchRequestCounts', +] diff --git a/src/zai/types/chat/__init__.py b/src/zai/types/chat/__init__.py index e3ae5e0..15a58f8 100644 --- a/src/zai/types/chat/__init__.py +++ b/src/zai/types/chat/__init__.py @@ -1,44 +1,44 @@ from .async_chat_completion import AsyncCompletion, AsyncTaskStatus from .chat_completion import ( - Completion, - CompletionChoice, - CompletionMessage, - CompletionMessageToolCall, - CompletionUsage, - Function, + Completion, + CompletionChoice, + CompletionMessage, + CompletionMessageToolCall, + CompletionUsage, + Function, ) from .chat_completion_chunk import ( - AudioCompletionChunk, - ChatCompletionChunk, - Choice, - ChoiceDelta, - ChoiceDeltaFunctionCall, - ChoiceDeltaToolCall, - ChoiceDeltaToolCallFunction, + AudioCompletionChunk, + ChatCompletionChunk, + Choice, + ChoiceDelta, + ChoiceDeltaFunctionCall, + ChoiceDeltaToolCall, + ChoiceDeltaToolCallFunction, ) from .chat_completion_chunk import CompletionUsage as CompletionChunkUsage from .chat_completions_create_param import Reference from .code_geex.code_geex_params import CodeGeexContext, CodeGeexExtra, CodeGeexTarget __all__ = [ - 'AsyncTaskStatus', - 'AsyncCompletion', - 'Completion', - 'CompletionUsage', - 'Function', - 'CompletionMessageToolCall', - 'CompletionMessage', - 'CompletionChoice', - 'ChatCompletionChunk', - 'CompletionChunkUsage', - 'Choice', - 'ChoiceDelta', - 'ChoiceDeltaFunctionCall', - 'ChoiceDeltaToolCall', - 'ChoiceDeltaToolCallFunction', - 'AudioCompletionChunk', - 'Reference', - 'CodeGeexTarget', - 'CodeGeexContext', - 'CodeGeexExtra', + 'AsyncTaskStatus', + 'AsyncCompletion', + 'Completion', + 'CompletionUsage', + 'Function', + 'CompletionMessageToolCall', + 'CompletionMessage', + 'CompletionChoice', + 'ChatCompletionChunk', + 'CompletionChunkUsage', + 'Choice', + 'ChoiceDelta', + 'ChoiceDeltaFunctionCall', + 'ChoiceDeltaToolCall', + 'ChoiceDeltaToolCallFunction', + 'AudioCompletionChunk', + 'Reference', + 'CodeGeexTarget', + 'CodeGeexContext', + 'CodeGeexExtra', ] diff --git a/src/zai/types/chat/async_chat_completion.py b/src/zai/types/chat/async_chat_completion.py index 1e25ce8..dcc4c06 100644 --- a/src/zai/types/chat/async_chat_completion.py +++ b/src/zai/types/chat/async_chat_completion.py @@ -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 diff --git a/src/zai/types/chat/chat_completion.py b/src/zai/types/chat/chat_completion.py index 3c7c64c..5966b8f 100644 --- a/src/zai/types/chat/chat_completion.py +++ b/src/zai/types/chat/chat_completion.py @@ -6,11 +6,12 @@ class Function(BaseModel): """ Function call information - + Attributes: arguments: Function call arguments name: Function name """ + arguments: str name: str @@ -18,12 +19,13 @@ class Function(BaseModel): class CompletionMessageToolCall(BaseModel): """ Tool call information in completion message - + Attributes: id: Unique identifier for the tool call function: Function call information type: Type of the tool call """ + id: str function: Function type: str @@ -32,13 +34,14 @@ class CompletionMessageToolCall(BaseModel): class CompletionMessage(BaseModel): """ Completion message information - + Attributes: content: Message content role: Role of the message sender 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,12 +66,14 @@ class CompletionTokensDetails(BaseModel): Attributes: reasoning_tokens: Number of tokens used for reasoning steps """ + reasoning_tokens: int + class CompletionUsage(BaseModel): """ Token usage information for completion - + Attributes: prompt_tokens: Number of tokens in the prompt prompt_tokens_details: Detailed breakdown of token usage for the input prompt @@ -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 @@ -84,12 +92,13 @@ class CompletionUsage(BaseModel): class CompletionChoice(BaseModel): """ Completion choice information - + Attributes: index: Index of the choice finish_reason: Reason why the completion finished message: Completion message """ + index: int finish_reason: str message: CompletionMessage @@ -98,7 +107,7 @@ class CompletionChoice(BaseModel): class Completion(BaseModel): """ Chat completion response - + Attributes: model: Model used for the completion created: Timestamp when the completion was created @@ -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] diff --git a/src/zai/types/chat/chat_completion_chunk.py b/src/zai/types/chat/chat_completion_chunk.py index 736189d..5bf19fc 100644 --- a/src/zai/types/chat/chat_completion_chunk.py +++ b/src/zai/types/chat/chat_completion_chunk.py @@ -6,11 +6,12 @@ class ChoiceDeltaFunctionCall(BaseModel): """ Function call delta information in streaming response - + Attributes: arguments: Function call arguments name: Function name """ + arguments: Optional[str] = None name: Optional[str] = None @@ -18,11 +19,12 @@ class ChoiceDeltaFunctionCall(BaseModel): class ChoiceDeltaToolCallFunction(BaseModel): """ Tool call function delta information in streaming response - + Attributes: arguments: Function call arguments name: Function name """ + arguments: Optional[str] = None name: Optional[str] = None @@ -30,13 +32,14 @@ class ChoiceDeltaToolCallFunction(BaseModel): class ChoiceDeltaToolCall(BaseModel): """ Tool call delta information in streaming response - + Attributes: index: Index of the tool call id: Unique identifier for the tool call function: Function call information type: Type of the tool call """ + index: int id: Optional[str] = None function: Optional[ChoiceDeltaToolCallFunction] = None @@ -46,12 +49,13 @@ class ChoiceDeltaToolCall(BaseModel): class AudioCompletionChunk(BaseModel): """ Audio completion chunk information - + Attributes: id: Unique identifier for the audio chunk data: Audio data content expires_at: Timestamp when the audio expires """ + id: Optional[str] = None data: Optional[str] = None expires_at: Optional[int] = None @@ -60,7 +64,7 @@ class AudioCompletionChunk(BaseModel): class ChoiceDelta(BaseModel): """ Delta information for streaming chat completion choice - + Attributes: content: Content delta role: Role of the message sender @@ -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 @@ -78,12 +83,13 @@ class ChoiceDelta(BaseModel): class Choice(BaseModel): """ Choice information in streaming chat completion - + Attributes: delta: Delta information for the choice finish_reason: Reason why the completion finished index: Index of the choice """ + delta: ChoiceDelta finish_reason: Optional[str] = None index: int @@ -92,12 +98,13 @@ class Choice(BaseModel): class CompletionUsage(BaseModel): """ Token usage information for completion - + Attributes: prompt_tokens: Number of tokens in the prompt completion_tokens: Number of tokens in the completion total_tokens: Total number of tokens used """ + prompt_tokens: int completion_tokens: int total_tokens: int @@ -106,7 +113,7 @@ class CompletionUsage(BaseModel): class ChatCompletionChunk(BaseModel): """ Streaming chat completion chunk response - + Attributes: id: Unique identifier for the completion choices: List of completion choices @@ -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 diff --git a/src/zai/types/embeddings/__init__.py b/src/zai/types/embeddings/__init__.py index 210e1e7..8b155a2 100644 --- a/src/zai/types/embeddings/__init__.py +++ b/src/zai/types/embeddings/__init__.py @@ -1,6 +1,6 @@ from .embeddings import Embedding, EmbeddingsResponded __all__ = [ - 'Embedding', - 'EmbeddingsResponded', -] \ No newline at end of file + 'Embedding', + 'EmbeddingsResponded', +] diff --git a/src/zai/types/files/file_create_params.py b/src/zai/types/files/file_create_params.py index 370d60b..8d0d165 100644 --- a/src/zai/types/files/file_create_params.py +++ b/src/zai/types/files/file_create_params.py @@ -11,7 +11,7 @@ class FileCreateParams(TypedDict, total=False): """ Parameters for creating a file upload - + Attributes: file: File to upload (one of file and upload_detail is required) upload_detail: Upload details for multiple files (one of file and upload_detail is required) @@ -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']] diff --git a/src/zai/types/files/file_object.py b/src/zai/types/files/file_object.py index 1628b94..c4d9b4d 100644 --- a/src/zai/types/files/file_object.py +++ b/src/zai/types/files/file_object.py @@ -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 diff --git a/src/zai/types/image/__init__.py b/src/zai/types/image/__init__.py index 470c743..8046c7c 100644 --- a/src/zai/types/image/__init__.py +++ b/src/zai/types/image/__init__.py @@ -1,6 +1,6 @@ from .image import GeneratedImage, ImagesResponded __all__ = [ - 'GeneratedImage', - 'ImagesResponded', -] \ No newline at end of file + 'GeneratedImage', + 'ImagesResponded', +] diff --git a/src/zai/types/moderation/moderation_completion.py b/src/zai/types/moderation/moderation_completion.py index aff673b..a657d08 100644 --- a/src/zai/types/moderation/moderation_completion.py +++ b/src/zai/types/moderation/moderation_completion.py @@ -6,10 +6,11 @@ class Completion(BaseModel): """ Moderation completion response - + Attributes: 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 diff --git a/src/zai/types/sensitive_word_check/sensitive_word_check.py b/src/zai/types/sensitive_word_check/sensitive_word_check.py index 505a267..5392b4a 100644 --- a/src/zai/types/sensitive_word_check/sensitive_word_check.py +++ b/src/zai/types/sensitive_word_check/sensitive_word_check.py @@ -6,7 +6,7 @@ class SensitiveWordCheckRequest(TypedDict, total=False): """ Sensitive word check request parameters - + Attributes: type: Sensitive word type, currently only supports ALL status: Sensitive word enable/disable status @@ -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] diff --git a/src/zai/types/tools/__init__.py b/src/zai/types/tools/__init__.py index 97a9eba..b7efc67 100644 --- a/src/zai/types/tools/__init__.py +++ b/src/zai/types/tools/__init__.py @@ -1,26 +1,26 @@ from .tools_web_search_params import WebSearchParams from .web_search import ( - SearchIntent, - SearchRecommend, - SearchResult, - WebSearch, - WebSearchChoice, - WebSearchMessage, - WebSearchMessageToolCall, + SearchIntent, + SearchRecommend, + SearchResult, + WebSearch, + WebSearchChoice, + WebSearchMessage, + WebSearchMessageToolCall, ) from .web_search_chunk import Choice, ChoiceDelta, ChoiceDeltaToolCall, WebSearchChunk __all__ = [ - 'WebSearch', - 'SearchIntent', - 'SearchResult', - 'SearchRecommend', - 'WebSearchMessageToolCall', - 'WebSearchMessage', - 'WebSearchChoice', - 'WebSearchChunk', - 'ChoiceDeltaToolCall', - 'ChoiceDelta', - 'Choice', - 'WebSearchParams', + 'WebSearch', + 'SearchIntent', + 'SearchResult', + 'SearchRecommend', + 'WebSearchMessageToolCall', + 'WebSearchMessage', + 'WebSearchChoice', + 'WebSearchChunk', + 'ChoiceDeltaToolCall', + 'ChoiceDelta', + 'Choice', + 'WebSearchParams', ] diff --git a/src/zai/types/tools/web_search_chunk.py b/src/zai/types/tools/web_search_chunk.py index 8239d22..d4677e6 100644 --- a/src/zai/types/tools/web_search_chunk.py +++ b/src/zai/types/tools/web_search_chunk.py @@ -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 diff --git a/src/zai/types/video/video_create_params.py b/src/zai/types/video/video_create_params.py index 197fe89..36618f9 100644 --- a/src/zai/types/video/video_create_params.py +++ b/src/zai/types/video/video_create_params.py @@ -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 diff --git a/src/zai/types/web_search/web_search_resp.py b/src/zai/types/web_search/web_search_resp.py index 190e756..b462529 100644 --- a/src/zai/types/web_search/web_search_resp.py +++ b/src/zai/types/web_search/web_search_resp.py @@ -4,17 +4,18 @@ class SearchIntentResp(BaseModel): - """ - Search intent response + """ + Search intent response + + Attributes: + query (str): Search optimized query + intent (str): Determined intent type + keywords (str): Search keywords + """ - Attributes: - query (str): Search optimized query - intent (str): Determined intent type - keywords (str): Search keywords - """ - query: str - intent: str - keywords: str + query: str + intent: str + keywords: str class SearchResultResp(BaseModel): @@ -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 diff --git a/tests/integration_tests/test_agents.py b/tests/integration_tests/test_agents.py index c5b7a5c..2ad8503 100644 --- a/tests/integration_tests/test_agents.py +++ b/tests/integration_tests/test_agents.py @@ -3,7 +3,7 @@ import time import zai -from zai import ZaiClient, ZhipuAiClient +from zai import ZaiClient def test_completions_sync(logging_conf): diff --git a/tests/integration_tests/test_file.py b/tests/integration_tests/test_file.py index 47af222..f69a071 100644 --- a/tests/integration_tests/test_file.py +++ b/tests/integration_tests/test_file.py @@ -71,11 +71,14 @@ def test_files_list(self, test_server): def test_delete_files(self, test_server): try: - delete1 = test_server.client.files.delete(file_id=test_server.file_id1) - print(delete1) - - delete2 = test_server.client.files.delete(file_id=test_server.file_id2) - print(delete2) + # 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) except zai.core._errors.APIRequestFailedError as err: print(err) diff --git a/tests/integration_tests/test_moderation.py b/tests/integration_tests/test_moderation.py index 74cccd9..48ebfe8 100644 --- a/tests/integration_tests/test_moderation.py +++ b/tests/integration_tests/test_moderation.py @@ -8,7 +8,13 @@ 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() diff --git a/tests/integration_tests/test_thinking.py b/tests/integration_tests/test_thinking.py index ee00148..65cebe2 100644 --- a/tests/integration_tests/test_thinking.py +++ b/tests/integration_tests/test_thinking.py @@ -5,55 +5,53 @@ 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 - try: - # Generate request_id - request_id = time.time() - print(f'request_id:{request_id}') - response = client.chat.completions.create( - request_id=request_id, - model='glm-4.5', - messages=[ - {'role': 'user', 'content': '请介绍一下Agent的原理,并给出详细的推理过程'} - ], - top_p=0.7, - temperature=0.9, - ) - print(response) + logging.config.dictConfig(logging_conf) # type: ignore + client = ZaiClient() # Fill in your own API Key + try: + # Generate request_id + request_id = time.time() + print(f'request_id:{request_id}') + response = client.chat.completions.create( + request_id=request_id, + model='glm-4.5', + messages=[{'role': 'user', 'content': '请介绍一下Agent的原理,并给出详细的推理过程'}], + top_p=0.7, + temperature=0.9, + ) + print(response) + + except zai.core._errors.APIRequestFailedError as err: + print(err) + except zai.core._errors.APIInternalError as err: + print(err) + except zai.core._errors.APIStatusError as err: + print(err) + - except zai.core._errors.APIRequestFailedError as err: - print(err) - except zai.core._errors.APIInternalError as err: - print(err) - 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 - try: - # Generate request_id - request_id = time.time() - print(f'request_id:{request_id}') - response = client.chat.completions.create( - request_id=request_id, - model='glm-4.5', - messages=[ - {'role': 'user', 'content': '请介绍一下Agent的原理'} - ], - top_p=0.7, - temperature=0.9, - thinking={ - "type": "disabled", - } - ) - print(response) + logging.config.dictConfig(logging_conf) # type: ignore + client = ZaiClient() # Fill in your own API Key + try: + # Generate request_id + request_id = time.time() + print(f'request_id:{request_id}') + response = client.chat.completions.create( + request_id=request_id, + model='glm-4.5', + messages=[{'role': 'user', 'content': '请介绍一下Agent的原理'}], + top_p=0.7, + temperature=0.9, + thinking={ + 'type': 'disabled', + }, + ) + print(response) - except zai.core._errors.APIRequestFailedError as err: - print(err) - except zai.core._errors.APIInternalError as err: - print(err) - except zai.core._errors.APIStatusError as err: - print(err) \ No newline at end of file + except zai.core._errors.APIRequestFailedError as err: + print(err) + except zai.core._errors.APIInternalError as err: + print(err) + except zai.core._errors.APIStatusError as err: + print(err) diff --git a/tests/unit_tests/response_model/test_response.py b/tests/unit_tests/response_model/test_response.py index 434b18d..5cfb865 100644 --- a/tests/unit_tests/response_model/test_response.py +++ b/tests/unit_tests/response_model/test_response.py @@ -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]) diff --git a/tests/unit_tests/test_agent.py b/tests/unit_tests/test_agent.py index 7cb6442..cb6f6ab 100644 --- a/tests/unit_tests/test_agent.py +++ b/tests/unit_tests/test_agent.py @@ -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") +def test_agents_completion_error_field(): + # 构造一个 AgentsError + error = AgentsError(code='404', message='Not Found') - # 构造一个完整的 AgentsCompletion - completion = AgentsCompletion( - agent_id="test_agent", - conversation_id="conv_1", - status="failed", - choices=[ - AgentsCompletionChoice( - index=0, - finish_reason="error", - message=AgentsCompletionMessage(content="error", role="system") - ) - ], - request_id="req_1", - id="id_1", - usage=AgentsCompletionUsage(prompt_tokens=1, completion_tokens=1, total_tokens=2), - error=error - ) + # 构造一个完整的 AgentsCompletion + completion = AgentsCompletion( + agent_id='test_agent', + conversation_id='conv_1', + status='failed', + choices=[ + AgentsCompletionChoice( + index=0, finish_reason='error', message=AgentsCompletionMessage(content='error', role='system') + ) + ], + request_id='req_1', + id='id_1', + usage=AgentsCompletionUsage(prompt_tokens=1, completion_tokens=1, total_tokens=2), + error=error, + ) - # 检查 error 字段是否为 AgentsError 实例 - assert isinstance(completion.error, AgentsError) - assert completion.error.code == "404" - assert completion.error.message == "Not Found" + # 检查 error 字段是否为 AgentsError 实例 + assert isinstance(completion.error, AgentsError) + 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.") \ No newline at end of file + # 检查序列化 + 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.')