chore: lint fix and test coverage (#19)

Co-authored-by: zhengweijun <weijun.zheng@aminer.cn>
This commit is contained in:
wellenzheng 2025-07-27 14:03:32 +08:00 committed by GitHub
parent f6ec3f2189
commit e8a26d53e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
51 changed files with 319 additions and 267 deletions

View file

@ -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,12 +206,14 @@ 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):
return 'https://open.bigmodel.cn/api/paas/v4'
return 'https://open.bigmodel.cn/api/paas/v4'

View file

@ -30,10 +30,11 @@ if TYPE_CHECKING:
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 @@ class Audio(BaseAPI):
) -> 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 @@ class Audio(BaseAPI):
) -> 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

View file

@ -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)
@ -54,7 +54,7 @@ class Transcriptions(BaseAPI):
) -> Completion | StreamResponse[ChatCompletionChunk]:
"""
Transcribe audio files to text
Arguments:
file (FileTypes): Audio file to transcribe
model (str): The model to use for transcription

View file

@ -1,3 +1,3 @@
from .batches import Batches
__all__ = ["Batches"]
__all__ = ['Batches']

View file

@ -6,4 +6,4 @@ __all__ = [
'AsyncCompletions',
'Chat',
'Completions',
]
]

View file

@ -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 @@ class AsyncCompletions(BaseAPI):
) -> 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 @@ 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',
@ -145,7 +146,7 @@ class AsyncCompletions(BaseAPI):
) -> 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

View file

@ -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)

View file

@ -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(

View file

@ -1,3 +1,3 @@
from .embeddings import Embeddings
__all__ = ['Embeddings']
__all__ = ['Embeddings']

View file

@ -18,6 +18,7 @@ class Embeddings(BaseAPI):
Attributes:
client (ZaiClient): The ZAI client instance
"""
def __init__(self, client: 'ZaiClient') -> None:
super().__init__(client)

View file

@ -1,3 +1,3 @@
from .files import Files, FilesWithRawResponse
__all__ = ['Files', 'FilesWithRawResponse']
__all__ = ['Files', 'FilesWithRawResponse']

View file

@ -1,3 +1,3 @@
from .images import Images
__all__ = ['Images']
__all__ = ['Images']

View file

@ -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 @@ class Images(BaseAPI):
) -> ImagesResponded:
"""
Generate images from text prompts
Arguments:
prompt (str): Text description of the desired image
model (str): The model to use for image generation

View file

@ -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 @@ class Moderations(BaseAPI):
) -> Completion:
"""
Moderate content for safety and compliance
Arguments:
model (str): The moderation model to use
input (Union[str, List[str], Dict]): Content to moderate

View file

@ -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 @@ class Tools(BaseAPI):
) -> 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

View file

@ -1,6 +1,6 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Optional, List
from typing import TYPE_CHECKING, List, Optional
import httpx

View file

@ -16,6 +16,7 @@ class BaseAPI:
Attributes:
_client (ZaiClient): The client instance for making API requests
"""
_client: ZaiClient
def __init__(self, client: ZaiClient) -> None:

View file

@ -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)

View file

@ -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:

View file

@ -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,

View file

@ -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,

View file

@ -4,12 +4,12 @@ from .agents_completion_chunk import AgentsCompletionUsage as AgentsCompletionCh
from .chat_completions_create_param import Reference
__all__ = [
'AgentsCompletion',
'AgentsCompletionUsage',
'AgentsCompletionChunkUsage',
'AgentsCompletionChunk',
'AgentsChoice',
'AgentsChoiceDelta',
'AgentsError',
'Reference',
'AgentsCompletion',
'AgentsCompletionUsage',
'AgentsCompletionChunkUsage',
'AgentsCompletionChunk',
'AgentsChoice',
'AgentsChoiceDelta',
'AgentsError',
'Reference',
]

View file

@ -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

View file

@ -2,33 +2,33 @@ from .assistant_completion import AssistantChoice, AssistantCompletion, Completi
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',
]

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -6,10 +6,10 @@ from .tools_type import ToolsType
from .web_browser_delta_block import WebBrowserToolBlock
__all__ = [
'CodeInterpreterToolBlock',
'DrawingToolBlock',
'FunctionToolBlock',
'RetrievalToolBlock',
'WebBrowserToolBlock',
'ToolsType',
]
'CodeInterpreterToolBlock',
'DrawingToolBlock',
'FunctionToolBlock',
'RetrievalToolBlock',
'WebBrowserToolBlock',
'ToolsType',
]

View file

@ -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

View file

@ -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

View file

@ -5,10 +5,10 @@ from .batch_list_params import BatchListParams
from .batch_request_counts import BatchRequestCounts
__all__ = [
'Batch',
'Errors',
'BatchCreateParams',
'BatchError',
'BatchListParams',
'BatchRequestCounts',
]
'Batch',
'Errors',
'BatchCreateParams',
'BatchError',
'BatchListParams',
'BatchRequestCounts',
]

View file

@ -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',
]

View file

@ -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

View file

@ -6,11 +6,12 @@ from zai.core import BaseModel
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]

View file

@ -6,11 +6,12 @@ from zai.core import BaseModel
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

View file

@ -1,6 +1,6 @@
from .embeddings import Embedding, EmbeddingsResponded
__all__ = [
'Embedding',
'EmbeddingsResponded',
]
'Embedding',
'EmbeddingsResponded',
]

View file

@ -11,7 +11,7 @@ from zai.types.files.upload_detail import UploadDetail
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']]

View file

@ -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

View file

@ -1,6 +1,6 @@
from .image import GeneratedImage, ImagesResponded
__all__ = [
'GeneratedImage',
'ImagesResponded',
]
'GeneratedImage',
'ImagesResponded',
]

View file

@ -6,10 +6,11 @@ from zai.core import BaseModel
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

View file

@ -6,7 +6,7 @@ from typing_extensions import TypedDict
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]

View file

@ -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',
]

View file

@ -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

View file

@ -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

View file

@ -4,17 +4,18 @@ from zai.core import BaseModel
class SearchIntentResp(BaseModel):
"""
Search intent response
"""
Search intent response
Attributes:
query (str): Search optimized query
intent (str): Determined intent type
keywords (str): Search keywords
"""
query: str
intent: str
keywords: str
Attributes:
query (str): Search optimized query
intent (str): Determined intent type
keywords (str): Search keywords
"""
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

View file

@ -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):

View file

@ -71,11 +71,14 @@ class TestZaiClientFileServer:
def test_delete_files(self, test_server):
try:
delete1 = test_server.client.files.delete(file_id=test_server.file_id1)
print(delete1)
# 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)
delete2 = test_server.client.files.delete(file_id=test_server.file_id2)
print(delete2)
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)

View file

@ -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()

View file

@ -5,55 +5,53 @@ 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
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)
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)

View file

@ -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])

View file

@ -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')
# 构造一个 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.")
# 检查序列化
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.')