yuzhe commited on
Commit
0532c27
·
verified ·
1 Parent(s): d5f5aec

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

Files changed (1) hide show
  1. README.md +105 -13
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, AutoTokenizer
274
 
275
  model_path = "DMindAI/DMind-3-nano"
276
- model = AutoModelForCausalLM.from_pretrained(model_path)
277
- tokenizer = AutoTokenizer.from_pretrained(model_path)
278
 
279
- # Prepare messages with developer prompt
280
- messages = [
 
 
 
 
281
  {
282
- "role": "developer",
283
- "content": "You are a model that can do function calling with the following functions. You are an on-chain trading assistant... [full prompt as above]"
 
 
 
 
 
 
 
 
 
 
284
  },
285
  {
286
- "role": "user",
287
- "content": "在base查BTC地址"
 
 
 
 
 
 
 
 
 
 
 
 
288
  }
289
  ]
290
 
291
- # Generate
292
- input_text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
293
- inputs = tokenizer(input_text, return_tensors="pt")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
294
  outputs = model.generate(**inputs, max_new_tokens=256)
295
- print(tokenizer.decode(outputs[0]))
 
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