Wendong-Fan commited on
Commit
ec6368b
·
1 Parent(s): 268015d

update deepseek example and fix format

Browse files
owl/app.py CHANGED
@@ -1,3 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import sys
3
  import gradio as gr
@@ -25,7 +38,7 @@ SCRIPTS = {
25
  "Mini": "run_mini.py",
26
  "DeepSeek (中文)": "run_deepseek_zh.py",
27
  "Default": "run.py",
28
- "GAIA Roleplaying": "run_gaia_roleplaying.py"
29
  }
30
 
31
  # 脚本描述
@@ -35,98 +48,100 @@ SCRIPT_DESCRIPTIONS = {
35
  "Mini": "轻量级版本,使用OpenAI GPT-4o模型",
36
  "DeepSeek (中文)": "使用DeepSeek模型,适合非多模态任务",
37
  "Default": "默认OWL实现,使用OpenAI GPT-4o模型和全套工具",
38
- "GAIA Roleplaying": "GAIA基准测试实现,用于评估模型能力"
39
  }
40
 
41
  # 环境变量分组
42
  ENV_GROUPS = {
43
  "模型API": [
44
  {
45
- "name": "OPENAI_API_KEY",
46
- "label": "OpenAI API密钥",
47
- "type": "password",
48
  "required": False,
49
- "help": "OpenAI API密钥,用于访问GPT模型。获取方式:https://platform.openai.com/api-keys"
50
  },
51
  {
52
- "name": "OPENAI_API_BASE_URL",
53
- "label": "OpenAI API基础URL",
54
- "type": "text",
55
  "required": False,
56
- "help": "OpenAI API的基础URL,可选。如果使用代理或自定义端点,请设置此项。"
57
  },
58
  {
59
- "name": "QWEN_API_KEY",
60
- "label": "阿里云Qwen API密钥",
61
- "type": "password",
62
  "required": False,
63
- "help": "阿里云Qwen API密钥,用于访问Qwen模型。获取方式:https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key"
64
  },
65
  {
66
- "name": "DEEPSEEK_API_KEY",
67
- "label": "DeepSeek API密钥",
68
- "type": "password",
69
  "required": False,
70
- "help": "DeepSeek API密钥,用于访问DeepSeek模型。获取方式:https://platform.deepseek.com/api_keys"
71
  },
72
  ],
73
  "搜索工具": [
74
  {
75
- "name": "GOOGLE_API_KEY",
76
- "label": "Google API密钥",
77
- "type": "password",
78
  "required": False,
79
- "help": "Google搜索API密钥,用于网络搜索功能。获取方式:https://developers.google.com/custom-search/v1/overview"
80
  },
81
  {
82
- "name": "SEARCH_ENGINE_ID",
83
- "label": "搜索引擎ID",
84
- "type": "text",
85
  "required": False,
86
- "help": "Google自定义搜索引擎ID,与Google API密钥配合使用。获取方式:https://developers.google.com/custom-search/v1/overview"
87
  },
88
  ],
89
  "其他工具": [
90
  {
91
- "name": "HF_TOKEN",
92
- "label": "Hugging Face令牌",
93
- "type": "password",
94
  "required": False,
95
- "help": "Hugging Face API令牌,用于访问Hugging Face模型和数据集。获取方式:https://huggingface.co/join"
96
  },
97
  {
98
- "name": "CHUNKR_API_KEY",
99
- "label": "Chunkr API密钥",
100
- "type": "password",
101
  "required": False,
102
- "help": "Chunkr API密钥,用于文档处理功能。获取方式:https://chunkr.ai/"
103
  },
104
  {
105
- "name": "FIRECRAWL_API_KEY",
106
- "label": "Firecrawl API密钥",
107
- "type": "password",
108
  "required": False,
109
- "help": "Firecrawl API密钥,用于网页爬取功能。获取方式:https://www.firecrawl.dev/"
110
  },
111
  ],
112
- "自定义环境变量": [] # 用户自定义的环境变量将存储在这里
113
  }
114
 
 
115
  def get_script_info(script_name):
116
  """获取脚本的详细信息"""
117
  return SCRIPT_DESCRIPTIONS.get(script_name, "无描述信息")
118
 
 
119
  def load_env_vars():
120
  """加载环境变量"""
121
  env_vars = {}
122
  # 尝试从.env文件加载
123
  dotenv.load_dotenv()
124
-
125
  # 获取所有环境变量
126
  for group in ENV_GROUPS.values():
127
  for var in group:
128
  env_vars[var["name"]] = os.environ.get(var["name"], "")
129
-
130
  # 加载.env文件中可能存在的其他环境变量
131
  if Path(".env").exists():
132
  with open(".env", "r", encoding="utf-8") as f:
@@ -135,34 +150,37 @@ def load_env_vars():
135
  if line and not line.startswith("#") and "=" in line:
136
  key, value = line.split("=", 1)
137
  key = key.strip()
138
- value = value.strip().strip('"\'')
139
-
140
  # 检查是否是已知的环境变量
141
  known_var = False
142
  for group in ENV_GROUPS.values():
143
  if any(var["name"] == key for var in group):
144
  known_var = True
145
  break
146
-
147
  # 如果不是已知的环境变量,添加到自定义环境变量组
148
  if not known_var and key not in env_vars:
149
- ENV_GROUPS["自定义环境变量"].append({
150
- "name": key,
151
- "label": key,
152
- "type": "text",
153
- "required": False,
154
- "help": "用户自定义环境变量"
155
- })
 
 
156
  env_vars[key] = value
157
-
158
  return env_vars
159
 
 
160
  def save_env_vars(env_vars):
161
  """保存环境变量到.env文件"""
162
  # 读取现有的.env文件内容
163
  env_path = Path(".env")
164
  existing_content = {}
165
-
166
  if env_path.exists():
167
  with open(env_path, "r", encoding="utf-8") as f:
168
  for line in f:
@@ -170,105 +188,116 @@ def save_env_vars(env_vars):
170
  if line and not line.startswith("#") and "=" in line:
171
  key, value = line.split("=", 1)
172
  existing_content[key.strip()] = value.strip()
173
-
174
  # 更新环境变量
175
  for key, value in env_vars.items():
176
  if value: # 只保存非空值
177
  # 确保值是字符串形式,并用引号包裹
178
  value = str(value) # 确保值是字符串
179
- if not (value.startswith('"') and value.endswith('"')) and not (value.startswith("'") and value.endswith("'")):
 
 
180
  value = f'"{value}"'
181
  existing_content[key] = value
182
  # 同时更新当前进程的环境变量
183
- os.environ[key] = value.strip('"\'')
184
-
185
  # 写入.env文件
186
  with open(env_path, "w", encoding="utf-8") as f:
187
  for key, value in existing_content.items():
188
  f.write(f"{key}={value}\n")
189
-
190
  return "✅ 环境变量已保存"
191
 
 
192
  def add_custom_env_var(name, value, var_type):
193
  """添加自定义环境变量"""
194
  if not name:
195
  return "❌ 环境变量名不能为空", None
196
-
197
  # 检查是否已存在同名环境变量
198
  for group in ENV_GROUPS.values():
199
  if any(var["name"] == name for var in group):
200
  return f"❌ 环境变量 {name} 已存在", None
201
-
202
  # 添加到自定义环境变量组
203
- ENV_GROUPS["自定义环境变量"].append({
204
- "name": name,
205
- "label": name,
206
- "type": var_type,
207
- "required": False,
208
- "help": "用户自定义环境变量"
209
- })
210
-
 
 
211
  # 保存环境变量
212
  env_vars = {name: value}
213
  save_env_vars(env_vars)
214
-
215
  # 返回成功消息和更新后的环境变量组
216
  return f"✅ 已添加环境变量 {name}", ENV_GROUPS["自定义环境变量"]
