fuliai commited on
Commit
f900ee0
·
verified ·
1 Parent(s): 6c38c84

Upload ksa-ics.py

Browse files
Files changed (1) hide show
  1. ksa-ics.py +437 -0
ksa-ics.py ADDED
@@ -0,0 +1,437 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import marimo
2
+
3
+ __generated_with = "0.10.13"
4
+ app = marimo.App(width="medium")
5
+
6
+
7
+ @app.cell
8
+ def _():
9
+ import marimo as mo
10
+ import subprocess
11
+ import os
12
+ import logging
13
+ from datetime import datetime
14
+ return datetime, logging, mo, os, subprocess
15
+
16
+
17
+ @app.cell
18
+ def _(mo):
19
+ """UI 组件:工具选择"""
20
+ ai_app = "ksa虚拟网络"
21
+ aitool_name = mo.ui.dropdown(
22
+ [f"{ai_app}"],
23
+ value=f"{ai_app}",
24
+ label="选择AI工具"
25
+ )
26
+ return ai_app, aitool_name
27
+
28
+ @app.cell
29
+ def _(aitool_name):
30
+ """虚拟环境所在文件夹、git REPO等常规变量设置"""
31
+ uv_venv_dir = f"ai_{aitool_name.value}"
32
+ git_repo_url = "https://openi.pcl.ac.cn/niubi/ComfyUI.git"
33
+ repo_name = "ComfyUI"
34
+ app_log = f"{aitool_name.value}.log"
35
+ python_ver = "3.12.8"
36
+
37
+ custom_node_1 = "comfyui-manager"
38
+ custom_node_1_repo = "https://openi.pcl.ac.cn/niubi/comfyui-manager.git"
39
+ return (
40
+ app_log,
41
+ custom_node_1,
42
+ custom_node_1_repo,
43
+ git_repo_url,
44
+ python_ver,
45
+ repo_name,
46
+ uv_venv_dir,
47
+ )
48
+
49
+
50
+ @app.cell
51
+ def _(custom_node_1, custom_node_1_repo, python_ver):
52
+ """配置类"""
53
+ class Config:
54
+ SYSTEM_DEPS = [
55
+ {
56
+ "name": "系统依赖",
57
+ "cmd": """
58
+ apt-get update
59
+ apt install build-essential libgl1 ffmpeg python3-pip aria2 git git-lfs htop -y
60
+ pip install uv -i https://mirrors.cloud.tencent.com/pypi/simple
61
+ """
62
+ }
63
+ ]
64
+
65
+ @staticmethod
66
+ def get_venv_commands(venv_dir):
67
+ return [
68
+ {
69
+ "name": "虚拟环境设置",
70
+ "cmd": f"""
71
+ echo "无需设置,直接跳过"
72
+ """
73
+ }
74
+ ]
75
+
76
+ @staticmethod
77
+ def setup_repo_commands(venv_dir, git_url, repo_name):
78
+ return [
79
+ {
80
+ "name": f"处理{repo_name}项目仓库",
81
+ "cmd": f"""
82
+ echo "无需设置,直接跳过"
83
+ """
84
+ }
85
+ ]
86
+
87
+ @staticmethod
88
+ def get_start_command(venv_dir, repo_name, app_log):
89
+ """获取启动命令"""
90
+ return {
91
+ "name": "启动服务",
92
+ "cmd": f"""
93
+ echo "无需设置,直接跳过"
94
+ """
95
+ }
96
+
97
+ @staticmethod
98
+ def get_stop_commands():
99
+ """获取停止命令"""
100
+ return [
101
+ {
102
+ "name": "停止服务",
103
+ "cmd": "echo '无需设置,直接跳过'"
104
+ }
105
+ ]
106
+
107
+ @staticmethod
108
+ def download_commands(venv_dir, repo_name):
109
+ return [
110
+ {
111
+ "name": "模型下载",
112
+ "cmd": f"""
113
+ echo "无需设置,直接跳过"
114
+ """
115
+ }
116
+ ]
117
+
118
+ @staticmethod
119
+ def get_end_show_info(venv_dir, repo_name):
120
+ """获取安装完成后的展示信息"""
121
+ return f"""
122
+ ## 安装完成后的操作说明
123
+
124
+ Q&A及资讯:
125
+ - 最新资讯及相关命令请查看 https://fuliai-ai2u.hf.space/
126
+ - 加群交流:https://qr61.cn/oohivs/qRp62U6
127
+
128
+ ## 启动程序
129
+
130
+ ```bash
131
+ /workspace/apps/ksa/ksa_x64
132
+ export HF_ENDPOINT=https://hf-mirror.com
133
+ ```
134
+ 之后使用ksa连接,比如在终端中运行了ollama,在浏览器中使用 10.0.0.1:11434 来访问ollama。
135
+ 不会用的请查看视频教程:https://www.bilibili.com/video/BV13UBRYVEmX/
136
+
137
+ ## 退出程序
138
+ ```bash
139
+ (使用 Ctrl + C)
140
+ ```
141
+ """
142
+ return (Config,)
143
+
144
+
145
+ @app.cell
146
+ def _(datetime, logging, os):
147
+ """日志处理类"""
148
+ class Logger:
149
+ def __init__(self, name):
150
+ self.logger = self._setup_logger(name)
151
+
152
+ def _setup_logger(self, name):
153
+ os.makedirs("logs", exist_ok=True)
154
+ log_file = f'logs/{name}_{datetime.now().strftime("%Y%m%d")}.log'
155
+
156
+ logger = logging.getLogger(name)
157
+ logging.basicConfig(
158
+ level=logging.INFO,
159
+ format="%(asctime)s - %(levelname)s - %(message)s",
160
+ handlers=[
161
+ logging.FileHandler(log_file, encoding="utf-8"),
162
+ logging.StreamHandler(),
163
+ ],
164
+ )
165
+ return logger
166
+
167
+ def info(self, msg): self.logger.info(msg)
168
+ def error(self, msg): self.logger.error(msg)
169
+ def warning(self, msg): self.logger.warning(msg)
170
+ return (Logger,)
171
+
172
+
173
+ @app.cell
174
+ def _(mo):
175
+ """UI 组件:功能开关"""
176
+ switches = {
177
+ "system": mo.ui.switch(label="系统依赖安装", value=True),
178
+ "venv": mo.ui.switch(label="虚拟环境设置", value=True),
179
+ "repo": mo.ui.switch(label="程序文件设置", value=True),
180
+ "app": mo.ui.switch(label="启动应用程序", value=True),
181
+ "download": mo.ui.switch(label="文件或模型下载", value=True),
182
+ }
183
+ return (switches,)
184
+
185
+
186
+ @app.cell
187
+ def _(Logger, aitool_name):
188
+ """初始化日志记录器"""
189
+ logger = Logger(aitool_name.value)
190
+ return (logger,)
191
+
192
+
193
+ @app.cell
194
+ def _(subprocess):
195
+ """命令执行工具类"""
196
+ class CommandRunner:
197
+ @staticmethod
198
+ def run(cmd, logger, check=True, step_name=""):
199
+ try:
200
+ prefix = f"[{step_name}] " if step_name else ""
201
+ logger.info(f"{prefix}正在执行命令...")
202
+ result = subprocess.run(
203
+ cmd,
204
+ shell=True,
205
+ check=check,
206
+ text=True,
207
+ capture_output=True
208
+ )
209
+ if result.stdout:
210
+ logger.info(f"{prefix}输出: {result.stdout.strip()}")
211
+ logger.info(f"{prefix}命令执行成功")
212
+ return True, None
213
+ except subprocess.CalledProcessError as e:
214
+ error_msg = f"{prefix}命令执行失败: {e.stderr if e.stderr else '未知错误'}"
215
+ logger.error(error_msg)
216
+ return False, error_msg
217
+ except KeyboardInterrupt:
218
+ logger.info(f"{prefix}用户中断了命令执行")
219
+ return False, "用户中断了命令执行"
220
+ except Exception as e:
221
+ error_msg = f"{prefix}执行出错: {str(e)}"
222
+ logger.error(error_msg)
223
+ return False, error_msg
224
+ return (CommandRunner,)
225
+
226
+
227
+ @app.cell
228
+ def _(aitool_name):
229
+ aitool_name
230
+ return
231
+
232
+
233
+ @app.cell
234
+ def _(switches):
235
+ switches
236
+ return
237
+
238
+
239
+ @app.cell
240
+ def _(CommandRunner, Config, logger, mo, switches):
241
+ """系统依赖安装"""
242
+ def install_system():
243
+ if not switches["system"].value:
244
+ return mo.md("⚠️ 请先启用系统依赖安装").callout(kind="warn")
245
+
246
+ for cmd_info in Config.SYSTEM_DEPS:
247
+ success, error = CommandRunner.run(cmd_info["cmd"], logger, step_name=cmd_info["name"])
248
+ if not success:
249
+ return mo.md(f"❌ {error}").callout(kind="danger")
250
+
251
+ return mo.md("✅ 系统依赖安装完成").callout(kind="success")
252
+
253
+ install_system()
254
+ return (install_system,)
255
+
256
+
257
+ @app.cell
258
+ def _(CommandRunner, Config, logger, mo, os, switches, uv_venv_dir):
259
+ """虚拟环境设置"""
260
+ def setup_venv():
261
+ if not switches["venv"].value:
262
+ return mo.md("⚠️ 请先启用虚拟环境设置").callout(kind="warn")
263
+
264
+ os.makedirs(uv_venv_dir, exist_ok=True)
265
+
266
+ for cmd_info in Config.get_venv_commands(uv_venv_dir):
267
+ success, error = CommandRunner.run(cmd_info["cmd"], logger, step_name=cmd_info["name"])
268
+ if not success:
269
+ return mo.md(f"❌ {error}").callout(kind="danger")
270
+
271
+ return mo.md("✅ 虚拟环境设置完成").callout(kind="success")
272
+
273
+ setup_venv()
274
+ return (setup_venv,)
275
+
276
+
277
+ @app.cell
278
+ def _(
279
+ CommandRunner,
280
+ Config,
281
+ git_repo_url,
282
+ logger,
283
+ mo,
284
+ repo_name,
285
+ switches,
286
+ uv_venv_dir,
287
+ ):
288
+ """程序文件安装设置"""
289
+ def setup_repo():
290
+ if not switches["repo"].value:
291
+ return mo.md("⚠️ 请先启用文件安装设置").callout(kind="warn")
292
+
293
+ for cmd_info in Config.setup_repo_commands(uv_venv_dir, git_repo_url, repo_name):
294
+ success, error = CommandRunner.run(cmd_info["cmd"], logger, step_name=cmd_info["name"])
295
+ if not success:
296
+ return mo.md(f"❌ {error}").callout(kind="danger")
297
+
298
+ return mo.md("✅ 程序文件设置完成").callout(kind="success")
299
+
300
+ setup_repo()
301
+ return (setup_repo,)
302
+
303
+
304
+ @app.cell
305
+ def _(
306
+ CommandRunner,
307
+ Config,
308
+ end_show,
309
+ logger,
310
+ mo,
311
+ post_end_show,
312
+ repo_name,
313
+ switches,
314
+ uv_venv_dir,
315
+ ):
316
+ """下载:文件或模型"""
317
+ def download_files():
318
+ if not switches["download"].value:
319
+ return mo.md("⚠️ 请先启用下载开关").callout(kind="warn")
320
+
321
+ try:
322
+ for cmd_info in Config.download_commands(uv_venv_dir, repo_name):
323
+ success, error = CommandRunner.run(cmd_info["cmd"], logger, step_name=cmd_info["name"])
324
+ if not success:
325
+ return mo.md(f"❌ {error}").callout(kind="danger")
326
+
327
+ # 显示下载完成信息
328
+ download_success = mo.md("✅ 相关下载已经完成").callout(kind="success")
329
+ # 显示安装完成信息
330
+ install_info = end_show()
331
+ post_info = post_end_show()
332
+
333
+ return mo.hstack([download_success, install_info, post_info])
334
+ except KeyboardInterrupt:
335
+ logger.info("用户中断了下载过程")
336
+ return mo.md("⚠️ 下载已被用户中断").callout(kind="warn")
337
+ except Exception as e:
338
+ logger.error(f"下载过程出错: {str(e)}")
339
+ return mo.md(f"❌ 下载出错: {str(e)}").callout(kind="danger")
340
+
341
+ download_files()
342
+ return (download_files,)
343
+
344
+
345
+ @app.cell
346
+ def _(Config, mo, repo_name, uv_venv_dir):
347
+ """主体完成后展示信息内容"""
348
+ def end_show():
349
+ return mo.md(Config.get_end_show_info(uv_venv_dir, repo_name)).callout(kind="success")
350
+ return (end_show,)
351
+
352
+
353
+ @app.cell
354
+ def _(Config, mo, ai_app, uv_venv_dir):
355
+ """将主体完成后展示信息内容写入说明文件"""
356
+ def post_end_show():
357
+ # 获取说明信息内容
358
+ info_content = Config.get_end_show_info(uv_venv_dir, ai_app)
359
+
360
+ # 写入说明文件
361
+ try:
362
+ with open(f"{ai_app}说明文件.md", "w", encoding="utf-8") as f:
363
+ f.write(info_content)
364
+ return mo.md(f"✅ 安装成功,使用说明已写入 {ai_app}说明文件.md").callout(kind="success")
365
+ except Exception as e:
366
+ return mo.md(f"❌ 写入说明文件失败: {str(e)}").callout(kind="danger")
367
+ return (post_end_show,)
368
+
369
+
370
+ @app.cell
371
+ def _(mo):
372
+ """创建启动和停止按钮"""
373
+ btn = mo.ui.run_button(label="启动服务", kind="info")
374
+ btn1 = mo.ui.run_button(label="停止服务", kind="info")
375
+ return btn, btn1
376
+
377
+
378
+ @app.cell
379
+ def _(btn):
380
+ btn
381
+ return
382
+
383
+
384
+ @app.cell
385
+ def _(btn1):
386
+ btn1
387
+ return
388
+
389
+
390
+ @app.cell
391
+ def _(
392
+ Config,
393
+ app_log,
394
+ btn,
395
+ btn1,
396
+ logger,
397
+ repo_name,
398
+ subprocess,
399
+ switches,
400
+ uv_venv_dir,
401
+ ):
402
+ """启动/停止应用程序"""
403
+ def handle_app():
404
+ if not switches["app"].value:
405
+ print("⚠️ 请先启用应用程序开关")
406
+ return
407
+
408
+ if btn.value:
409
+ # 获取启动配置
410
+ start_config = Config.get_start_command(uv_venv_dir, repo_name, app_log)
411
+
412
+ # 检查是否已有进程在运行
413
+ check_result = subprocess.run(start_config["check_cmd"], shell=True)
414
+ if check_result.returncode == 0:
415
+ print("⚠️ 程序已在运行中")
416
+ return
417
+
418
+ # 启动服务
419
+ logger.info("[启动服务] 正在启动应用程序...")
420
+ subprocess.run(start_config["cmd"], shell=True)
421
+ print("✅ 程序启动命令已执行")
422
+
423
+ elif btn1.value:
424
+ # 获取停止配置
425
+ stop_config = Config.get_stop_commands()[0]
426
+
427
+ # 停止服务
428
+ logger.info("[停止服务] 正在停止应用程序...")
429
+ subprocess.run(stop_config["cmd"], shell=True)
430
+ print("✅ 程序停止命令已执行")
431
+
432
+ handle_app()
433
+ return (handle_app,)
434
+
435
+
436
+ if __name__ == "__main__":
437
+ app.run()