Inference stays on your device. Standardized function calling for wallets, DEXs, and agents. Built on google/functiongemma-270m-it.
Model Description
DMind-3-nano is a small, edge-optimized language model fine-tuned for crypto wallet and DEX intent recognition using standardized function-calling protocols. It is designed to run entirely on-device, enabling privacy-preserving, low-latency intent parsing for Web3 wallets and local agents.
This repository hosts the open-source training and evaluation pipeline as well as the released model artifacts.
Repo purpose: host the open-source training/eval pipeline and release artifacts.
Performance Snapshot
Figure 1. DMind-3-nano significantly outperforms both the untuned base model and a similarly sized general-purpose model (Qwen3-0.6B), especially in multi-turn success.
Highlights
🔐 Privacy-first: 100% on-device intent recognition; no data leaves the device.
📱 Edge-optimized: 270M params; runs on phones/tablets/edge CPUs.
🔄 Standardized protocols: SEARCH_TOKEN / EXECUTE_SWAP with unified schemas.
🌐 Multi-chain: Solana, Ethereum, BSC, Base.
🌍 Multilingual: English + Chinese intents (Chinese samples kept in data/benchmarks).
🤖 Agent-native: designed for local-first wallet/agent workflows where a growing share of trading decisions and execution happen on-device.
📊 Training data: the final full fine-tune used 12,000+ samples in total; LLM-generated data is only a subset, and 60%+ of the data comes from real trading scenarios.
🧾 (To our knowledge) first public vertical-domain FunctionGemma case study: an end-to-end example of fine-tuning google/functiongemma-270m-it for a real wallet/DEX intent domain, including the practical training/evaluation pipeline and reproducible scripts.
Why This Matters for Web3 (Standardization as a Step-Change)
Web3 is composable at the protocol layer (tokens, RPCs), but still fragmented at the intent layer. Today every wallet, DEX, and agent framework invents its own “swap/search intent” schema and function-calling format. The result is high integration cost, brittle adapters, inconsistent safety guarantees, and poor ecosystem interoperability.
This work targets a transformative goal: standardize wallet intents as a small, versionable protocol between natural language and transaction builders. Concretely, DMind-3-nano enforces a minimal set of typed tools (e.g. SEARCH_TOKEN, EXECUTE_SWAP) with strict schemas and a deterministic wrapper output format.
What standardization unlocks:
Interoperability: one protocol works across wallets/DEXs/agents; integrations become plug-and-play.
Safety & auditability: tool calls are structured data—easy to validate, simulate, policy-check, and display for confirmation before signing.
Benchmarkability: shared datasets and comparable evaluations across models and releases.
Ecosystem scaling: new tools can be added via versioning without breaking existing clients.
In short, DMind-3-nano is not only a model—it is a proposal for a standard protocol layer that can make wallet intelligence as interoperable as ERC-20 made tokens.
The next wave: local agents executing trades
We expect a large share of future Web3 activity to be agent-driven: wallets will run local copilots that continuously parse user intent, monitor context, and propose/execute transactions. In that world, “cloud-only” intelligence becomes a bottleneck and a risk:
Privacy: trading intent, token preferences, and behavioral signals should not be streamed to third-party servers.
Latency & reliability: agents must work instantly and offline (mobile, hardware wallets, poor connectivity).
Security boundaries: local agents can keep a tighter loop between intent → policy checks → simulation → user confirmation → signing.
This is why a small, high-accuracy on-device function-calling model is necessary infrastructure for the agent-native wallet era—and why standardizing the intent protocol matters even more when millions of agents need to speak the same language.
Equally important, this repository serves as a public reference implementation for applying FunctionGemma to a concrete vertical domain. By openly sharing fine-tuning details (data format, training configs, evaluation, and benchmarks), it lowers the barrier for the community to replicate, extend, and standardize on a common intent protocol.
Experimental notice: Highest accuracy on the token/chain set above; other assets may need further tuning. Validate outputs before transacting.
Repository Layout
model/ We have uploaded an experimental version of the model weights. Please note that this is a bold exploratory release, and we do not take responsibility for any financial losses incurred from using this model in production environments.
src/ training/eval utilities
train.py (LoRA or full fine-tune)
evaluate.py (benchmark evaluation)
prepare_dataset.py (SFT-ready formatting)
generate_benchmark.py (100-case benchmark)
config.py (tools, prompts, token maps)
data/ sample data
training_data.json (raw; open-sourced subset for reproducibility)
benchmark_dataset.json (eval set; includes Chinese test prompts by design)
Note: data/prepared_dataset.json is a generated artifact (optional) and is intentionally not committed.
Tool Definitions & Schemas
To ensure interoperability, DMind-3-nano uses strict JSON schemas for tool definitions. Below are the standard definitions used during training and inference.
1. SEARCH_TOKEN
Used to find token metadata or address on a specific chain.
json
1{2"name":"SEARCH_TOKEN",3"description":"Search for a cryptocurrency token on-chain to retrieve its metadata or address.",4"parameters":{5"type":"object",6"properties":{7"symbol":{8"type":"string",9"description":"The ticker symbol of the token (e.g., 'SOL', 'USDC')."10},11"address":{12"type":"string",13"description":"The specific contract address (CA) of the token, if known."14},15"chain":{16"type":"string",17"enum":["solana","ethereum","bsc","base"],18"description":"The target blockchain network."19},20"keyword":{21"type":"string",22"description":"General search keywords (e.g., project name) if symbol/address are unclear."23}24},25"required":[]26}27}
2. EXECUTE_SWAP
Used to construct a swap transaction intent between two assets.
json
1{2"name":"EXECUTE_SWAP",3"description":"Propose a token swap transaction.",4"parameters":{5"type":"object",6"properties":{7"inputTokenSymbol":{8"type":"string",9"description":"Symbol of the token being sold (e.g., 'SOL')."10},11"inputTokenCA":{12"type":"string",13"description":"Contract address of the token being sold."14},15"outputTokenCA":{16"type":"string",17"description":"Contract address of the token being bought."18},19"inputTokenAmount":{20"type":"number",21"description":"Absolute amount of input token to swap."22},23"inputTokenPercentage":{24"type":"number",25"description":"Percentage of balance to swap (0.0 to 1.0), used if exact amount is not specified."26},27"outputTokenAmount":{28"type":"number",29"description":"Minimum amount of output token expected (optional/slippage related)."30}31},32"required":["inputTokenSymbol"]33}34}
Output Format
The model outputs the function call wrapped in special tokens (standard FunctionGemma format):
For optimal performance, use the following developer/system prompt when initializing the model:
Usage Principles (Important)
Follow these rules for best results:
Place Once at the Beginning: Put the developer prompt only once, at the very start of your conversation session
Do NOT place in user messages: Never include the developer prompt content in user/assistant messages or tool schemas
Session-wide persistence: For multi-turn conversations, keep the same developer prompt at the session start - do not repeat it
Correct usage pattern:
json
1{2"messages":[3{"role":"developer","content":"<developer prompt goes here>"},4{"role":"user","content":"first user query"},5{"role":"assistant","content":"assistant response"},6{"role":"user","content":"second user query"}7// No need to repeat developer prompt in subsequent turns8]9}
Developer Prompt Content
json
1{2"messages":[3{"role":"developer","content":"You are a model that can do function calling with the following functions.\nYou are an on-chain trading assistant.\nYou may use only two tools: SEARCH_TOKEN and EXECUTE_SWAP.\n\nCore policy:\n- Use a tool only when needed.\n- If required fields are missing or ambiguous, ask one concise clarification question first.\n- If the user is just chatting, reply naturally without calling tools.\n- Never fabricate addresses, amounts, balances, prices, or execution results.\n- Never resolve token symbols to contract addresses from memory or static snapshots.\n- Treat ticker symbols as potentially ambiguous and contract addresses as dynamic (can migrate/upgrade).\n- Supported chains are: solana, ethereum, bsc, base.\n If the user asks for an unsupported chain (for example polygon), explain the limitation and ask for a supported chain.\n\nTool-call format (must match exactly):\n<start_function_call>call:TOOL_NAME{\"key\":\"value\",\"amount\":1.23}</end_function_call>\nDo not output XML-style tags such as <function_calls>, <invoke>, or <parameter>.\n\nStrict schema:\n\nSEARCH_TOKEN params\n{\n \"symbol\": \"string, optional\",\n \"address\": \"string, optional\",\n \"keyword\": \"string, optional\",\n \"chain\": \"solana | ethereum | bsc | base, optional\"\n}\nRules:\n- At least one of symbol/address/keyword is required.\n- If the user gives only an address, do address-only lookup (do not guess chain).\n- If user explicitly gives chain, include chain.\n- For symbol/keyword based requests, call SEARCH_TOKEN first before producing a swap call.\n- If lookup may return multiple candidates (same ticker/name), ask the user to confirm the exact token (address or more context).\n\nEXECUTE_SWAP params\n{\n \"inputTokenSymbol\": \"string, required\",\n \"inputTokenCA\": \"string, optional\",\n \"outputTokenCA\": \"string, optional\",\n \"inputTokenAmount\": \"number, optional\",\n \"inputTokenPercentage\": \"number in [0,1], optional\",\n \"outputTokenAmount\": \"number, optional\"\n}\nRules:\n- inputTokenAmount and inputTokenPercentage are mutually exclusive.\n- Convert 30% to inputTokenPercentage=0.3.\n- If both amount and percentage are provided, ask the user to choose one.\n- If outputTokenCA is unknown, call SEARCH_TOKEN first and use the returned result.\n- If user already provides output token address explicitly, you may call EXECUTE_SWAP directly.\n- If lookup returns multiple candidates or low-confidence candidates, ask a clarification question; do not guess.\n\nLanguage:\n- Support both Chinese and English.\n- Reply in the same language as the user unless they ask otherwise."},4{"role":"user","content":"<user query goes here>"}5]6}
Usage Example (Python/Transformers):
python
1from transformers import AutoModelForCausalLM, AutoProcessor
23model_path ="DMindAI/DMind-3-nano"45# Load model and processor (processor combines tokenizer and tool handling)6model = AutoModelForCausalLM.from_pretrained(model_path, device_map="auto")7processor = AutoProcessor.from_pretrained(model_path, device_map="auto")89# Define tool schemas (must match training format)10tools =[11{12"name":"SEARCH_TOKEN",13"description":"Search for a cryptocurrency token on-chain to retrieve its metadata or address.",14"parameters":{15"type":"object",16"properties":{17"symbol":{"type":"string","description":"The ticker symbol of the token (e.g., 'SOL', 'USDC')."},18"address":{"type":"string","description":"The specific contract address (CA) of the token, if known."},19"chain":{"type":"string","enum":["solana","ethereum","bsc","base"],"description":"The target blockchain network."},20"keyword":{"type":"string","description":"General search keywords (e.g., project name) if symbol/address are unclear."}21},22"required":[]23}24},25{26"name":"EXECUTE_SWAP",27"description":"Propose a token swap transaction.",28"parameters":{29"type":"object",30"properties":{31"inputTokenSymbol":{"type":"string","description":"Symbol of the token being sold (e.g., 'SOL')."},32"inputTokenCA":{"type":"string","description":"Contract address of the token being sold."},33"outputTokenCA":{"type":"string","description":"Contract address of the token being bought."},34"inputTokenAmount":{"type":"number","description":"Absolute amount of input token to swap."},35"inputTokenPercentage":{"type":"number","description":"Percentage of balance to swap (0.0 to 1.0)."},36"outputTokenAmount":{"type":"number","description":"Minimum amount of output token expected."}37},38"required":["inputTokenSymbol"]39}40}41]4243# Prepare messages with developer prompt (CRITICAL: must be first message)44developer_prompt ="""You are a model that can do function calling with the following functions.
45You are an on-chain trading assistant.
46You may use only two tools: SEARCH_TOKEN and EXECUTE_SWAP.
4748Core policy:
49- Use a tool only when needed.
50- If required fields are missing or ambiguous, ask one concise clarification question first.
51- If the user is just chatting, reply naturally without calling tools.
52- Never fabricate addresses, amounts, balances, prices, or execution results.
53- Never resolve token symbols to contract addresses from memory or static snapshots.
54- Treat ticker symbols as potentially ambiguous and contract addresses as dynamic (can migrate/upgrade).
55- Supported chains are: solana, ethereum, bsc, base.
56 If the user asks for an unsupported chain (for example polygon), explain the limitation and ask for a supported chain.
5758Tool-call format (must match exactly):
59<start_function_call>call:TOOL_NAME{\"key\":\"value\",\"amount\":1.23}</end_function_call>
60Do not output XML-style tags such as <function_calls>, <invoke>, or <parameter>.
6162Strict schema:
6364SEARCH_TOKEN params
65{
66 \"symbol\": \"string, optional\",
67 \"address\": \"string, optional\",
68 \"keyword\": \"string, optional\",
69 \"chain\": \"solana | ethereum | bsc | base, optional\"
70}
71Rules:
72- At least one of symbol/address/keyword is required.
73- If the user gives only an address, do address-only lookup (do not guess chain).
74- If user explicitly gives chain, include chain.
75- For symbol/keyword based requests, call SEARCH_TOKEN first before producing a swap call.
76- If lookup may return multiple candidates (same ticker/name), ask the user to confirm the exact token (address or more context).
7778EXECUTE_SWAP params
79{
80 \"inputTokenSymbol\": \"string, required\",
81 \"inputTokenCA\": \"string, optional\",
82 \"outputTokenCA\": \"string, optional\",
83 \"inputTokenAmount\": \"number, optional\",
84 \"inputTokenPercentage\": \"number in [0,1], optional\",
85 \"outputTokenAmount\": \"number, optional\"
86}
87Rules:
88- inputTokenAmount and inputTokenPercentage are mutually exclusive.
89- Convert 30% to inputTokenPercentage=0.3.
90- If both amount and percentage are provided, ask the user to choose one.
91- If outputTokenCA is unknown, call SEARCH_TOKEN first and use the returned result.
92- If user already provides output token address explicitly, you may call EXECUTE_SWAP directly.
93- If lookup returns multiple candidates or low-confidence candidates, ask a clarification question; do not guess.
9495Language:
96- Support both Chinese and English.
97- Reply in the same language as the user unless they ask otherwise."""9899messages =[100{"role":"developer","content": developer_prompt},101{"role":"user","content":"在base查BTC地址"}102]103104# Generate with processor (handles tools automatically)105inputs = processor.apply_chat_template(106 messages,107 tools=tools,108 add_generation_prompt=True,109 return_dict=True,110 return_tensors="pt"111).to(model.device)112113outputs = model.generate(**inputs, max_new_tokens=256)114response = processor.decode(outputs[0], skip_special_tokens=True)115print(response)
License & Governance
Code: MIT (LICENSE)
Model card intent: Apache-2.0 (as in metadata above)
Protocol specs (SEARCH_TOKEN / EXECUTE_SWAP): public domain for maximal adoption