217
 
 
218
  def terminate_process():
219
  """终止当前运行的进程"""
220
  global current_process
221
-
222
  with process_lock:
223
  if current_process is not None and current_process.poll() is None:
224
  # 在Windows上使用CTRL_BREAK_EVENT,在Unix上使用SIGTERM
225
- if os.name == 'nt':
226
  current_process.send_signal(signal.CTRL_BREAK_EVENT)
227
  else:
228
  current_process.terminate()
229
-
230
  # 等待进程终止
231
  try:
232
  current_process.wait(timeout=5)
233
  except subprocess.TimeoutExpired:
234
  # 如果进程没有在5秒内终止,强制终止
235
  current_process.kill()
236
-
237
  log_queue.put("进程已终止\n")
238
  return "✅ 进程已终止"
239
  else:
240
  return "❌ 没有正在运行的进程"
241
 
 
242
  def run_script(script_dropdown, question, progress=gr.Progress()):
243
  """运行选定的脚本并返回输出"""
244
  global current_process
245
-
246
  script_name = SCRIPTS.get(script_dropdown)
247
  if not script_name:
248
  return "❌ 无效的脚本选择", "", "", "", None
249
-
250
  if not question.strip():
251
  return "请输入问题!", "", "", "", None
252
-
253
  # 清空日志队列
254
  while not log_queue.empty():
255
  log_queue.get()
256
-
257
  # 创建日志目录
258
  log_dir = Path("logs")
259
  log_dir.mkdir(exist_ok=True)
260
-
261
  # 创建带时间戳的日志文件
262
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
263
  log_file = log_dir / f"{script_name.replace('.py', '')}_{timestamp}.log"
264
-
265
  # 构建命令
266
- cmd = [sys.executable, os.path.join("owl", "script_adapter.py"), os.path.join("owl", script_name)]
267
-
 
 
 
 
268
  # 创建环境变量副本并添加问题
269
  env = os.environ.copy()
270
  env["OWL_QUESTION"] = question
271
-
272
  # 启动进程
273
  with process_lock:
274
  current_process = subprocess.Popen(
@@ -277,9 +306,9 @@ def run_script(script_dropdown, question, progress=gr.Progress()):
277
  stderr=subprocess.STDOUT,
278
  text=True,
279
  bufsize=1,
280
- env=env
281
  )
282
-
283
  # 创建线程来读取输出
284
  def read_output():
285
  try:
@@ -293,54 +322,67 @@ def run_script(script_dropdown, question, progress=gr.Progress()):
293
  log_queue.put(line)
294
  except Exception as e:
295
  log_queue.put(f"读取输出时出错: {str(e)}\n")
296
-
297
  # 启动读取线程
298
  threading.Thread(target=read_output, daemon=True).start()
299
-
300
  # 收集日志
301
  logs = []
302
  progress(0, desc="正在运行...")
303
-
304
  # 等待进程完成或超时
305
  start_time = time.time()
306
  timeout = 1800 # 30分钟超时
307
-
308
  while current_process.poll() is None:
309
  # 检查是否超时
310
  if time.time() - start_time > timeout:
311
  with process_lock:
312
  if current_process.poll() is None:
313
- if os.name == 'nt':
314
  current_process.send_signal(signal.CTRL_BREAK_EVENT)
315
  else:
316
  current_process.terminate()
317
  log_queue.put("执行超时,已终止进程\n")
318
  break
319
-
320
  # 从队列获取日志
321
  while not log_queue.empty():
322
  log = log_queue.get()
323
  logs.append(log)
324
-
325
  # 更新进度
326
  elapsed = time.time() - start_time
327
  progress(min(elapsed / 300, 0.99), desc="正在运行...")
328
-
329
  # 短暂休眠以减少CPU使用
330
  time.sleep(0.1)
331
-
332
  # 每秒更新一次日志显示
333
- yield status_message(current_process), extract_answer(logs), "".join(logs), str(log_file), None
334
-
 
 
 
 
 
 
335
  # 获取剩余日志
336
  while not log_queue.empty():
337
  logs.append(log_queue.get())
338
-
339
  # 提取聊天历史(如果有)
340
  chat_history = extract_chat_history(logs)
341
-
342
  # 返回最终状态和日志
343
- return status_message(current_process), extract_answer(logs), "".join(logs), str(log_file), chat_history
 
 
 
 
 
 
 
344
 
345
  def status_message(process):
346
  """根据进程状态返回状态消息"""
@@ -351,6 +393,7 @@ def status_message(process):
351
  else:
352
  return f"❌ 执行失败 (返回码: {process.returncode})"
353
 
 
354
  def extract_answer(logs):
355
  """从日志中提取答案"""
356
  answer = ""
@@ -360,12 +403,13 @@ def extract_answer(logs):
360
  break
361
  return answer
362
 
 
363
  def extract_chat_history(logs):
364
  """尝试从日志中提取聊天历史"""
365
  try:
366
  chat_json_str = ""
367
  capture_json = False
368
-
369
  for log in logs:
370
  if "chat_history" in log:
371
  # 开始捕获JSON
@@ -384,7 +428,7 @@ def extract_chat_history(logs):
384
  # 清理可能的额外文本
385
  json_str = chat_json_str[:end_idx].strip()
386
  chat_data = json.loads(json_str)
387
-
388
  # 格式化为Gradio聊天组件可用的格式
389
  formatted_chat = []
390
  for msg in chat_data:
@@ -402,11 +446,12 @@ def extract_chat_history(logs):
402
  pass
403
  return None
404
 
 
405
  def create_ui():
406
  """创建Gradio界面"""
407
  # 加载环境变量
408
  env_vars = load_env_vars()
409
-
410
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as app:
411
  gr.Markdown(
412
  """
@@ -415,7 +460,7 @@ def create_ui():
415
  选择一个模型并输入您的问题,系统将运行相应的脚本并显示结果。
416
  """
417
  )
418
-
419
  with gr.Tabs() as tabs:
420
  with gr.TabItem("运行模式"):
421
  with gr.Row():
@@ -425,144 +470,173 @@ def create_ui():
425
  script_dropdown = gr.Dropdown(
426
  choices=list(SCRIPTS.keys()),
427
  value=default_script,
428
- label="选择模式"
429
  )
430
-
431
  script_info = gr.Textbox(
432
- value=get_script_info(default_script) if default_script else "",
 
 
433
  label="模型描述",
434
- interactive=False
435
  )
436
-
437
  script_dropdown.change(
438
  fn=lambda x: get_script_info(x),
439
  inputs=script_dropdown,
440
- outputs=script_info
441
  )
442
-
443
  question_input = gr.Textbox(
444
- lines=5,
445
- placeholder="请输入您的问题...",
446
- label="问题"
447
  )
448
-
449
  gr.Markdown(
450
  """
451
  > **注意**: 您输入的问题将替换脚本中的默认问题。系统会自动处理问题的替换,确保您的问题被正确使用。
452
  """
453
  )
454
-
455
  with gr.Row():
456
  run_button = gr.Button("运行", variant="primary")
457
  stop_button = gr.Button("终止", variant="stop")
458
-
459
  with gr.Column(scale=2):
460
  with gr.Tabs():
461
  with gr.TabItem("结果"):
462
  status_output = gr.Textbox(label="状态")
463
  answer_output = gr.Textbox(label="回答", lines=10)
464
  log_file_output = gr.Textbox(label="日志文件路径")
465
-
466
  with gr.TabItem("运行日志"):
467
  log_output = gr.Textbox(label="完整日志", lines=25)
468
-
469
  with gr.TabItem("聊天历史"):
470
  chat_output = gr.Chatbot(label="对话历史")
471
-
472
  # 示例问题
