zhangjf commited on
Commit
1e87b01
·
verified ·
1 Parent(s): 6a9ecde

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +202 -0
  2. requirements.txt +15 -0
  3. start.sh +34 -0
app.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ import time
5
+ import os
6
+
7
+ # 配置
8
+ KIMINA_SERVER_URL = "http://localhost:8000"
9
+ HEALTH_CHECK_INTERVAL = 2 # 秒
10
+ MAX_WAIT_TIME = 30 # 秒
11
+
12
+
13
+ def check_server_health():
14
+ """检查 Kimina 服务器是否就绪"""
15
+ try:
16
+ response = requests.get(f"{KIMINA_SERVER_URL}/health", timeout=5)
17
+ return response.status_code == 200
18
+ except:
19
+ return False
20
+
21
+
22
+ def wait_for_server():
23
+ """等待服务器启动"""
24
+ print("等待 Kimina 服务器启动...")
25
+ start_time = time.time()
26
+
27
+ while time.time() - start_time < MAX_WAIT_TIME:
28
+ if check_server_health():
29
+ print("Kimina 服务器已就绪!")
30
+ return True
31
+ print(f"服务器尚未就绪,等待 {HEALTH_CHECK_INTERVAL} 秒...")
32
+ time.sleep(HEALTH_CHECK_INTERVAL)
33
+
34
+ print(f"等待超时 ({MAX_WAIT_TIME} 秒)")
35
+ return False
36
+
37
+
38
+ def verify_lean_code(code, infotree_type="original"):
39
+ """验证 Lean 代码"""
40
+ if not wait_for_server():
41
+ return "❌ 错误:Kimina 服务器未启动"
42
+
43
+ try:
44
+ payload = {
45
+ "codes": [{
46
+ "custom_id": "user_input",
47
+ "proof": code
48
+ }],
49
+ "infotree_type": infotree_type
50
+ }
51
+
52
+ response = requests.post(
53
+ f"{KIMINA_SERVER_URL}/verify",
54
+ json=payload,
55
+ timeout=30
56
+ )
57
+
58
+ if response.status_code == 200:
59
+ result = response.json()
60
+ if "results" in result and result["results"]:
61
+ item = result["results"][0]
62
+
63
+ if item["type"] == "success":
64
+ return f"✅ 验证成功!\n\n输出:{item.get('message', '无输出')}"
65
+ elif item["type"] == "error":
66
+ return f"❌ 验证失败:\n\n错误信息:{item.get('message', '未知错误')}"
67
+ else:
68
+ return f"⚠️ 未知结果类型:{item}"
69
+ else:
70
+ return "❌ 错误:服务器返回无效响应"
71
+ else:
72
+ return f"❌ 服务器错误 (状态码:{response.status_code}): {response.text}"
73
+
74
+ except requests.exceptions.Timeout:
75
+ return "❌ 错误:请求超时,代码可能太复杂或服务器繁忙"
76
+ except requests.exceptions.ConnectionError:
77
+ return "❌ 错误:无法连接到 Kimina 服务器"
78
+ except Exception as e:
79
+ return f"❌ 错误:{str(e)}"
80
+
81
+
82
+ def create_demo():
83
+ """创建 Gradio 界面"""
84
+
85
+ # 等待服务器启动(在后台进行)
86
+ import threading
87
+ def wait_in_background():
88
+ wait_for_server()
89
+
90
+ thread = threading.Thread(target=wait_in_background, daemon=True)
91
+ thread.start()
92
+
93
+ with gr.Blocks(title="Kimina Lean Server", theme=gr.themes.Soft()) as demo:
94
+ gr.Markdown("""
95
+ # ⚡ Kimina Lean Server
96
+ 在线验证 Lean 4 代码
97
+
98
+ ## 使用示例
99
+ ```lean
100
+ #check Nat
101
+ theorem test : 1 + 1 = 2 := by native_decide
102
+ example : 2 + 2 = 4 := by native_decide
103
+ ```
104
+ """)
105
+
106
+ with gr.Row():
107
+ with gr.Column(scale=3):
108
+ code_input = gr.Code(
109
+ label="Lean 4 代码",
110
+ value="#check Nat\ntheorem test : 1 + 1 = 2 := by native_decide",
111
+ language="python",
112
+ lines=10,
113
+ interactive=True
114
+ )
115
+
116
+ infotree_type = gr.Radio(
117
+ choices=["original", "compressed"],
118
+ value="original",
119
+ label="信息树类型",
120
+ info="选择返回的信息树格式"
121
+ )
122
+
123
+ submit_btn = gr.Button("验证代码", variant="primary", size="lg")
124
+
125
+ with gr.Column(scale=2):
126
+ output = gr.Textbox(
127
+ label="验证结果",
128
+ lines=15,
129
+ interactive=False
130
+ )
131
+
132
+ examples = gr.Examples(
133
+ examples=[
134
+ ["#check Nat", "original"],
135
+ ["theorem test : 1 + 1 = 2 := by native_decide", "original"],
136
+ ["example : True := by trivial", "original"],
137
+ ["#eval List.range 5", "original"],
138
+ ["""theorem add_comm (a b : Nat) : a + b = b + a := by
139
+ induction a with
140
+ | zero => simp
141
+ | succ a ih => simp [Nat.succ_add, ih]""", "compressed"]
142
+ ],
143
+ inputs=[code_input, infotree_type],
144
+ label="示例代码"
145
+ )
146
+
147
+ # 状态指示器
148
+ status = gr.Textbox(
149
+ value="🟡 正在启动 Kimina 服务器...",
150
+ label="服务器状态",
151
+ interactive=False
152
+ )
153
+
154
+ # 绑定事件
155
+ submit_btn.click(
156
+ fn=verify_lean_code,
157
+ inputs=[code_input, infotree_type],
158
+ outputs=output
159
+ )
160
+
161
+ # 自动更新状态
162
+ def update_status():
163
+ if check_server_health():
164
+ return "🟢 Kimina 服务器已就绪"
165
+ else:
166
+ return "🔴 Kimina 服务器未就绪"
167
+
168
+ demo.load(
169
+ fn=update_status,
170
+ outputs=status,
171
+ every=5 # 每5秒更新一次
172
+ )
173
+
174
+ gr.Markdown("""
175
+ ## 特性说明
176
+
177
+ 1. **并行验证**:支持同时验证多个代码片段
178
+ 2. **错误报告**:详细的错误信息和位置
179
+ 3. **mathlib4 支持**:内置完整的 mathlib4 库
180
+ 4. **高性能**:优化的 REPL 管理和内存控制
181
+
182
+ ## 支持的 Lean 功能
183
+
184
+ - 定理证明
185
+ - 定义检查
186
+ - 类型检查
187
+ - 求值 (#eval)
188
+ - 元编程
189
+ """)
190
+
191
+ return demo
192
+
193
+
194
+ if __name__ == "__main__":
195
+ # 在 Gradio 中启动应用
196
+ demo = create_demo()
197
+ demo.launch(
198
+ server_name="0.0.0.0",
199
+ server_port=7860,
200
+ share=False,
201
+ debug=True
202
+ )
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Kimina 客户端
2
+ kimina-client>=0.2.0
3
+
4
+ # Gradio 前端
5
+ gradio>=4.0.0
6
+
7
+ # FastAPI 和依赖
8
+ fastapi>=0.104.0
9
+ uvicorn[standard]>=0.24.0
10
+ httpx>=0.25.0
11
+
12
+ # 其他工具
13
+ structlog>=23.0.0
14
+ pydantic>=2.0.0
15
+ websockets>=12.0
start.sh ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "🚀 启动 Kimina Lean Server 空间..."
5
+
6
+ # 设置环境变量
7
+ export LEAN_SERVER_REPL_PATH="/home/user/repl/.lake/build/bin/repl"
8
+ export LEAN_SERVER_PROJECT_DIR="/home/user/mathlib4"
9
+
10
+ # 启动 Kimina 服务器(后台运行)
11
+ echo "启动 Kimina Lean Server..."
12
+ python -m server &
13
+ KIMINA_PID=$!
14
+
15
+ # 等待服务器启动
16
+ echo "等待 Kimina 服务器启动..."
17
+ sleep 10
18
+
19
+ # 检查服务器是否运行
20
+ if ps -p $KIMINA_PID > /dev/null; then
21
+ echo "✅ Kimina 服务器已启动 (PID: $KIMINA_PID)"
22
+ else
23
+ echo "❌ Kimina 服务器启动失败"
24
+ exit 1
25
+ fi
26
+
27
+ # 启动 Gradio 前端
28
+ echo "启动 Gradio 前端界面..."
29
+ python app.py
30
+
31
+ # 清理(如果前端退出)
32
+ echo "正在关闭 Kimina 服务器..."
33
+ kill $KIMINA_PID
34
+ wait $KIMINA_PID