jetlab commited on
Commit
bcfcdb0
·
verified ·
1 Parent(s): b25b73e

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -0
app.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import gradio as gr
3
+ import torch
4
+ from transformers import AutoTokenizer, AutoModelForCausalLM
5
+ import xgrammar as xgr
6
+
7
+ # ----------------------------
8
+ # 模型、XGrammar初始化
9
+ # ----------------------------
10
+ # 注意:模型名称可以根据你的实际情况替换为合适的模型(建议使用较小模型测试,正式场景可换大模型)
11
+ model_name = "Qwen/Qwen1.5-0.5B-Chat"
12
+ device = "cuda" if torch.cuda.is_available() else "cpu"
13
+
14
+ print("Loading tokenizer and model...")
15
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
16
+ model = AutoModelForCausalLM.from_pretrained(model_name).to(device)
17
+ model.config.pad_token_id = tokenizer.eos_token_id # 设置 pad_token_id 避免警告
18
+
19
+ # 初始化 XGrammar 的基本组件
20
+ tokenizer_info = xgr.TokenizerInfo.from_huggingface(tokenizer, vocab_size=model.config.vocab_size)
21
+ grammar_compiler = xgr.GrammarCompiler(tokenizer_info)
22
+
23
+ # 默认 JSON schema(以 Person 结构为示例)
24
+ default_schema = {
25
+ "type": "object",
26
+ "properties": {
27
+ "name": {"type": "string"},
28
+ "age": {"type": "integer"}
29
+ },
30
+ "required": ["name", "age"]
31
+ }
32
+ default_schema_text = json.dumps(default_schema, indent=2)
33
+
34
+
35
+ # ----------------------------
36
+ # 主转换函数
37
+ # ----------------------------
38
+ def convert_xml_to_json(xml_input: str, schema_input: str) -> str:
39
+ # 如果用户未提供 JSON schema,则使用默认 schema
40
+ if not schema_input.strip():
41
+ schema_str = default_schema_text
42
+ else:
43
+ schema_str = schema_input.strip()
44
+
45
+ # 尝试加载 JSON schema
46
+ try:
47
+ schema = json.loads(schema_str)
48
+ except Exception as e:
49
+ return f"JSON schema 解析错误:{str(e)}"
50
+
51
+ # 编译 JSON schema 为 XGrammar Grammar
52
+ try:
53
+ compiled_grammar = grammar_compiler.compile_json_schema(schema)
54
+ except Exception as e:
55
+ return f"编译 JSON schema 出错:{str(e)}"
56
+
57
+ # 构造 XGrammar 的 logits processor
58
+ logits_processor = xgr.contrib.hf.LogitsProcessor(compiled_grammar)
59
+
60
+ # 构造转换提示,要求 LLM 解析 XML 并输出符合 schema 的 JSON
61
+ prompt = (
62
+ "You are a JSON converter that converts XML data to a structured JSON object.\n"
63
+ "The output must strictly conform to the following JSON schema (and nothing else):\n\n"
64
+ f"{schema_str}\n\n"
65
+ "Convert the following XML to JSON:\n"
66
+ f"{xml_input}\n\n"
67
+ "Output:"
68
+ )
69
+
70
+ # 编码 prompt
71
+ inputs = tokenizer(prompt, return_tensors="pt").to(device)
72
+ # 调用 generate,并传入 XGrammar logits processor,使生成过程中非法 token 被屏蔽
73
+ generated_ids = model.generate(
74
+ **inputs,
75
+ max_new_tokens=256,
76
+ logits_processor=[logits_processor],
77
+ pad_token_id=tokenizer.eos_token_id,
78
+ )
79
+ # 提取生成部分
80
+ output_text = tokenizer.decode(
81
+ generated_ids[0][inputs.input_ids.shape[1]:],
82
+ skip_special_tokens=True
83
+ )
84
+ return output_text.strip()
85
+
86
+
87
+ # ----------------------------
88
+ # 构建 Gradio 界面
89
+ # ----------------------------
90
+ title = "📄 XML to JSON Converter with XGrammar Structure Check"
91
+ description = (
92
+ "将任意 XML 转换为 JSON。\n\n"
93
+ "在左侧粘贴 XML 文本,并可选地提供 JSON schema(如果留空,则使用默认结构,示例 schema 为 Person 模式);\n"
94
+ "系统将调用 LLM 将 XML 转为 JSON,同时利用 XGrammar 限制输出结构,确保生成的 JSON 严格符合 schema。"
95
+ )
96
+
97
+ with gr.Blocks(title=title) as demo:
98
+ gr.Markdown(f"## {title}\n\n{description}")
99
+
100
+ with gr.Row():
101
+ with gr.Column():
102
+ xml_input = gr.Textbox(lines=12, label="XML 输入", placeholder="在此粘贴 XML 内容…")
103
+ schema_input = gr.Textbox(lines=8, label="JSON Schema(可选)", value=default_schema_text,
104
+ placeholder="可提供自定义 JSON schema,否则使用默认 schema")
105
+ convert_btn = gr.Button("转换 XML → JSON")
106
+ with gr.Column():
107
+ json_output = gr.Textbox(lines=12, label="生成的结构化 JSON")
108
+
109
+ convert_btn.click(
110
+ fn=convert_xml_to_json,
111
+ inputs=[xml_input, schema_input],
112
+ outputs=json_output
113
+ )
114
+
115
+ if __name__ == "__main__":
116
+ demo.launch()