473
  examples = [
474
- ["Qwen Mini (中文)", "浏览亚马逊并找出一款对程序员有吸引力的产品。请提供产品名称和价格"],
475
- ["DeepSeek (中文)", "请分析GitHub上CAMEL-AI项目的最新统计数据。找出该项目的星标数量、贡献者数量和最近的活跃度。然后,创建一个简单的Excel表格来展示这些数据,并生成一个柱状图来可视化这些指标。最后,总结CAMEL项目的受欢迎程度和发展趋势。"],
476
- ["Default", "Navigate to Amazon.com and identify one product that is attractive to coders. Please provide me with the product name and price. No need to verify your answer."]
 
 
 
 
 
 
 
 
 
477
  ]
478
-
479
- gr.Examples(
480
- examples=examples,
481
- inputs=[script_dropdown, question_input]
482
- )
483
-
484
  with gr.TabItem("环境变量配置"):
485
  env_inputs = {}
486
  save_status = gr.Textbox(label="保存状态", interactive=False)
487
-
488
  # 添加自定义环境变量部分
489
  with gr.Accordion("添加自定义环境变量", open=True):
490
  with gr.Row():
491
- new_var_name = gr.Textbox(label="环境变量名", placeholder="例如:MY_CUSTOM_API_KEY")
492
- new_var_value = gr.Textbox(label="环境变量值", placeholder="输入值")
 
 
 
 
493
  new_var_type = gr.Dropdown(
494
- choices=["text", "password"],
495
- value="text",
496
- label="类型"
497
  )
498
-
499
  add_var_button = gr.Button("添加环境变量", variant="primary")
500
  add_var_status = gr.Textbox(label="添加状态", interactive=False)
501
-
502
  # 自定义环境变量列表
503
  custom_vars_list = gr.JSON(
504
  value=ENV_GROUPS["自定义环境变量"],
505
  label="已添加的自定义环境变量",
506
- visible=len(ENV_GROUPS["自定义环境变量"]) > 0
507
  )
508
-
509
  # 添加环境变量按钮点击事件
510
  add_var_button.click(
511
  fn=add_custom_env_var,
512
  inputs=[new_var_name, new_var_value, new_var_type],
513
- outputs=[add_var_status, custom_vars_list]
514
  )
515
-
516
  # 现有环境变量配置
517
  for group_name, vars in ENV_GROUPS.items():
518
- if group_name != "自定义环境变量" or len(vars) > 0: # 只显示非空的自定义环境变量组
519
- with gr.Accordion(group_name, open=(group_name != "自定义环境变量")):
 
 
 
 
520
  for var in vars:
521
  # 添加帮助信息
522
  gr.Markdown(f"**{var['help']}**")
523
-
524
  if var["type"] == "password":
525
  env_inputs[var["name"]] = gr.Textbox(
526
  value=env_vars.get(var["name"], ""),
527
  label=var["label"],
528
  placeholder=f"请输入{var['label']}",
529
- type="password"
530
  )
531
  else:
532
  env_inputs[var["name"]] = gr.Textbox(
533
  value=env_vars.get(var["name"], ""),
534
  label=var["label"],
535
- placeholder=f"请输入{var['label']}"
536
  )
537
-
538
  save_button = gr.Button("保存环境变量", variant="primary")
539
-
540
  # 保存环境变量
541
- save_inputs = [env_inputs[var_name] for group in ENV_GROUPS.values() for var in group for var_name in [var["name"]] if var_name in env_inputs]
 
 
 
 
 
 
542
  save_button.click(
543
- fn=lambda *values: save_env_vars(dict(zip([var["name"] for group in ENV_GROUPS.values() for var in group if var["name"] in env_inputs], values))),
 
 
 
 
 
 
 
 
 
 
 
 
544
  inputs=save_inputs,
545
- outputs=save_status
546
  )
547
-
548
  # 运行脚本
549
  run_button.click(
550
  fn=run_script,
551
- inputs=[
552
- script_dropdown,
553
- question_input
 
 
 
 
554
  ],
555
- outputs=[status_output, answer_output, log_output, log_file_output, chat_output],
556
- show_progress=True
557
  )
558
-
559
  # 终止运行
560
- stop_button.click(
561
- fn=terminate_process,
562
- inputs=[],
563
- outputs=[status_output]
564
- )
565
-
566
  # 添加页脚
567
  gr.Markdown(
568
  """
@@ -585,10 +659,11 @@ def create_ui():
585
  - 您输入的问题将替换脚本中的默认问题,确保问题与所选模型兼容
586
  """
587
  )
588
-
589
  return app
590
 
 
591
  if __name__ == "__main__":
592
  # 创建并启动应用
593
  app = create_ui()
594
- app.queue().launch(share=True)
 
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
  import os
15
  import sys
16
  import gradio as gr
 
38
  "Mini": "run_mini.py",
39
  "DeepSeek (中文)": "run_deepseek_zh.py",
40
  "Default": "run.py",
41
+ "GAIA Roleplaying": "run_gaia_roleplaying.py",
42
  }
43
 
44
  # 脚本描述
 
48
  "Mini": "轻量级版本,使用OpenAI GPT-4o模型",
49
  "DeepSeek (中文)": "使用DeepSeek模型,适合非多模态任务",
50
  "Default": "默认OWL实现,使用OpenAI GPT-4o模型和全套工具",
51
+ "GAIA Roleplaying": "GAIA基准测试实现,用于评估模型能力",
52
  }
53
 
54
  # 环境变量分组
55
  ENV_GROUPS = {
56
  "模型API": [
57
  {
58
+ "name": "OPENAI_API_KEY",
59
+ "label": "OpenAI API密钥",
60
+ "type": "password",
61
  "required": False,
62
+ "help": "OpenAI API密钥,用于访问GPT模型。获取方式:https://platform.openai.com/api-keys",
63
  },
64
  {
65
+ "name": "OPENAI_API_BASE_URL",
66
+ "label": "OpenAI API基础URL",
67
+ "type": "text",
68
  "required": False,
69
+ "help": "OpenAI API的基础URL,可选。如果使用代理或自定义端点,请设置此项。",
70
  },
71
  {
72
+ "name": "QWEN_API_KEY",
73
+ "label": "阿里云Qwen API密钥",
74
+ "type": "password",
75
  "required": False,
76
+ "help": "阿里云Qwen API密钥,用于访问Qwen模型。获取方式:https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key",
77
  },
78
  {
79
+ "name": "DEEPSEEK_API_KEY",
80
+ "label": "DeepSeek API密钥",
81
+ "type": "password",
82
  "required": False,
83
+ "help": "DeepSeek API密钥,用于访问DeepSeek模型。获取方式:https://platform.deepseek.com/api_keys",
84
  },
85
  ],
86
  "搜索工具": [
87
  {
88
+ "name": "GOOGLE_API_KEY",
89
+ "label": "Google API密钥",
90
+ "type": "password",
91
  "required": False,
92
+ "help": "Google搜索API密钥,用于网络搜索功能。获取方式:https://developers.google.com/custom-search/v1/overview",
93
  },
94
  {
95
+ "name": "SEARCH_ENGINE_ID",
96
+ "label": "搜索引擎ID",
97
+ "type": "text",
98
  "required": False,
99
+ "help": "Google自定义搜索引擎ID,与Google API密钥配合使用。获取方式:https://developers.google.com/custom-search/v1/overview",
100
  },
101
  ],
102
  "其他工具": [
103
  {
104
+ "name": "HF_TOKEN",
105
+ "label": "Hugging Face令牌",
106
+ "type": "password",
107
  "required": False,
108
+ "help": "Hugging Face API令牌,用于访问Hugging Face模型和数据集。获取方式:https://huggingface.co/join",
109
  },
110
  {
111
+ "name": "CHUNKR_API_KEY",
112
+ "label": "Chunkr API密钥",
113
+ "type": "password",
114
  "required": False,
115
+ "help": "Chunkr API密钥,用于文档处理功能。获取方式:https://chunkr.ai/",
116
  },
117
  {
118
+ "name": "FIRECRAWL_API_KEY",
119
+ "label": "Firecrawl API密钥",
120
+ "type": "password",
121
  "required": False,
122
+ "help": "Firecrawl API密钥,用于网页爬取功能。获取方式:https://www.firecrawl.dev/",
123
  },
124
  ],
125
+ "自定义环境变量": [], # 用户自定义的环境变量将存储在这里
126
  }
