Views
No views yet
list_organizations, search_datasets,
get_dataset_details.1from transformers import AutoModelForCausalLM, AutoTokenizer
2
3mid = "grc-iit/FunctionGemma-ndp"
4tok = AutoTokenizer.from_pretrained(mid, subfolder="merged_16bit")
5mdl = AutoModelForCausalLM.from_pretrained(
6 mid, subfolder="merged_16bit", device_map="auto",
7)
8
9messages = [
10 {"role": "developer", "content":
11 "You are a model that can do function calling with the following functions"},
12 {"role": "user", "content": "List all organizations on the NDP global server"},
13]
14prompt = tok.apply_chat_template(
15 messages, tools=[...], add_generation_prompt=True, tokenize=False,
16)<start_function_call>call:list_organizations{server:<escape>global<escape>}<end_function_call>clio-kit NDP MCP → real NDP response.1# /// script
2# requires-python = ">=3.11"
3# dependencies = [
4# "transformers>=4.45", "torch>=2.4", "accelerate>=0.34",
5# "sentencepiece>=0.2", "protobuf>=4", "mcp>=1.0",
6# ]
7# ///
8import asyncio, json, re
9import torch
10from transformers import AutoModelForCausalLM, AutoTokenizer
11from mcp import ClientSession, StdioServerParameters
12from mcp.client.stdio import stdio_client
13
14MID = "grc-iit/FunctionGemma-ndp"
15PROMPT = "List all organizations on the NDP global server"
16
17# 14-tool NDP catalog reshaped as OpenAI function specs (truncated here).
18tools = [{"type": "function", "function": {
19 "name": "list_organizations",
20 "description": "List organizations available in the National Data Platform.",
21 "parameters": {"type": "object", "properties": {
22 "name_filter": {"type": "string"}, "server": {"type": "string"},
23 }, "required": []},
24}}]
25
26tok = AutoTokenizer.from_pretrained(MID, subfolder="merged_16bit")
27mdl = AutoModelForCausalLM.from_pretrained(
28 MID, subfolder="merged_16bit", dtype=torch.bfloat16, device_map="auto",
29)
30text = tok.apply_chat_template(
31 [{"role": "user", "content": PROMPT}],
32 tools=tools, add_generation_prompt=True, tokenize=False,
33)
34inp = tok(text, return_tensors="pt").to(mdl.device)
35out = mdl.generate(**inp, max_new_tokens=300)
36raw = tok.decode(out[0][inp.input_ids.shape[-1]:], skip_special_tokens=False)
37
38# Parse FunctionGemma format: <start_function_call>call:NAME{k:v,...}<end_function_call>
39m = re.search(r"<start_function_call>\s*call:(\w+)\s*\{(.*?)\}\s*<end_function_call>",
40 raw, re.DOTALL)
41name = m.group(1)
42args = {}
43for k, v in re.findall(r"(\w+)\s*:\s*(<escape>.*?<escape>|None|\w+)", m.group(2)):
44 if v == "None":
45 continue # strip phantom nulls
46 args[k] = re.sub(r"<escape>|<escape>", "", v) if "<escape>" in v else v
47
48# Spawn the upstream clio-kit NDP MCP and call the parsed tool against it.
49async def call():
50 params = StdioServerParameters(command="uvx", args=[
51 "--from",
52 "git+https://github.com/iowarp/clio-kit.git#subdirectory=clio-kit-mcp-servers/ndp",
53 "ndp-mcp",
54 ])
55 async with stdio_client(params) as (r, w):
56 async with ClientSession(r, w) as s:
57 await s.initialize()
58 out = await s.call_tool(name, args)
59 print("".join(c.text for c in out.content if hasattr(c, "text")))
60
61asyncio.run(call())test.py and run:uv run --isolated test.pyList all organizations on the NDP global server<start_function_call>call:list_organizations{name_filter:None,server:<escape>global<escape>}<end_function_call>1{"organizations": ["ai-genomics-at-scale", "aquasteady", "burnpro3d",
2 "cal-oes", "california-forest-observatory", ...],
3 "count": 84, "server": "global"}Get details for dataset clm-full-climate-connectivity-network<start_function_call>call:get_dataset_details{
dataset_identifier:<escape>clm-full-climate-connectivity-network<escape>,
identifier_type:<escape>name<escape>,
server:<escape>global<escape>
}<end_function_call>1{"dataset": {
2 "id": "3264e7ee-ef6d-42d5-b722-8ad39670cf3d",
3 "name": "clm-full-climate-connectivity-network",
4 "title": "Full Climate Connectivity Network",
5 "owner_org": "california-landscape-metrics",
6 "resources": [{...4 resources: WMS, WFS, SHP, HTML...}]
7 }}Find datasets about climate<start_function_call>call:search_datasets{
limit:20, search_terms:[<escape>climate<escape>], server:<escape>global<escape>
}<end_function_call>{"datasets": [...], "count": 20, "total_found": "20 of 137"}merged_16bit/ — full safetensors checkpointlora/ — LoRA adapter onlyunsloth/functiongemma-270m-it