Update README with official FunctionGemma calling format
Browse files- Use AutoProcessor instead of AutoTokenizer
- Add tools parameter to apply_chat_template
- Include complete tool schemas in example
- Match official Google Gemma documentation pattern
README.md
CHANGED
|
@@ -270,29 +270,121 @@ For optimal performance, use the following developer/system prompt when initiali
|
|
| 270 |
**Usage Example (Python/Transformers):**
|
| 271 |
|
| 272 |
```python
|
| 273 |
-
from transformers import AutoModelForCausalLM,
|
| 274 |
|
| 275 |
model_path = "DMindAI/DMind-3-nano"
|
| 276 |
-
model = AutoModelForCausalLM.from_pretrained(model_path)
|
| 277 |
-
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
| 278 |
|
| 279 |
-
#
|
| 280 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 281 |
{
|
| 282 |
-
"
|
| 283 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
},
|
| 285 |
{
|
| 286 |
-
"
|
| 287 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 288 |
}
|
| 289 |
]
|
| 290 |
|
| 291 |
-
#
|
| 292 |
-
|
| 293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
outputs = model.generate(**inputs, max_new_tokens=256)
|
| 295 |
-
|
|
|
|
| 296 |
```
|
| 297 |
|
| 298 |
## License & Governance
|
|
|
|
| 270 |
**Usage Example (Python/Transformers):**
|
| 271 |
|
| 272 |
```python
|
| 273 |
+
from transformers import AutoModelForCausalLM, AutoProcessor
|
| 274 |
|
| 275 |
model_path = "DMindAI/DMind-3-nano"
|
|
|
|
|
|
|
| 276 |
|
| 277 |
+
# Load model and processor (processor combines tokenizer and tool handling)
|
| 278 |
+
model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto")
|
| 279 |
+
processor = AutoProcessor.from_pretrained(model_path, device_map="auto")
|
| 280 |
+
|
| 281 |
+
# Define tool schemas (must match training format)
|
| 282 |
+
tools = [
|
| 283 |
{
|
| 284 |
+
"name": "SEARCH_TOKEN",
|
| 285 |
+
"description": "Search for a cryptocurrency token on-chain to retrieve its metadata or address.",
|
| 286 |
+
"parameters": {
|
| 287 |
+
"type": "object",
|
| 288 |
+
"properties": {
|
| 289 |
+
"symbol": {"type": "string", "description": "The ticker symbol of the token (e.g., 'SOL', 'USDC')."},
|
| 290 |
+
"address": {"type": "string", "description": "The specific contract address (CA) of the token, if known."},
|
| 291 |
+
"chain": {"type": "string", "enum": ["solana", "ethereum", "bsc", "base"], "description": "The target blockchain network."},
|
| 292 |
+
"keyword": {"type": "string", "description": "General search keywords (e.g., project name) if symbol/address are unclear."}
|
| 293 |
+
},
|
| 294 |
+
"required": []
|
| 295 |
+
}
|
| 296 |
},
|
| 297 |
{
|
| 298 |
+
"name": "EXECUTE_SWAP",
|
| 299 |
+
"description": "Propose a token swap transaction.",
|
| 300 |
+
"parameters": {
|
| 301 |
+
"type": "object",
|
| 302 |
+
"properties": {
|
| 303 |
+
"inputTokenSymbol": {"type": "string", "description": "Symbol of the token being sold (e.g., 'SOL')."},
|
| 304 |
+
"inputTokenCA": {"type": "string", "description": "Contract address of the token being sold."},
|
| 305 |
+
"outputTokenCA": {"type": "string", "description": "Contract address of the token being bought."},
|
| 306 |
+
"inputTokenAmount": {"type": "number", "description": "Absolute amount of input token to swap."},
|
| 307 |
+
"inputTokenPercentage": {"type": "number", "description": "Percentage of balance to swap (0.0 to 1.0)."},
|
| 308 |
+
"outputTokenAmount": {"type": "number", "description": "Minimum amount of output token expected."}
|
| 309 |
+
},
|
| 310 |
+
"required": ["inputTokenSymbol"]
|
| 311 |
+
}
|
| 312 |
}
|
| 313 |
]
|
| 314 |
|
| 315 |
+
# Prepare messages with developer prompt (CRITICAL: must be first message)
|
| 316 |
+
developer_prompt = """You are a model that can do function calling with the following functions.
|
| 317 |
+
You are an on-chain trading assistant.
|
| 318 |
+
You may use only two tools: SEARCH_TOKEN and EXECUTE_SWAP.
|
| 319 |
+
|
| 320 |
+
Core policy:
|
| 321 |
+
- Use a tool only when needed.
|
| 322 |
+
- If required fields are missing or ambiguous, ask one concise clarification question first.
|
| 323 |
+
- If the user is just chatting, reply naturally without calling tools.
|
| 324 |
+
- Never fabricate addresses, amounts, balances, prices, or execution results.
|
| 325 |
+
- Never resolve token symbols to contract addresses from memory or static snapshots.
|
| 326 |
+
- Treat ticker symbols as potentially ambiguous and contract addresses as dynamic (can migrate/upgrade).
|
| 327 |
+
- Supported chains are: solana, ethereum, bsc, base.
|
| 328 |
+
If the user asks for an unsupported chain (for example polygon), explain the limitation and ask for a supported chain.
|
| 329 |
+
|
| 330 |
+
Tool-call format (must match exactly):
|
| 331 |
+
<start_function_call>call:TOOL_NAME{\"key\":\"value\",\"amount\":1.23}</end_function_call>
|
| 332 |
+
Do not output XML-style tags such as <function_calls>, <invoke>, or <parameter>.
|
| 333 |
+
|
| 334 |
+
Strict schema:
|
| 335 |
+
|
| 336 |
+
SEARCH_TOKEN params
|
| 337 |
+
{
|
| 338 |
+
\"symbol\": \"string, optional\",
|
| 339 |
+
\"address\": \"string, optional\",
|
| 340 |
+
\"keyword\": \"string, optional\",
|
| 341 |
+
\"chain\": \"solana | ethereum | bsc | base, optional\"
|
| 342 |
+
}
|
| 343 |
+
Rules:
|
| 344 |
+
- At least one of symbol/address/keyword is required.
|
| 345 |
+
- If the user gives only an address, do address-only lookup (do not guess chain).
|
| 346 |
+
- If user explicitly gives chain, include chain.
|
| 347 |
+
- For symbol/keyword based requests, call SEARCH_TOKEN first before producing a swap call.
|
| 348 |
+
- If lookup may return multiple candidates (same ticker/name), ask the user to confirm the exact token (address or more context).
|
| 349 |
+
|
| 350 |
+
EXECUTE_SWAP params
|
| 351 |
+
{
|
| 352 |
+
\"inputTokenSymbol\": \"string, required\",
|
| 353 |
+
\"inputTokenCA\": \"string, optional\",
|
| 354 |
+
\"outputTokenCA\": \"string, optional\",
|
| 355 |
+
\"inputTokenAmount\": \"number, optional\",
|
| 356 |
+
\"inputTokenPercentage\": \"number in [0,1], optional\",
|
| 357 |
+
\"outputTokenAmount\": \"number, optional\"
|
| 358 |
+
}
|
| 359 |
+
Rules:
|
| 360 |
+
- inputTokenAmount and inputTokenPercentage are mutually exclusive.
|
| 361 |
+
- Convert 30% to inputTokenPercentage=0.3.
|
| 362 |
+
- If both amount and percentage are provided, ask the user to choose one.
|
| 363 |
+
- If outputTokenCA is unknown, call SEARCH_TOKEN first and use the returned result.
|
| 364 |
+
- If user already provides output token address explicitly, you may call EXECUTE_SWAP directly.
|
| 365 |
+
- If lookup returns multiple candidates or low-confidence candidates, ask a clarification question; do not guess.
|
| 366 |
+
|
| 367 |
+
Language:
|
| 368 |
+
- Support both Chinese and English.
|
| 369 |
+
- Reply in the same language as the user unless they ask otherwise."""
|
| 370 |
+
|
| 371 |
+
messages = [
|
| 372 |
+
{"role": "developer", "content": developer_prompt},
|
| 373 |
+
{"role": "user", "content": "在base查BTC地址"}
|
| 374 |
+
]
|
| 375 |
+
|
| 376 |
+
# Generate with processor (handles tools automatically)
|
| 377 |
+
inputs = processor.apply_chat_template(
|
| 378 |
+
messages,
|
| 379 |
+
tools=tools,
|
| 380 |
+
add_generation_prompt=True,
|
| 381 |
+
return_dict=True,
|
| 382 |
+
return_tensors="pt"
|
| 383 |
+
).to(model.device)
|
| 384 |
+
|
| 385 |
outputs = model.generate(**inputs, max_new_tokens=256)
|
| 386 |
+
response = processor.decode(outputs[0], skip_special_tokens=True)
|
| 387 |
+
print(response)
|
| 388 |
```
|
| 389 |
|
| 390 |
## License & Governance
|