127
 
128
+
129
  def get_script_info(script_name):
130
  """获取脚本的详细信息"""
131
  return SCRIPT_DESCRIPTIONS.get(script_name, "无描述信息")
132
 
133
+
134
  def load_env_vars():
135
  """加载环境变量"""
136
  env_vars = {}
137
  # 尝试从.env文件加载
138
  dotenv.load_dotenv()
139
+
140
  # 获取所有环境变量
141
  for group in ENV_GROUPS.values():
142
  for var in group:
143
  env_vars[var["name"]] = os.environ.get(var["name"], "")
144
+
145
  # 加载.env文件中可能存在的其他环境变量
146
  if Path(".env").exists():
147
  with open(".env", "r", encoding="utf-8") as f:
 
150
  if line and not line.startswith("#") and "=" in line:
151
  key, value = line.split("=", 1)
152
  key = key.strip()
153
+ value = value.strip().strip("\"'")
154
+
155
  # 检查是否是已知的环境变量
156
  known_var = False
157
  for group in ENV_GROUPS.values():
158
  if any(var["name"] == key for var in group):
159
  known_var = True
160
  break
161
+
162
  # 如果不是已知的环境变量,添加到自定义环境变量组
163
  if not known_var and key not in env_vars:
164
+ ENV_GROUPS["自定义环境变量"].append(
165
+ {
166
+ "name": key,
167
+ "label": key,
168
+ "type": "text",
169
+ "required": False,
170
+ "help": "用户自定义环境变量",
171
+ }
172
+ )
173
  env_vars[key] = value
174
+
175
  return env_vars
176
 
177
+
178
  def save_env_vars(env_vars):
179
  """保存环境变量到.env文件"""
180
  # 读取现有的.env文件内容
181
  env_path = Path(".env")
182
  existing_content = {}
183
+
184
  if env_path.exists():
185
  with open(env_path, "r", encoding="utf-8") as f:
186
  for line in f:
 
188
  if line and not line.startswith("#") and "=" in line:
189
  key, value = line.split("=", 1)
190
  existing_content[key.strip()] = value.strip()
191
+
192
  # 更新环境变量
193
  for key, value in env_vars.items():
194
  if value: # 只保存非空值
195
  # 确保值是字符串形式,并用引号包裹
196
  value = str(value) # 确保值是字符串
197
+ if not (value.startswith('"') and value.endswith('"')) and not (
198
+ value.startswith("'") and value.endswith("'")
199
+ ):
200
  value = f'"{value}"'
201
  existing_content[key] = value
202
  # 同时更新当前进程的环境变量
203
+ os.environ[key] = value.strip("\"'")
204
+
205
  # 写入.env文件
206
  with open(env_path, "w", encoding="utf-8") as f:
207
  for key, value in existing_content.items():
208
  f.write(f"{key}={value}\n")
209
+
210
  return "✅ 环境变量已保存"
211
 
212
+
213
  def add_custom_env_var(name, value, var_type):
214
  """添加自定义环境变量"""
215
  if not name:
216
  return "❌ 环境变量名不能为空", None
217
+
218
  # 检查是否已存在同名环境变量
219
  for group in ENV_GROUPS.values():
220
  if any(var["name"] == name for var in group):
221
  return f"❌ 环境变量 {name} 已存在", None
222
+
223
  # 添加到自定义环境变量组
224
+ ENV_GROUPS["自定义环境变量"].append(
225
+ {
226
+ "name": name,
227
+ "label": name,
228
+ "type": var_type,
229
+ "required": False,
230
+ "help": "用户自定义环境变量",
231
+ }
232
+ )
233
+
234
  # 保存环境变量
235
  env_vars = {name: value}
236
  save_env_vars(env_vars)
237
+
238
  # 返回成功消息和更新后的环境变量组
239
  return f"✅ 已添加环境变量 {name}", ENV_GROUPS["自定义环境变量"]
240
 
241
+
242
  def terminate_process():
243
  """终止当前运行的进程"""
244
  global current_process
245
+
246
  with process_lock:
247
  if current_process is not None and current_process.poll() is None:
248
  # 在Windows上使用CTRL_BREAK_EVENT,在Unix上使用SIGTERM
249
+ if os.name == "nt":
250
  current_process.send_signal(signal.CTRL_BREAK_EVENT)
251
  else:
252
  current_process.terminate()
253
+
254
  # 等待进程终止
255
  try:
256
  current_process.wait(timeout=5)
257
  except subprocess.TimeoutExpired:
258
  # 如果进程没有在5秒内终止,强制终止
259
  current_process.kill()
260
+
261
  log_queue.put("进程已终止\n")
262
  return "✅ 进程已终止"
263
  else:
264
  return "❌ 没有正在运行的进程"
265
 
266
+
267
  def run_script(script_dropdown, question, progress=gr.Progress()):
268
  """运行选定的脚本并返回输出"""
269
  global current_process
270
+
271
  script_name = SCRIPTS.get(script_dropdown)
272
  if not script_name:
273
  return "❌ 无效的脚本选择", "", "", "", None
274
+
275
  if not question.strip():
276
  return "请输入问题!", "", "", "", None
277
+
278
  # 清空日志队列
279
  while not log_queue.empty():
280
  log_queue.get()
281
+
282
  # 创建日志目录
283
  log_dir = Path("logs")
284
  log_dir.mkdir(exist_ok=True)
285
+
286
  # 创建带时间戳的日志文件
287
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
288
  log_file = log_dir / f"{script_name.replace('.py', '')}_{timestamp}.log"
289
+
290
  # 构建命令
291
+ cmd = [
292
+ sys.executable,
293
+ os.path.join("owl", "script_adapter.py"),
294
+ os.path.join("owl", script_name),
295
+ ]
296
+
297
  # 创建环境变量副本并添加问题
298
  env = os.environ.copy()
299
  env["OWL_QUESTION"] = question
300
+
301
  # 启动进程
302
  with process_lock:
303
  current_process = subprocess.Popen(
 
306
  stderr=subprocess.STDOUT,
307
  text=True,
308
  bufsize=1,
309
+ env=env,
310
  )
311
+
312
  # 创建线程来读取输出
313
  def read_output():
314
  try:
 
322
  log_queue.put(line)
323
  except Exception as e:
324
  log_queue.put(f"读取输出时出错: {str(e)}\n")
325
+
326
  # 启动读取线程
327
  threading.Thread(target=read_output, daemon=True).start()
328
+
329
  # 收集日志
330
  logs = []
331
  progress(0, desc="正在运行...")
332
+
333
  # 等待进程完成或超时
334
  start_time = time.time()
335
  timeout = 1800 # 30分钟超时
336
+
337
  while current_process.poll() is None:
338
  # 检查是否超时
339
  if time.time() - start_time > timeout:
340
  with process_lock:
341
  if current_process.poll() is None:
342
+ if os.name == "nt":
343
  current_process.send_signal(signal.CTRL_BREAK_EVENT)
344
  else:
345
  current_process.terminate()
346
  log_queue.put("执行超时,已终止进程\n")
347
  break
348
+
349
  # 从队列获取日志
350
  while not log_queue.empty():
351
  log = log_queue.get()
352
  logs.append(log)
