agentscope-runtime 0.1.4__py3-none-any.whl → 0.1.5b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentscope_runtime/engine/agents/agentscope_agent/agent.py +3 -0
- agentscope_runtime/engine/deployers/__init__.py +13 -0
- agentscope_runtime/engine/deployers/adapter/responses/__init__.py +0 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_adapter_utils.py +2886 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_agent_adapter.py +51 -0
- agentscope_runtime/engine/deployers/adapter/responses/response_api_protocol_adapter.py +314 -0
- agentscope_runtime/engine/deployers/cli_fc_deploy.py +143 -0
- agentscope_runtime/engine/deployers/kubernetes_deployer.py +265 -0
- agentscope_runtime/engine/deployers/local_deployer.py +356 -501
- agentscope_runtime/engine/deployers/modelstudio_deployer.py +626 -0
- agentscope_runtime/engine/deployers/utils/__init__.py +0 -0
- agentscope_runtime/engine/deployers/utils/deployment_modes.py +14 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/__init__.py +8 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/docker_image_builder.py +429 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/dockerfile_generator.py +240 -0
- agentscope_runtime/engine/deployers/utils/docker_image_utils/runner_image_factory.py +297 -0
- agentscope_runtime/engine/deployers/utils/package_project_utils.py +932 -0
- agentscope_runtime/engine/deployers/utils/service_utils/__init__.py +9 -0
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_factory.py +504 -0
- agentscope_runtime/engine/deployers/utils/service_utils/fastapi_templates.py +157 -0
- agentscope_runtime/engine/deployers/utils/service_utils/process_manager.py +268 -0
- agentscope_runtime/engine/deployers/utils/service_utils/service_config.py +75 -0
- agentscope_runtime/engine/deployers/utils/service_utils/service_factory.py +220 -0
- agentscope_runtime/engine/deployers/utils/wheel_packager.py +389 -0
- agentscope_runtime/engine/helpers/agent_api_builder.py +651 -0
- agentscope_runtime/engine/runner.py +36 -10
- agentscope_runtime/engine/schemas/agent_schemas.py +70 -2
- agentscope_runtime/engine/schemas/embedding.py +37 -0
- agentscope_runtime/engine/schemas/modelstudio_llm.py +310 -0
- agentscope_runtime/engine/schemas/oai_llm.py +538 -0
- agentscope_runtime/engine/schemas/realtime.py +254 -0
- agentscope_runtime/engine/services/mem0_memory_service.py +124 -0
- agentscope_runtime/engine/services/memory_service.py +2 -1
- agentscope_runtime/engine/services/redis_session_history_service.py +4 -3
- agentscope_runtime/engine/services/session_history_service.py +4 -3
- agentscope_runtime/sandbox/manager/container_clients/kubernetes_client.py +555 -10
- agentscope_runtime/version.py +1 -1
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/METADATA +21 -4
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/RECORD +43 -16
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/entry_points.txt +1 -0
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/WHEEL +0 -0
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/licenses/LICENSE +0 -0
- {agentscope_runtime-0.1.4.dist-info → agentscope_runtime-0.1.5b1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,538 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# pylint:disable=not-an-iterable, redefined-builtin
|
|
3
|
+
|
|
4
|
+
import json
|
|
5
|
+
import time
|
|
6
|
+
import uuid
|
|
7
|
+
from typing import Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from openai.types.chat import ChatCompletion, ChatCompletionChunk
|
|
10
|
+
from openai.types.chat.chat_completion_stream_options_param import (
|
|
11
|
+
ChatCompletionStreamOptionsParam,
|
|
12
|
+
)
|
|
13
|
+
from pydantic import BaseModel, Field, model_validator
|
|
14
|
+
from typing_extensions import Annotated, Literal
|
|
15
|
+
|
|
16
|
+
from .agent_schemas import Role, Tool, FunctionCall
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def generate_tool_call_id(prefix: str = "call_") -> str:
|
|
20
|
+
# generate a random uuid
|
|
21
|
+
random_uuid = uuid.uuid4()
|
|
22
|
+
# replace uuid to string and remove '-', then get latest 22 characters
|
|
23
|
+
random_part = str(random_uuid).replace("-", "")[:22]
|
|
24
|
+
# add prefix
|
|
25
|
+
tool_call_id = f"{prefix}{random_part}"
|
|
26
|
+
return tool_call_id
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ImageMessageContent(BaseModel):
|
|
30
|
+
class ImageUrl(BaseModel):
|
|
31
|
+
"""
|
|
32
|
+
Model class for image prompt message content.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
url: str
|
|
36
|
+
"""Either a URL of the image or the base64 encoded image data."""
|
|
37
|
+
|
|
38
|
+
detail: Literal["auto", "low", "high"] = "low"
|
|
39
|
+
"""Specifies the detail level of the image."""
|
|
40
|
+
|
|
41
|
+
type: Literal["image_url"] = "image_url"
|
|
42
|
+
"""The type of the content part."""
|
|
43
|
+
|
|
44
|
+
image_url: ImageUrl
|
|
45
|
+
"""The image URL details."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TextMessageContent(BaseModel):
|
|
49
|
+
type: Literal["text"] = "text"
|
|
50
|
+
"""The type of the content part."""
|
|
51
|
+
|
|
52
|
+
text: str
|
|
53
|
+
"""The text content."""
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class AudioMessageContent(BaseModel):
|
|
57
|
+
class InputAudioDetail(BaseModel):
|
|
58
|
+
"""
|
|
59
|
+
Model class for audio prompt message content.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
base64_data: str = Field(
|
|
63
|
+
default="",
|
|
64
|
+
description="the base64 data of multi-modal file",
|
|
65
|
+
)
|
|
66
|
+
"""The base64 encoded audio data."""
|
|
67
|
+
|
|
68
|
+
format: str = Field(
|
|
69
|
+
default="mp3",
|
|
70
|
+
description="The format of the encoded audio data. supports "
|
|
71
|
+
"'wav' and 'mp3'.",
|
|
72
|
+
)
|
|
73
|
+
"""The format of the encoded audio data. Supports 'wav' and 'mp3'."""
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def data(self) -> str:
|
|
77
|
+
return f"data:{self.format};base64,{self.base64_data}"
|
|
78
|
+
|
|
79
|
+
type: Literal["input_audio"] = "input_audio"
|
|
80
|
+
"""The type of the content part."""
|
|
81
|
+
|
|
82
|
+
input_audio: InputAudioDetail
|
|
83
|
+
"""The input audio details."""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
ChatCompletionMessage = Annotated[
|
|
87
|
+
Union[TextMessageContent, ImageMessageContent, AudioMessageContent],
|
|
88
|
+
Field(discriminator="type"),
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ToolCall(BaseModel):
|
|
93
|
+
"""
|
|
94
|
+
Model class for assistant prompt message tool call.
|
|
95
|
+
"""
|
|
96
|
+
|
|
97
|
+
index: int = 0
|
|
98
|
+
"""The index of the tool call in the tool calls array."""
|
|
99
|
+
|
|
100
|
+
id: str
|
|
101
|
+
"""The ID of the tool call."""
|
|
102
|
+
|
|
103
|
+
type: Optional[str] = None
|
|
104
|
+
"""The type of the tool. Currently, only `function` is supported."""
|
|
105
|
+
|
|
106
|
+
function: FunctionCall
|
|
107
|
+
"""The function that the model called."""
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class OpenAIMessage(BaseModel):
|
|
111
|
+
"""
|
|
112
|
+
Model class for prompt message.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
role: str
|
|
116
|
+
"""The role of the messages author, should be in `user`,`system`,
|
|
117
|
+
'assistant', 'tool'."""
|
|
118
|
+
|
|
119
|
+
content: Optional[Union[str, List[ChatCompletionMessage]]] = None
|
|
120
|
+
"""The contents of the message.
|
|
121
|
+
|
|
122
|
+
Can be a string, a list of content parts for multimodal messages.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
name: Optional[str] = None
|
|
126
|
+
"""An optional name for the participant.
|
|
127
|
+
|
|
128
|
+
Provides the model information to differentiate between participants of the
|
|
129
|
+
same role.
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
tool_calls: Optional[List[ToolCall]] = None
|
|
133
|
+
"""The tool calls generated by the model, such as function calls."""
|
|
134
|
+
|
|
135
|
+
def get_text_content(self) -> Optional[str]:
|
|
136
|
+
"""
|
|
137
|
+
Extract the first text content from the message.
|
|
138
|
+
|
|
139
|
+
:return: First text string found in the content, or None if no text
|
|
140
|
+
content
|
|
141
|
+
"""
|
|
142
|
+
if self.content is None:
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
# Case 1: content is a simple string
|
|
146
|
+
if isinstance(self.content, str):
|
|
147
|
+
return self.content
|
|
148
|
+
# Case 2: content is a list
|
|
149
|
+
elif isinstance(self.content, list):
|
|
150
|
+
for item in self.content:
|
|
151
|
+
if hasattr(item, "type"):
|
|
152
|
+
if item.type == "text" and hasattr(item, "text"):
|
|
153
|
+
return item.text
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
def get_image_content(self) -> List[str]:
|
|
157
|
+
"""
|
|
158
|
+
Extract all image content (URLs or base64 data) from the message.
|
|
159
|
+
|
|
160
|
+
:return: List of image URLs or base64 encoded strings found in the
|
|
161
|
+
content
|
|
162
|
+
"""
|
|
163
|
+
images = []
|
|
164
|
+
|
|
165
|
+
if self.content is None:
|
|
166
|
+
return images
|
|
167
|
+
|
|
168
|
+
# Case 1: content is a simple string - no images
|
|
169
|
+
if isinstance(self.content, str):
|
|
170
|
+
return images
|
|
171
|
+
# Case 2: content is a list
|
|
172
|
+
elif isinstance(self.content, list):
|
|
173
|
+
for item in self.content:
|
|
174
|
+
if hasattr(item, "type"):
|
|
175
|
+
if item.type == "image_url" and hasattr(item, "image_url"):
|
|
176
|
+
if hasattr(item.image_url, "url"):
|
|
177
|
+
images.append(item.image_url.url)
|
|
178
|
+
|
|
179
|
+
return images
|
|
180
|
+
|
|
181
|
+
def get_audio_content(self) -> List[str]:
|
|
182
|
+
"""
|
|
183
|
+
Extract all audio content (URLs or base64 data) from the message.
|
|
184
|
+
|
|
185
|
+
:return: List of audio URLs or base64 encoded strings found in the
|
|
186
|
+
content
|
|
187
|
+
"""
|
|
188
|
+
audios = []
|
|
189
|
+
|
|
190
|
+
if self.content is None:
|
|
191
|
+
return audios
|
|
192
|
+
|
|
193
|
+
# Case 1: content is a simple string - no audios
|
|
194
|
+
if isinstance(self.content, str):
|
|
195
|
+
return audios
|
|
196
|
+
# Case 2: content is a list
|
|
197
|
+
elif isinstance(self.content, list):
|
|
198
|
+
for item in self.content:
|
|
199
|
+
if hasattr(item, "type"):
|
|
200
|
+
if item.type == "input_audio" and hasattr(
|
|
201
|
+
item,
|
|
202
|
+
"input_audio",
|
|
203
|
+
):
|
|
204
|
+
if hasattr(item.input_audio, "data"):
|
|
205
|
+
audios.append(item.input_audio.data)
|
|
206
|
+
elif hasattr(item.input_audio, "base64_data"):
|
|
207
|
+
# Construct data URL for audio
|
|
208
|
+
format_type = getattr(
|
|
209
|
+
item.input_audio,
|
|
210
|
+
"format",
|
|
211
|
+
"mp3",
|
|
212
|
+
)
|
|
213
|
+
audios.append(
|
|
214
|
+
f"data:{format_type};base64,"
|
|
215
|
+
f"{item.input_audio.base64_data}",
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return audios
|
|
219
|
+
|
|
220
|
+
def has_multimodal_content(self) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
Check if the message contains multimodal content (images, audio,
|
|
223
|
+
or video).
|
|
224
|
+
|
|
225
|
+
:return: True if the message contains non-text content, False otherwise
|
|
226
|
+
"""
|
|
227
|
+
return bool(
|
|
228
|
+
self.get_image_content() or self.get_audio_content(),
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
def get_content_summary(self) -> Dict[str, int]:
|
|
232
|
+
"""
|
|
233
|
+
Get a summary of different content types in the message.
|
|
234
|
+
|
|
235
|
+
:return: Dictionary with counts of different content types
|
|
236
|
+
"""
|
|
237
|
+
return {
|
|
238
|
+
"text_count": 1 if self.get_text_content() is not None else 0,
|
|
239
|
+
"image_count": len(self.get_image_content()),
|
|
240
|
+
"audio_count": len(self.get_audio_content()),
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
class UserMessage(OpenAIMessage):
|
|
245
|
+
"""
|
|
246
|
+
Model class for user prompt message.
|
|
247
|
+
"""
|
|
248
|
+
|
|
249
|
+
role: str = Role.USER
|
|
250
|
+
"""The role of the messages author, in this case `user`."""
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
class AssistantMessage(OpenAIMessage):
|
|
254
|
+
"""
|
|
255
|
+
Model class for assistant prompt message.
|
|
256
|
+
"""
|
|
257
|
+
|
|
258
|
+
role: str = Role.ASSISTANT
|
|
259
|
+
"""The role of the messages author, in this case `assistant`."""
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class SystemMessage(OpenAIMessage):
|
|
263
|
+
"""
|
|
264
|
+
Model class for system prompt message.
|
|
265
|
+
"""
|
|
266
|
+
|
|
267
|
+
role: str = Role.SYSTEM
|
|
268
|
+
"""The role of the messages author, in this case `system`."""
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
class ToolMessage(OpenAIMessage):
|
|
272
|
+
"""
|
|
273
|
+
Model class for tool prompt message.
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
role: str = Role.TOOL
|
|
277
|
+
"""The role of the messages author, in this case `tool`."""
|
|
278
|
+
|
|
279
|
+
tool_call_id: str
|
|
280
|
+
"""Tool call that this message is responding to."""
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class ResponseFormat(BaseModel):
|
|
284
|
+
class JsonSchema(BaseModel):
|
|
285
|
+
name: str
|
|
286
|
+
"""The name of the response format. """
|
|
287
|
+
|
|
288
|
+
description: Union[str, None] = None
|
|
289
|
+
"""A description of what the response format is for, used by the
|
|
290
|
+
model to determine how to respond in the format.
|
|
291
|
+
"""
|
|
292
|
+
|
|
293
|
+
schema_param: dict = Field(None, alias="schema")
|
|
294
|
+
"""The schema for the response format, described as a JSON Schema
|
|
295
|
+
object."""
|
|
296
|
+
|
|
297
|
+
strict: Union[bool, None] = False
|
|
298
|
+
"""Whether to enable strict schema adherence when generating the output
|
|
299
|
+
|
|
300
|
+
If set to true, the model will follow the exact schema defined in the
|
|
301
|
+
`schema` field. Only a subset of JSON Schema is supported when `strict`
|
|
302
|
+
is `true`. Learn more about Structured Outputs in the
|
|
303
|
+
[function calling guide](docs/guides/function-calling).
|
|
304
|
+
"""
|
|
305
|
+
|
|
306
|
+
type: Literal["text", "json_object", "json_schema"] = "text"
|
|
307
|
+
"""The type of response format being defined.
|
|
308
|
+
|
|
309
|
+
- `text`: The default response format, which can be either text or any
|
|
310
|
+
value needed.
|
|
311
|
+
- `json_object`: Enables JSON mode, which guarantees the message the model
|
|
312
|
+
generates is valid JSON.
|
|
313
|
+
- `json_schema`: Enables Structured Outputs which guarantees the model will
|
|
314
|
+
match your supplied JSON schema.
|
|
315
|
+
"""
|
|
316
|
+
|
|
317
|
+
json_schema: Optional[JsonSchema] = None
|
|
318
|
+
"""The JSON schema for the response format."""
|
|
319
|
+
|
|
320
|
+
@model_validator(mode="before")
|
|
321
|
+
def validate_schema(self, values: dict) -> dict:
|
|
322
|
+
if not isinstance(values, dict) or "type" not in values:
|
|
323
|
+
raise ValueError(f"Json schema not valid with type {type(values)}")
|
|
324
|
+
format_type = values.get("type")
|
|
325
|
+
json_schema = values.get("json_schema")
|
|
326
|
+
|
|
327
|
+
if format_type in ["text", "json_object"] and json_schema is not None:
|
|
328
|
+
raise ValueError(
|
|
329
|
+
f"Json schema is not allowed for type {format_type}",
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
if format_type == "json_schema":
|
|
333
|
+
if json_schema is None:
|
|
334
|
+
raise ValueError(
|
|
335
|
+
f"Json schema is required for type {format_type}",
|
|
336
|
+
)
|
|
337
|
+
return values
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class ToolChoiceInputFunction(BaseModel):
|
|
341
|
+
name: str
|
|
342
|
+
"""The name of the function to call."""
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class ToolChoice(BaseModel):
|
|
346
|
+
type: str
|
|
347
|
+
"""The type of the tool. Currently, only `function` is supported."""
|
|
348
|
+
|
|
349
|
+
function: ToolChoiceInputFunction
|
|
350
|
+
"""The function that the model called."""
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
class Parameters(BaseModel):
|
|
354
|
+
"""
|
|
355
|
+
General Parameters for LLM
|
|
356
|
+
"""
|
|
357
|
+
|
|
358
|
+
top_p: Optional[float] = None
|
|
359
|
+
"""Nucleus sampling, between (0, 1.0], where the model considers the
|
|
360
|
+
results of the tokens with top_p probability mass.
|
|
361
|
+
|
|
362
|
+
So 0.1 means only the tokens comprising the top 10% probability mass are
|
|
363
|
+
considered.
|
|
364
|
+
|
|
365
|
+
We generally recommend altering this or `temperature` but not both.
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
temperature: Optional[float] = None
|
|
369
|
+
"""What sampling temperature to use, between 0 and 2.
|
|
370
|
+
|
|
371
|
+
Higher values like 0.8 will make the output more random, while lower values
|
|
372
|
+
like 0.2 will make it more focused and deterministic.
|
|
373
|
+
|
|
374
|
+
We generally recommend altering this or `top_p` but not both.
|
|
375
|
+
"""
|
|
376
|
+
|
|
377
|
+
frequency_penalty: Optional[float] = None
|
|
378
|
+
"""Positive values penalize new tokens based on their existing frequency in
|
|
379
|
+
the text so far, decreasing the model's likelihood to repeat the same line
|
|
380
|
+
verbatim.
|
|
381
|
+
|
|
382
|
+
"""
|
|
383
|
+
|
|
384
|
+
presence_penalty: Optional[float] = None
|
|
385
|
+
"""Number between -2.0 and 2.0.
|
|
386
|
+
|
|
387
|
+
Positive values penalize new tokens based on whether they appear in the
|
|
388
|
+
text so far, increasing the model's likelihood to talk about new topics.
|
|
389
|
+
|
|
390
|
+
"""
|
|
391
|
+
|
|
392
|
+
max_tokens: Optional[int] = None
|
|
393
|
+
"""The maximum number of [tokens](/tokenizer) that can be generated in the
|
|
394
|
+
chat completion.
|
|
395
|
+
|
|
396
|
+
The total length of input tokens and generated tokens is limited by the
|
|
397
|
+
model's context length.
|
|
398
|
+
"""
|
|
399
|
+
|
|
400
|
+
stop: Optional[Union[Optional[str], List[str]]] = None
|
|
401
|
+
"""Up to 4 sequences where the API will stop generating further tokens."""
|
|
402
|
+
|
|
403
|
+
stream: bool = True
|
|
404
|
+
"""If set, partial message deltas will be sent, like in ChatGPT. """
|
|
405
|
+
|
|
406
|
+
stream_options: Optional[ChatCompletionStreamOptionsParam] = None
|
|
407
|
+
"""Options for streaming response. Only set this when you set
|
|
408
|
+
`stream: true`."""
|
|
409
|
+
|
|
410
|
+
tools: Optional[List[Union[Tool, Dict]]] = None
|
|
411
|
+
"""A list of tools the model may call.
|
|
412
|
+
|
|
413
|
+
Currently, only functions are supported as a tool. Use this to provide a
|
|
414
|
+
list of functions the model may generate JSON inputs for.
|
|
415
|
+
"""
|
|
416
|
+
|
|
417
|
+
tool_choice: Optional[Union[str, ToolChoice]] = None
|
|
418
|
+
"""Controls which (if any) tool is called by the model.
|
|
419
|
+
|
|
420
|
+
"""
|
|
421
|
+
|
|
422
|
+
parallel_tool_calls: bool = False
|
|
423
|
+
"""Whether to enable parallel function calling during tool use."""
|
|
424
|
+
|
|
425
|
+
logit_bias: Optional[Dict[str, int]] = None
|
|
426
|
+
"""Modify the likelihood of specified tokens appearing in the completion.
|
|
427
|
+
|
|
428
|
+
Accepts a JSON object that maps tokens (specified by their token ID in the
|
|
429
|
+
tokenizer) to an associated bias value from -100 to 100. Mathematically,
|
|
430
|
+
the bias is added to the logits generated by the model prior to
|
|
431
|
+
sampling. The exact effect will vary per model, but values between -1
|
|
432
|
+
and 1 should decrease or increase likelihood of selection; values like
|
|
433
|
+
-100 or 100 should result in a ban or exclusive selection of the relevant
|
|
434
|
+
token.
|
|
435
|
+
"""
|
|
436
|
+
|
|
437
|
+
top_logprobs: Optional[int] = None
|
|
438
|
+
"""An integer between 0 and 20 specifying the number of most likely
|
|
439
|
+
tokens to return at each token position, each with an associated log
|
|
440
|
+
probability.
|
|
441
|
+
|
|
442
|
+
`logprobs` must be set to `true` if this parameter is used.
|
|
443
|
+
"""
|
|
444
|
+
|
|
445
|
+
logprobs: Optional[bool] = None
|
|
446
|
+
"""Whether to return log probabilities of the output tokens or not.
|
|
447
|
+
|
|
448
|
+
If true, returns the log probabilities of each output token returned in the
|
|
449
|
+
`content` of `message`.
|
|
450
|
+
"""
|
|
451
|
+
|
|
452
|
+
n: Optional[int] = Field(default=1, ge=1, le=5)
|
|
453
|
+
"""How many chat completion choices to generate for each input message.
|
|
454
|
+
|
|
455
|
+
Note that you will be charged based on the number of generated tokens
|
|
456
|
+
across all of the choices. Keep `n` as `1` to minimize costs.
|
|
457
|
+
"""
|
|
458
|
+
|
|
459
|
+
seed: Optional[int] = None
|
|
460
|
+
"""If specified, system will make a best effort to sample
|
|
461
|
+
deterministically, such that repeated requests with the same `seed` and
|
|
462
|
+
parameters should return the same result.
|
|
463
|
+
"""
|
|
464
|
+
|
|
465
|
+
response_format: Optional[Union[ResponseFormat, str]] = ResponseFormat(
|
|
466
|
+
type="text",
|
|
467
|
+
)
|
|
468
|
+
"""An object specifying the format that the model must output.
|
|
469
|
+
|
|
470
|
+
Setting to `{ "type": "json_object" }` enables JSON mode,
|
|
471
|
+
which guarantees the message the model generates is valid JSON.
|
|
472
|
+
"""
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
def create_chat_completion(
|
|
476
|
+
message: OpenAIMessage,
|
|
477
|
+
model_name: str,
|
|
478
|
+
id: str = "",
|
|
479
|
+
finish_reason: Optional[str] = None,
|
|
480
|
+
) -> ChatCompletion:
|
|
481
|
+
# Create Choice object
|
|
482
|
+
choice = {
|
|
483
|
+
"finish_reason": finish_reason,
|
|
484
|
+
"index": 0,
|
|
485
|
+
"message": message.model_dump(),
|
|
486
|
+
"logprobs": None,
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
# Construct ChatCompletion object
|
|
490
|
+
return ChatCompletion(
|
|
491
|
+
id=id, # Generate unique ID
|
|
492
|
+
choices=[choice], # List containing at least one Choice
|
|
493
|
+
created=int(time.time()), # Current timestamp
|
|
494
|
+
model=model_name, # Adjust based on actual model used
|
|
495
|
+
object="chat.completion", # Fixed literal value
|
|
496
|
+
# Optional fields below
|
|
497
|
+
service_tier=None,
|
|
498
|
+
system_fingerprint=None,
|
|
499
|
+
usage=None,
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def create_chat_completion_chunk(
|
|
504
|
+
message: OpenAIMessage,
|
|
505
|
+
model_name: str,
|
|
506
|
+
id: str = "",
|
|
507
|
+
finish_reason: Optional[str] = None,
|
|
508
|
+
) -> ChatCompletionChunk:
|
|
509
|
+
# Create Choice object for chunk
|
|
510
|
+
choice = {
|
|
511
|
+
"finish_reason": finish_reason,
|
|
512
|
+
"index": 0,
|
|
513
|
+
"logprobs": None,
|
|
514
|
+
"delta": message.model_dump(),
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
# Construct ChatCompletionChunk object
|
|
518
|
+
return ChatCompletionChunk(
|
|
519
|
+
id=id, # Generate unique ID
|
|
520
|
+
choices=[choice], # List containing at least one Choice
|
|
521
|
+
created=int(time.time()), # Current timestamp
|
|
522
|
+
model=model_name, # Adjust based on actual model used
|
|
523
|
+
object="chat.completion.chunk", # Fixed literal value
|
|
524
|
+
# Optional fields below
|
|
525
|
+
service_tier=None,
|
|
526
|
+
system_fingerprint=None,
|
|
527
|
+
usage=None,
|
|
528
|
+
)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
def is_json_string(s: Union[str, Dict, BaseModel, None]) -> bool:
|
|
532
|
+
try:
|
|
533
|
+
obj = json.loads(s) # type: ignore[arg-type]
|
|
534
|
+
if isinstance(obj, (dict, list)):
|
|
535
|
+
return True
|
|
536
|
+
return False
|
|
537
|
+
except Exception:
|
|
538
|
+
return False
|