Skip to content

Commit 892d053

Browse files
fix(formatter): reconcile async xai conversion with input types
2 parents 202c165 + 6109dd0 commit 892d053

95 files changed

Lines changed: 8858 additions & 176 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎pyproject.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ dev = [
214214

215215
[project.urls]
216216
Homepage = "https://github.com/agentscope-ai/agentscope"
217-
Documentation = "https://doc.agentscope.io/"
217+
Documentation = "https://docs.agentscope.io/"
218218
Repository = "https://github.com/agentscope-ai/agentscope"
219219

220220
[tool.setuptools]

‎scripts/model_examples/README.md‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ scripts/model_examples/
2828
├── anthropic_multimodal.py
2929
├── anthropic_multiagent_multimodal.py
3030
│
31+
├── minimax_call.py # MiniMax M-series
32+
├── minimax_multiagent.py
33+
├── minimax_multimodal.py
34+
├── minimax_multiagent_multimodal.py
35+
│
3136
├── dashscope_call.py # Alibaba DashScope / Qwen
3237
├── dashscope_multiagent.py
3338
├── dashscope_multimodal.py
@@ -80,6 +85,7 @@ scripts/model_examples/
8085
| `openai_chat` | `OPENAI_API_KEY` | Chat Completions API – gpt-4.1, etc. |
8186
| `openai_response` | `OPENAI_API_KEY` | Responses API – o1, o3, o4-mini, etc. |
8287
| `anthropic` | `ANTHROPIC_API_KEY` | Claude models, supports extended thinking |
88+
| `minimax` | `MINIMAX_API_KEY` | MiniMax M-series via the Anthropic-compatible API |
8389
| `dashscope` | `DASHSCOPE_API_KEY` | Qwen series, supports `thinking_enable` |
8490
| `deepseek` | `DEEPSEEK_API_KEY` | Supports only `call` / `multiagent` (no multimodal) |
8591
| `gemini` | `GEMINI_API_KEY` | Gemini models, supports `thinking_budget` |
@@ -99,6 +105,7 @@ Set the environment variables for the providers you want to test:
99105
```bash
100106
export OPENAI_API_KEY="sk-..."
101107
export ANTHROPIC_API_KEY="sk-ant-..."
108+
export MINIMAX_API_KEY="sk-..."
102109
export DASHSCOPE_API_KEY="sk-..."
103110
export DEEPSEEK_API_KEY="sk-..."
104111
export GEMINI_API_KEY="AIza..."
@@ -220,7 +227,8 @@ Each script typically defines two or more async functions:
220227
- `example_structured_output()` – force a Pydantic-validated JSON output (in `_call.py` variants, uses a thinking-enabled model)
221228
- `example_image_url()` / `example_image_local_path()` / `example_image_base64()` – image + text input (in `_multimodal.py` variants)
222229
- `example_audio()` – audio input (e.g. `openai_chat_multimodal.py`, `dashscope_multimodal.py`)
223-
- `example_video()` – video input (e.g. `dashscope_multimodal.py`)
230+
- `example_video()` / `example_video_url()` – video input (e.g.
231+
`dashscope_multimodal.py`, `minimax_multimodal.py`)
224232

225233
---
226234

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
# -*- coding: utf-8 -*-
2+
"""Examples of MiniMax chat model calls.
3+
4+
The MiniMax M-series chat models (e.g. ``MiniMax-M3``) are exposed via
5+
MiniMax's officially recommended Anthropic-compatible API, so the
6+
controls and outputs match
7+
``scripts/model_examples/anthropic_call.py``.
8+
"""
9+
10+
import asyncio
11+
import json
12+
import os
13+
14+
from pydantic import BaseModel, Field
15+
16+
from _utils import stream_and_collect
17+
from agentscope.credential import MiniMaxCredential
18+
from agentscope.message import (
19+
Msg,
20+
TextBlock,
21+
ToolCallBlock,
22+
ToolResultBlock,
23+
ToolResultState,
24+
)
25+
from agentscope.model import MiniMaxChatModel
26+
from agentscope.tool import Toolkit, ToolChoice, FunctionTool
27+
28+
29+
# ---------------------------------------------------------------------------
30+
# Example 1: Simple user message (streaming, with extended thinking)
31+
# ---------------------------------------------------------------------------
32+
33+
34+
async def example_simple_call() -> None:
35+
"""Call MiniMax-M3 with a simple text message and extended thinking."""
36+
model = MiniMaxChatModel(
37+
credential=MiniMaxCredential(
38+
api_key=os.environ["MINIMAX_API_KEY"],
39+
),
40+
model="MiniMax-M3",
41+
stream=True,
42+
parameters=MiniMaxChatModel.Parameters(
43+
thinking_enable=True,
44+
),
45+
)
46+
47+
msgs = [
48+
Msg(
49+
name="user",
50+
content=[TextBlock(text="What is 1 + 1? Answer briefly.")],
51+
role="user",
52+
),
53+
]
54+
55+
print("=== Simple Call ===")
56+
await stream_and_collect(await model(msgs))
57+
58+
59+
# ---------------------------------------------------------------------------
60+
# Example 2: Tool calling (streaming)
61+
# ---------------------------------------------------------------------------
62+
63+
64+
def get_weather(city: str) -> str:
65+
"""Get the current weather for a city.
66+
67+
Args:
68+
city: The city name to query the weather for.
69+
70+
Returns:
71+
A description of the current weather.
72+
"""
73+
return f"The weather in {city} is sunny and 25°C."
74+
75+
76+
async def example_tool_call() -> None:
77+
"""Call MiniMax-M3 with tool calling enabled."""
78+
toolkit = Toolkit(tools=[FunctionTool(get_weather)])
79+
tools = await toolkit.get_tool_schemas()
80+
81+
model = MiniMaxChatModel(
82+
credential=MiniMaxCredential(
83+
api_key=os.environ["MINIMAX_API_KEY"],
84+
),
85+
model="MiniMax-M3",
86+
stream=True,
87+
parameters=MiniMaxChatModel.Parameters(
88+
thinking_enable=True,
89+
),
90+
)
91+
92+
msgs = [
93+
Msg(
94+
name="user",
95+
content=[TextBlock(text="What is the weather in Shanghai?")],
96+
role="user",
97+
),
98+
]
99+
100+
print("=== Tool Call - Round 1 ===")
101+
response = await stream_and_collect(
102+
await model(msgs, tools=tools, tool_choice=ToolChoice(mode="auto")),
103+
)
104+
print(response)
105+
106+
tool_calls = [b for b in response.content if isinstance(b, ToolCallBlock)]
107+
if tool_calls:
108+
tool_result_blocks = []
109+
for tool_call in tool_calls:
110+
args = json.loads(tool_call.input)
111+
result = get_weather(**args)
112+
tool_result_blocks.append(
113+
ToolResultBlock(
114+
id=tool_call.id,
115+
name=tool_call.name,
116+
output=result,
117+
state=ToolResultState.SUCCESS,
118+
),
119+
)
120+
121+
assistant_msg = Msg(
122+
name="assistant",
123+
content=response.content,
124+
role="assistant",
125+
)
126+
tool_result_msg = Msg(
127+
name="tool",
128+
content=tool_result_blocks,
129+
role="assistant",
130+
)
131+
msgs = msgs + [assistant_msg, tool_result_msg]
132+
133+
print("=== Tool Call - Round 2 (Final) ===")
134+
await stream_and_collect(await model(msgs))
135+
136+
137+
# ---------------------------------------------------------------------------
138+
# Example 3: Structured output
139+
# ---------------------------------------------------------------------------
140+
141+
142+
class MathSolution(BaseModel):
143+
"""Structured solution to a math problem."""
144+
145+
problem: str = Field(description="The original problem statement")
146+
answer: float = Field(description="The final numeric answer")
147+
steps: list[str] = Field(
148+
description="Step-by-step reasoning leading to the answer",
149+
)
150+
151+
152+
async def example_structured_output() -> None:
153+
"""Call MiniMax-M3 and force a structured (JSON) output."""
154+
model = MiniMaxChatModel(
155+
credential=MiniMaxCredential(
156+
api_key=os.environ["MINIMAX_API_KEY"],
157+
),
158+
model="MiniMax-M3",
159+
stream=True,
160+
parameters=MiniMaxChatModel.Parameters(
161+
thinking_enable=True,
162+
),
163+
)
164+
165+
msgs = [
166+
Msg(
167+
name="user",
168+
content=[
169+
TextBlock(
170+
text=(
171+
"Solve this: A train travels at 60 km/h for "
172+
"2.5 hours. How far does it travel in km?"
173+
),
174+
),
175+
],
176+
role="user",
177+
),
178+
]
179+
180+
print("=== Structured Output ===")
181+
response = await model.generate_structured_output(
182+
msgs,
183+
structured_model=MathSolution,
184+
)
185+
print(response.content)
186+
187+
188+
if __name__ == "__main__":
189+
asyncio.run(example_simple_call())
190+
asyncio.run(example_tool_call())
191+
asyncio.run(example_structured_output())
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# -*- coding: utf-8 -*-
2+
"""Example of MiniMax chat model calls with MiniMaxMultiAgentFormatter.
3+
4+
The multi-agent formatter wraps prior conversation history in
5+
``<history></history>`` tags, enabling MiniMax-M3 to handle multi-agent
6+
conversations where more than one non-user agent is involved.
7+
"""
8+
9+
import asyncio
10+
import os
11+
12+
from _utils import stream_and_collect
13+
from agentscope.credential import MiniMaxCredential
14+
from agentscope.formatter import MiniMaxMultiAgentFormatter
15+
from agentscope.message import Msg, TextBlock
16+
from agentscope.model import MiniMaxChatModel
17+
18+
19+
async def example_multiagent() -> None:
20+
"""Simulate a multi-agent conversation and let MiniMax-M3 summarize.
21+
22+
Alice and Bob discuss the weather, then a moderator (the model) is asked
23+
to summarize the conversation.
24+
"""
25+
formatter = MiniMaxMultiAgentFormatter()
26+
27+
model = MiniMaxChatModel(
28+
credential=MiniMaxCredential(
29+
api_key=os.environ["MINIMAX_API_KEY"],
30+
),
31+
model="MiniMax-M3",
32+
stream=True,
33+
parameters=MiniMaxChatModel.Parameters(
34+
thinking_enable=True,
35+
),
36+
formatter=formatter,
37+
)
38+
39+
msgs = [
40+
Msg(
41+
name="system",
42+
content=[
43+
TextBlock(
44+
text=(
45+
"You are a helpful moderator. Summarize the "
46+
"conversation."
47+
),
48+
),
49+
],
50+
role="system",
51+
),
52+
Msg(
53+
name="alice",
54+
content=[
55+
TextBlock(
56+
text="Hi Bob! What do you think about the weather today?",
57+
),
58+
],
59+
role="user",
60+
),
61+
Msg(
62+
name="bob",
63+
content=[
64+
TextBlock(
65+
text=(
66+
"It's quite sunny and warm, Alice. Perfect for a "
67+
"walk!"
68+
),
69+
),
70+
],
71+
role="assistant",
72+
),
73+
Msg(
74+
name="alice",
75+
content=[
76+
TextBlock(text="Agreed! I might head to the park later."),
77+
],
78+
role="user",
79+
),
80+
Msg(
81+
name="bob",
82+
content=[
83+
TextBlock(
84+
text="Great idea. I'll join you if I finish work early.",
85+
),
86+
],
87+
role="assistant",
88+
),
89+
Msg(
90+
name="moderator",
91+
content=[
92+
TextBlock(
93+
text=(
94+
"Please summarize the conversation above in one "
95+
"sentence."
96+
),
97+
),
98+
],
99+
role="user",
100+
),
101+
]
102+
103+
print("=== Multi-Agent Formatter Call ===")
104+
await stream_and_collect(await model(msgs))
105+
106+
107+
if __name__ == "__main__":
108+
asyncio.run(example_multiagent())

0 commit comments

Comments
 (0)