353
+
354
  # 更新进度
355
  elapsed = time.time() - start_time
356
  progress(min(elapsed / 300, 0.99), desc="正在运行...")
357
+
358
  # 短暂休眠以减少CPU使用
359
  time.sleep(0.1)
360
+
361
  # 每秒更新一次日志显示
362
+ yield (
363
+ status_message(current_process),
364
+ extract_answer(logs),
365
+ "".join(logs),
366
+ str(log_file),
367
+ None,
368
+ )
369
+
370
  # 获取剩余日志
371
  while not log_queue.empty():
372
  logs.append(log_queue.get())
373
+
374
  # 提取聊天历史(如果有)
375
  chat_history = extract_chat_history(logs)
376
+
377
  # 返回最终状态和日志
378
+ return (
379
+ status_message(current_process),
380
+ extract_answer(logs),
381
+ "".join(logs),
382
+ str(log_file),
383
+ chat_history,
384
+ )
385
+
386
 
387
  def status_message(process):
388
  """根据进程状态返回状态消息"""
 
393
  else:
394
  return f"❌ 执行失败 (返回码: {process.returncode})"
395
 
396
+
397
  def extract_answer(logs):
398
  """从日志中提取答案"""
399
  answer = ""
 
403
  break
404
  return answer
405
 
406
+
407
  def extract_chat_history(logs):
408
  """尝试从日志中提取聊天历史"""
409
  try:
410
  chat_json_str = ""
411
  capture_json = False
412
+
413
  for log in logs:
414
  if "chat_history" in log:
415
  # 开始捕获JSON
 
428
  # 清理可能的额外文本
429
  json_str = chat_json_str[:end_idx].strip()
430
  chat_data = json.loads(json_str)
431
+
432
  # 格式化为Gradio聊天组件可用的格式
433
  formatted_chat = []
434
  for msg in chat_data:
 
446
  pass
447
  return None
448
 
449
+
450
  def create_ui():
451
  """创建Gradio界面"""
452
  # 加载环境变量
453
  env_vars = load_env_vars()
454
+
455
  with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue")) as app:
456
  gr.Markdown(
457
  """
 
460
  选择一个模型并输入您的问题,系统将运行相应的脚本并显示结果。
461
  """
462
  )
463
+
464
  with gr.Tabs() as tabs:
465
  with gr.TabItem("运行模式"):
466
  with gr.Row():
 
470
  script_dropdown = gr.Dropdown(
471
  choices=list(SCRIPTS.keys()),
472
  value=default_script,
473
+ label="选择模式",
474
  )
475
+
476
  script_info = gr.Textbox(
477
+ value=get_script_info(default_script)
478
+ if default_script
479
+ else "",
480
  label="模型描述",
481
+ interactive=False,
482
  )
483
+
484
  script_dropdown.change(
485
  fn=lambda x: get_script_info(x),
486
  inputs=script_dropdown,
487
+ outputs=script_info,
488
  )
489
+
490
  question_input = gr.Textbox(
491
+ lines=5, placeholder="请输入您的问题...", label="问题"
 
 
492
  )
493
+
494
  gr.Markdown(
495
  """
496
  > **注意**: 您输入的问题将替换脚本中的默认问题。系统会自动处理问题的替换,确保您的问题被正确使用。
497
  """
498
  )
499
+
500
  with gr.Row():
501
  run_button = gr.Button("运行", variant="primary")
502
  stop_button = gr.Button("终止", variant="stop")
503
+
504
  with gr.Column(scale=2):
505
  with gr.Tabs():
506
  with gr.TabItem("结果"):
507
  status_output = gr.Textbox(label="状态")
508
  answer_output = gr.Textbox(label="回答", lines=10)
509
  log_file_output = gr.Textbox(label="日志文件路径")
510
+
511
  with gr.TabItem("运行日志"):
512
  log_output = gr.Textbox(label="完整日志", lines=25)
513
+
514
  with gr.TabItem("聊天历史"):
515
  chat_output = gr.Chatbot(label="对话历史")
516
+
517
  # 示例问题
518
  examples = [
519
+ [
520
+ "Qwen Mini (中文)",
521
+ "浏览亚马逊并找出一款对程序员有吸引力的产品。请提供产品名称和价格",
522
+ ],
523
+ [
524
+ "DeepSeek (中文)",
525
+ "请分析GitHub上CAMEL-AI项目的最新统计数据。找出该项目的星标数量、贡献者数量和最近的活跃度。然后,创建一个简单的Excel表格来展示这些数据,并生成一个柱状图来可视化这些指标。最后,总结CAMEL项目的受欢迎程度和发展趋势。",
526
+ ],
527
+ [
528
+ "Default",
529
+ "Navigate to Amazon.com and identify one product that is attractive to coders. Please provide me with the product name and price. No need to verify your answer.",
530
+ ],
531
  ]
532
+
533
+ gr.Examples(examples=examples, inputs=[script_dropdown, question_input])
534
+
 
 
 
535
  with gr.TabItem("环境变量配置"):
536
  env_inputs = {}
537
  save_status = gr.Textbox(label="保存状态", interactive=False)
538
+
539
  # 添加自定义环境变量部分
540
  with gr.Accordion("添加自定义环境变量", open=True):
541
  with gr.Row():
542
+ new_var_name = gr.Textbox(
543
+ label="环境变量名", placeholder="例如:MY_CUSTOM_API_KEY"
544
+ )
545
+ new_var_value = gr.Textbox(
546
+ label="环境变量值", placeholder="输入值"
547
+ )
548
  new_var_type = gr.Dropdown(
549
+ choices=["text", "password"], value="text", label="类型"
 
 
550
  )
551
+
552
  add_var_button = gr.Button("添加环境变量", variant="primary")
553
  add_var_status = gr.Textbox(label="添加状态", interactive=False)
554
+
555
  # 自定义环境变量列表
556
  custom_vars_list = gr.JSON(
557
  value=ENV_GROUPS["自定义环境变量"],
558
  label="已添加的自定义环境变量",
559
+ visible=len(ENV_GROUPS["自定义环境变量"]) > 0,
560
  )
561
+
562
  # 添加环境变量按钮点击事件
563
  add_var_button.click(
564
  fn=add_custom_env_var,
565
  inputs=[new_var_name, new_var_value, new_var_type],
566
+ outputs=[add_var_status, custom_vars_list],
567
  )
568
+
569
  # 现有环境变量配置
570
  for group_name, vars in ENV_GROUPS.items():
571
+ if (
572
+ group_name != "自定义环境变量" or len(vars) > 0
573
+ ): # 只显示非空的自定义环境变量组
574
+ with gr.Accordion(
575
+ group_name, open=(group_name != "自定义环境变量")
576
+ ):
577
  for var in vars:
578
  # 添加帮助信息
579
  gr.Markdown(f"**{var['help']}**")
580
+
581
  if var["type"] == "password":
582
  env_inputs[var["name"]] = gr.Textbox(
583
  value=env_vars.get(var["name"], ""),
584
  label=var["label"],
585
  placeholder=f"请输入{var['label']}",
586
+ type="password",
587
  )
588
  else:
589
  env_inputs[var["name"]] = gr.Textbox(
590
  value=env_vars.get(var["name"], ""),
591
  label=var["label"],
592
+ placeholder=f"请输入{var['label']}",
593
  )
594
+
595
  save_button = gr.Button("保存环境变量", variant="primary")
596
+
597
  # 保存环境变量
598
+ save_inputs = [
599
+ env_inputs[var_name]
600
+ for group in ENV_GROUPS.values()
601
+ for var in group
602
+ for var_name in [var["name"]]
603
+ if var_name in env_inputs
604
+ ]
605
  save_button.click(
606
+ fn=lambda *values: save_env_vars(
607
+ dict(
608
+ zip(
609
+ [
610
+ var["name"]
611
+ for group in ENV_GROUPS.values()
612
+ for var in group
613
+ if var["name"] in env_inputs
614
+ ],
615
+ values,
616
+ )
617
+ )
618
+ ),
619
  inputs=save_inputs,
620
+ outputs=save_status,
621
  )
622
+
623
  # 运行脚本
624
  run_button.click(
625
  fn=run_script,
626
+ inputs=[script_dropdown, question_input],
627
+ outputs=[
628
+ status_output,
629
+ answer_output,
630
+ log_output,
631
+ log_file_output,
632
+ chat_output,
633
  ],
634
+ show_progress=True,
 
635
  )
636
+
637
  # 终止运行
638
+ stop_button.click(fn=terminate_process, inputs=[], outputs=[status_output])
639
+
 
 
 
 
640
  # 添加页脚
641
  gr.Markdown(
642
  """
 
659
  - 您输入的问题将替换脚本中的默认问题,确保问题与所选模型兼容
660
  """
661
  )
662
+
663
  return app
664
 
665
+
666
  if __name__ == "__main__":
667
  # 创建并启动应用
668
  app = create_ui()
669
+ app.queue().launch(share=True)
owl/run_deepseek_zh.py CHANGED
@@ -81,6 +81,11 @@ def construct_society(question: str) -> OwlRolePlaying:
81
  model_type=ModelType.DEEPSEEK_CHAT,
82
  model_config_dict={"temperature": 0},
83
  ),
 
 
 
 
 
84
  }
85
 
86
  # Configure toolkits
@@ -89,7 +94,7 @@ def construct_society(question: str) -> OwlRolePlaying:
89
  SearchToolkit().search_duckduckgo,
90
  SearchToolkit().search_wiki,
91
  *ExcelToolkit().get_tools(),
92
- *DocumentProcessingToolkit().get_tools(),
93
  ]
94
 
95
  # Configure agent roles and parameters
 
81
  model_type=ModelType.DEEPSEEK_CHAT,
82
  model_config_dict={"temperature": 0},
83
  ),
84
+ "document": ModelFactory.create(
85
+ model_platform=ModelPlatformType.DEEPSEEK,
86
+ model_type=ModelType.DEEPSEEK_CHAT,
87
+ model_config_dict={"temperature": 0},
88
+ ),
89
  }
90
 
91
  # Configure toolkits
 
94
  SearchToolkit().search_duckduckgo,
95
  SearchToolkit().search_wiki,
96
  *ExcelToolkit().get_tools(),
97
+ *DocumentProcessingToolkit(model=models["document"]).get_tools(),
98
  ]
99
 
100
  # Configure agent roles and parameters
owl/script_adapter.py CHANGED
@@ -1,3 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
  import sys
3
  import importlib.util
@@ -5,6 +18,7 @@ import re
5
  from pathlib import Path
6
  import traceback
7
 
 
8
  def load_module_from_path(module_name, file_path):
9
  """从文件路径加载Python模块"""
10
  try:
@@ -12,7 +26,7 @@ def load_module_from_path(module_name, file_path):
12
  if spec is None:
13
  print(f"错误: 无法从 {file_path} 创建模块规范")
14
  return None
15
-
16
  module = importlib.util.module_from_spec(spec)
17
  sys.modules[module_name] = module
18
  spec.loader.exec_module(module)
@@ -22,6 +36,7 @@ def load_module_from_path(module_name, file_path):
22
  traceback.print_exc()
23
  return None
24
 
 
25
  def run_script_with_env_question(script_name):
26
  """使用环境变量中的问题运行脚本"""
27
  # 获取环境变量中的问题
@@ -29,16 +44,16 @@ def run_script_with_env_question(script_name):
29
  if not question:
30
  print("错误: 未设置OWL_QUESTION环境变量")
31
  sys.exit(1)
32
-
33
  # 脚本路径
34
  script_path = Path(script_name).resolve()
35
  if not script_path.exists():
36
  print(f"错误: 脚本 {script_path} 不存在")
37
  sys.exit(1)
38
-
39
  # 创建临时文件路径
40
  temp_script_path = script_path.with_name(f"temp_{script_path.name}")
41
-
42
  try:
43
  # 读取脚本内容
44
  try:
@@ -47,44 +62,55 @@ def run_script_with_env_question(script_name):
47
  except Exception as e:
48
  print(f"读取脚本文件时出错: {e}")
49
  sys.exit(1)
50
-
51
  # 检查脚本是否有main函数
52
- has_main = re.search(r'def\s+main\s*\(\s*\)\s*:', content) is not None
53
-
54
  # 转义问题中的特殊字符
55
- escaped_question = question.replace("\\", "\\\\").replace("\"", "\\\"").replace("'", "\\'")
56
-
 
 
57
  # 查找脚本中所有的question赋值 - 改进的正则表达式
58
  # 匹配单行和多行字符串赋值
59
- question_assignments = re.findall(r'question\s*=\s*(?:["\'].*?["\']|""".*?"""|\'\'\'.*?\'\'\'|\(.*?\))', content, re.DOTALL)
 
 
 
 
60
  print(f"在脚本中找到 {len(question_assignments)} 个question赋值")
61
-
62
  # 修改脚本内容,替换所有的question赋值
63
  modified_content = content
64
-
65
  # 如果脚本中有question赋值,替换所有的赋值
66
  if question_assignments:
67
  for assignment in question_assignments:
68
  modified_content = modified_content.replace(
69
- assignment,
70
- f'question = "{escaped_question}"'
71
  )
72
  print(f"已替换脚本中的所有question赋值为: {question}")
73
  else:
74
  # 如果没有找到question赋值,尝试在main函数前插入
75
  if has_main:
76
- main_match = re.search(r'def\s+main\s*\(\s*\)\s*:', content)
77
  if main_match:
78
  insert_pos = main_match.start()
79
- modified_content = content[:insert_pos] + f'\n# 用户输入的问题\nquestion = "{escaped_question}"\n\n' + content[insert_pos:]
 
 
 
 
80
  print(f"已在main函数前插入问题: {question}")
81
  else:
82
  # 如果没有main函数,在文件开头插入
83
- modified_content = f'# 用户输入的问题\nquestion = "{escaped_question}"\n\n' + content
 
 
84
  print(f"已在文件开头插入问题: {question}")
85
-
86
  # 添加monkey patch代码,确保construct_society函数使用用户的问题
87
- monkey_patch_code = f'''
88
  # 确保construct_society函数使用用户的问题
89
  original_construct_society = globals().get('construct_society')
90
  if original_construct_society:
@@ -95,24 +121,28 @@ if original_construct_society:
95
  # 替换原始函数
96
  globals()['construct_society'] = patched_construct_society
97
  print("已修补construct_society函数,确保使用用户问题")
98
- '''
99
-
100
  # 在文件末尾添加monkey patch代码
101
  modified_content += monkey_patch_code
102
-
103
  # 如果脚本没有调用main函数,添加调用代码
104
  if has_main and "__main__" not in content:
105
- modified_content += '''
106
 
107
  # 确保调用main函数
108
  if __name__ == "__main__":
109
  main()
110
- '''
111
  print("已添加main函数调用代码")
112
-
113
  # 如果脚本没有construct_society调用,添加调用代码
114
- if "construct_society" in content and "run_society" in content and "Answer:" not in content:
115
- modified_content += f'''
 
 
 
 
116
 
117
  # 确保执行construct_society和run_society
118
  if "construct_society" in globals() and "run_society" in globals():
@@ -125,16 +155,16 @@ if "construct_society" in globals() and "run_society" in globals():
125
  print(f"运行时出错: {{e}}")
126
  import traceback
127
  traceback.print_exc()
128
- '''
129
  print("已添加construct_society和run_society调用代码")
130
-
131
  # 执行修改后的脚本
132
  try:
133
  # 将脚本目录添加到sys.path
134
  script_dir = script_path.parent
135
  if str(script_dir) not in sys.path:
136
  sys.path.insert(0, str(script_dir))
137
-
138
  # 创建临时文件
139
  try:
140
  with open(temp_script_path, "w", encoding="utf-8") as f:
@@ -143,32 +173,34 @@ if "construct_society" in globals() and "run_society" in globals():
143
  except Exception as e:
144
  print(f"创建临时脚本文件时出错: {e}")
145
  sys.exit(1)
146
-
147
  try:
148
  # 直接执行临时脚本
149
- print(f"开始执行脚本...")
150
-
151
  # 如果有main函数,加载模块并调用main
152
  if has_main:
153
  # 加载临时模块
154
  module_name = f"temp_{script_path.stem}"
155
  module = load_module_from_path(module_name, temp_script_path)
156
-
157
  if module is None:
158
  print(f"错误: 无法加载模块 {module_name}")
159
  sys.exit(1)
160
-
161
  # 确保模块中有question变量,并且值是用户输入的问题
162
  setattr(module, "question", question)
163
-
164
  # 如果模块中有construct_society函数,修补它
165
  if hasattr(module, "construct_society"):
166
  original_func = module.construct_society
 
167
  def patched_func(*args, **kwargs):
168
  return original_func(question)
 
169
  module.construct_society = patched_func
170
  print("已在模块级别修补construct_society函数")
171
-
172
  # 调用main函数
173
  if hasattr(module, "main"):
174
  print("调用main函数...")
@@ -182,34 +214,35 @@ if "construct_society" in globals() and "run_society" in globals():
182
  # 使用更安全的方式执行脚本
183
  with open(temp_script_path, "r", encoding="utf-8") as f:
184
  script_code = f.read()
185
-
186
  # 创建一个安全的全局命名空间
187
  safe_globals = {
188
  "__file__": str(temp_script_path),
189
- "__name__": "__main__"
190
  }
191
  # 添加内置函数
192
- safe_globals.update({k: v for k, v in globals().items()
193
- if k in ['__builtins__']})
194
-
 
195
  # 执行脚本
196
  exec(script_code, safe_globals)
197
-
198
  except Exception as e:
199
  print(f"执行脚本时出错: {e}")
200
  traceback.print_exc()
201
  sys.exit(1)
202
-
203
  except Exception as e:
204
  print(f"处理脚本时出错: {e}")
205
  traceback.print_exc()
206
  sys.exit(1)
207
-
208
  except Exception as e:
209
  print(f"处理脚本时出错: {e}")
210
  traceback.print_exc()
211
  sys.exit(1)
212
-
213
  finally:
214
  # 删除临时文件
215
  if temp_script_path.exists():
@@ -219,11 +252,12 @@ if "construct_society" in globals() and "run_society" in globals():
219
  except Exception as e:
220
  print(f"删除临时脚本文件时出错: {e}")
221
 
 
222
  if __name__ == "__main__":
223
  # 检查命令行参数
224
  if len(sys.argv) < 2:
225
  print("用法: python script_adapter.py <script_path>")
226
  sys.exit(1)
227
-
228
  # 运行指定的脚本
229
- run_script_with_env_question(sys.argv[1])
 
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
  import os
15
  import sys
16
  import importlib.util
 
18
  from pathlib import Path
19
  import traceback
20
 
21
+
22
  def load_module_from_path(module_name, file_path):
23
  """从文件路径加载Python模块"""
24
  try:
 
26
  if spec is None:
27
  print(f"错误: 无法从 {file_path} 创建模块规范")
28
  return None
29
+
30
  module = importlib.util.module_from_spec(spec)
31
  sys.modules[module_name] = module
32
  spec.loader.exec_module(module)
 
36
  traceback.print_exc()
37
  return None
38
 
39
+
40
  def run_script_with_env_question(script_name):
41
  """使用环境变量中的问题运行脚本"""
42
  # 获取环境变量中的问题
 
44
  if not question:
45
  print("错误: 未设置OWL_QUESTION环境变量")
46
  sys.exit(1)
47
+
48
  # 脚本路径
49
  script_path = Path(script_name).resolve()
50
  if not script_path.exists():
51
  print(f"错误: 脚本 {script_path} 不存在")
52
  sys.exit(1)
53
+
54
  # 创建临时文件路径
55
  temp_script_path = script_path.with_name(f"temp_{script_path.name}")
56
+
57
  try:
58
  # 读取脚本内容
59
  try:
 
62
  except Exception as e:
63
  print(f"读取脚本文件时出错: {e}")
64
  sys.exit(1)
65
+
66
  # 检查脚本是否有main函数
67
+ has_main = re.search(r"def\s+main\s*\(\s*\)\s*:", content) is not None
68
+
69
  # 转义问题中的特殊字符
70
+ escaped_question = (
71
+ question.replace("\\", "\\\\").replace('"', '\\"').replace("'", "\\'")
72
+ )
73
+
74
  # 查找脚本中所有的question赋值 - 改进的正则表达式
75
  # 匹配单行和多行字符串赋值
76
+ question_assignments = re.findall(
77
+ r'question\s*=\s*(?:["\'].*?["\']|""".*?"""|\'\'\'.*?\'\'\'|\(.*?\))',
78
+ content,
79
+ re.DOTALL,
80
+ )
81
  print(f"在脚本中找到 {len(question_assignments)} 个question赋值")
82
+
83
  # 修改脚本内容,替换所有的question赋值
84
  modified_content = content
85
+
86
  # 如果脚本中有question赋值,替换所有的赋值
87
  if question_assignments:
88
  for assignment in question_assignments:
89
  modified_content = modified_content.replace(
90
+ assignment, f'question = "{escaped_question}"'
 
91
  )
92
  print(f"已替换脚本中的所有question赋值为: {question}")
93
  else:
94
  # 如果没有找到question赋值,尝试在main函数前插入
95
  if has_main:
96
+ main_match = re.search(r"def\s+main\s*\(\s*\)\s*:", content)
97
  if main_match:
98
  insert_pos = main_match.start()
99
+ modified_content = (
100
+ content[:insert_pos]
101
+ + f'\n# 用户输入的问题\nquestion = "{escaped_question}"\n\n'
102
+ + content[insert_pos:]
103
+ )
104
  print(f"已在main函数前插入问题: {question}")
105
  else:
106
  # 如果没有main函数,在文件开头插入
107
+ modified_content = (
108
+ f'# 用户输入的问题\nquestion = "{escaped_question}"\n\n' + content
109
+ )
110
  print(f"已在文件开头插入问题: {question}")
111
+
112
  # 添加monkey patch代码,确保construct_society函数使用用户的问题
113
+ monkey_patch_code = f"""
114
  # 确保construct_society函数使用用户的问题
115
  original_construct_society = globals().get('construct_society')
116
  if original_construct_society:
 
121
  # 替换原始函数
122
  globals()['construct_society'] = patched_construct_society
123
  print("已修补construct_society函数,确保使用用户问题")
124
+ """
125
+
126
  # 在文件末尾添加monkey patch代码
127
  modified_content += monkey_patch_code
128
+
129
  # 如果脚本没有调用main函数,添加调用代码
130
  if has_main and "__main__" not in content:
131
+ modified_content += """
132
 
133
  # 确保调用main函数
134
  if __name__ == "__main__":
135
  main()
136
+ """
137
  print("已添加main函数调用代码")
138
+
139
  # 如果脚本没有construct_society调用,添加调用代码
140
+ if (
141
+ "construct_society" in content
142
+ and "run_society" in content
143
+ and "Answer:" not in content
144
+ ):
145
+ modified_content += f"""
146
 
147
  # 确保执行construct_society和run_society
148
  if "construct_society" in globals() and "run_society" in globals():
 
155
  print(f"运行时出错: {{e}}")
156
  import traceback
157
  traceback.print_exc()
158
+ """
159
  print("已添加construct_society和run_society调用代码")
160
+
161
  # 执行修改后的脚本
162
  try:
163
  # 将脚本目录添加到sys.path
164
  script_dir = script_path.parent
165
  if str(script_dir) not in sys.path:
166
  sys.path.insert(0, str(script_dir))
167
+
168
  # 创建临时文件
169
  try:
170
  with open(temp_script_path, "w", encoding="utf-8") as f:
 
173
  except Exception as e:
174
  print(f"创建临时脚本文件时出错: {e}")
175
  sys.exit(1)
176
+
177
  try:
178
  # 直接执行临时脚本
179
+ print("开始执行脚本...")
180
+
181
  # 如果有main函数,加载模块并调用main
182
  if has_main:
183
  # 加载临时模块
184
  module_name = f"temp_{script_path.stem}"
185
  module = load_module_from_path(module_name, temp_script_path)
186
+
187
  if module is None:
188
  print(f"错误: 无法加载模块 {module_name}")
189
  sys.exit(1)
190
+
191
  # 确保模块中有question变量,并且值是用户输入的问题
192
  setattr(module, "question", question)
193
+
194
  # 如果模块中有construct_society函数,修补它
195
  if hasattr(module, "construct_society"):
196
  original_func = module.construct_society
197
+
198
  def patched_func(*args, **kwargs):
199
  return original_func(question)
200
+
201
  module.construct_society = patched_func
202
  print("已在模块级别修补construct_society函数")
203
+
204
  # 调用main函数
205
  if hasattr(module, "main"):
206
  print("调用main函数...")
 
214
  # 使用更安全的方式执行脚本
215
  with open(temp_script_path, "r", encoding="utf-8") as f:
216
  script_code = f.read()
217
+
218
  # 创建一个安全的全局命名空间
219
  safe_globals = {
220
  "__file__": str(temp_script_path),
221
+ "__name__": "__main__",
222
  }
223
  # 添加内置函数
224
+ safe_globals.update(
225
+ {k: v for k, v in globals().items() if k in ["__builtins__"]}
226
+ )
227
+
228
  # 执行脚本
229
  exec(script_code, safe_globals)
230
+
231
  except Exception as e:
232
  print(f"执行脚本时出错: {e}")
233
  traceback.print_exc()
234
  sys.exit(1)
235
+
236
  except Exception as e:
237
  print(f"处理脚本时出错: {e}")
238
  traceback.print_exc()
239
  sys.exit(1)
240
+
241
  except Exception as e:
242
  print(f"处理脚本时出错: {e}")
243
  traceback.print_exc()
244
  sys.exit(1)
245
+
246
  finally:
247
  # 删除临时文件
248
  if temp_script_path.exists():
 
252
  except Exception as e:
253
  print(f"删除临时脚本文件时出错: {e}")
254
 
255
+
256
  if __name__ == "__main__":
257
  # 检查命令行参数
258
  if len(sys.argv) < 2:
259
  print("用法: python script_adapter.py <script_path>")
260
  sys.exit(1)
261
+
262
  # 运行指定的脚本
263
+ run_script_with_env_question(sys.argv[1])
owl/utils/document_toolkit.py CHANGED
@@ -17,6 +17,7 @@ from camel.toolkits.function_tool import FunctionTool
17
  from camel.toolkits import ImageAnalysisToolkit, ExcelToolkit
18
  from camel.utils import retry_on_error
19
  from camel.logger import get_logger
 
20
  from docx2markdown._docx_to_markdown import docx_to_markdown
21
  from chunkr_ai import Chunkr
22
  import requests
@@ -40,8 +41,10 @@ class DocumentProcessingToolkit(BaseToolkit):
40
  This class provides method for processing docx, pdf, pptx, etc. It cannot process excel files.
41
  """
42
 
43
- def __init__(self, cache_dir: Optional[str] = None):
44
- self.image_tool = ImageAnalysisToolkit()
 
 
45
  # self.audio_tool = AudioAnalysisToolkit()
46
  self.excel_tool = ExcelToolkit()
47
 
 
17
  from camel.toolkits import ImageAnalysisToolkit, ExcelToolkit
18
  from camel.utils import retry_on_error
19
  from camel.logger import get_logger
20
+ from camel.models import BaseModelBackend
21
  from docx2markdown._docx_to_markdown import docx_to_markdown
22
  from chunkr_ai import Chunkr
23
  import requests
 
41
  This class provides method for processing docx, pdf, pptx, etc. It cannot process excel files.
42
  """
43
 
44
+ def __init__(
45
+ self, cache_dir: Optional[str] = None, model: Optional[BaseModelBackend] = None
46
+ ):
47
+ self.image_tool = ImageAnalysisToolkit(model=model)
48
  # self.audio_tool = AudioAnalysisToolkit()
49
  self.excel_tool = ExcelToolkit()
50
 
run_app.py CHANGED
@@ -1,3 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  #!/usr/bin/env python
2
  # -*- coding: utf-8 -*-
3
 
@@ -9,26 +22,27 @@ import os
9
  import sys
10
  from pathlib import Path
11
 
 
12
  def main():
13
  """主函数,启动OWL智能助手运行平台"""
14
  # 确保当前目录是项目根目录
15
  project_root = Path(__file__).resolve().parent
16
  os.chdir(project_root)
17
-
18
  # 创建日志目录
19
  log_dir = project_root / "logs"
20
  log_dir.mkdir(exist_ok=True)
21
-
22
  # 导入并运行应用
23
  sys.path.insert(0, str(project_root))
24
-
25
  try:
26
  from owl.app import create_ui
27
-
28
  # 创建并启动应用
29
  app = create_ui()
30
  app.queue().launch(share=False)
31
-
32
  except ImportError as e:
33
  print(f"错误: 无法导入必要的模块。请确保已安装所有依赖项: {e}")
34
  print("提示: 运行 'pip install -r requirements.txt' 安装所有依赖项")
@@ -36,8 +50,10 @@ def main():
36
  except Exception as e:
37
  print(f"启动应用程序时出错: {e}")
38
  import traceback
 
39
  traceback.print_exc()
40
  sys.exit(1)
41
 
 
42
  if __name__ == "__main__":
43
- main()
 
1
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+ # ========= Copyright 2023-2024 @ CAMEL-AI.org. All Rights Reserved. =========
14
  #!/usr/bin/env python
15
  # -*- coding: utf-8 -*-
16
 
 
22
  import sys
23
  from pathlib import Path
24
 
25
+
26
  def main():
27
  """主函数,启动OWL智能助手运行平台"""
28
  # 确保当前目录是项目根目录
29
  project_root = Path(__file__).resolve().parent
30
  os.chdir(project_root)
31
+
32
  # 创建日志目录
33
  log_dir = project_root / "logs"
34
  log_dir.mkdir(exist_ok=True)
35
+
36
  # 导入并运行应用
37
  sys.path.insert(0, str(project_root))
38
+
39
  try:
40
  from owl.app import create_ui
41
+
42
  # 创建并启动应用
43
  app = create_ui()
44
  app.queue().launch(share=False)
45
+
46
  except ImportError as e:
47
  print(f"错误: 无法导入必要的模块。请确保已安装所有依赖项: {e}")
48
  print("提示: 运行 'pip install -r requirements.txt' 安装所有依赖项")
 
50
  except Exception as e:
51
  print(f"启动应用程序时出错: {e}")
52
  import traceback
53
+
54
  traceback.print_exc()
55
  sys.exit(1)
56
 
57
+
58
  if __name__ == "__main__":
59
+ main()