Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| """ | |
| 扫描 modules/chart_engine/template/d3-js 下的所有 JS 文件, | |
| 使用 LLM 处理并输出到 d3-js-new 目录下的同名目录 | |
| """ | |
| import os | |
| import requests | |
| import json | |
| from pathlib import Path | |
| import time | |
| import concurrent.futures | |
| # OpenAI API configuration | |
| API_KEY = os.getenv("OPENAI_API_KEY") or os.getenv("AIHUBMIX_API_KEY", "") | |
| API_PROVIDER = os.getenv("OPENAI_BASE_URL", "https://aihubmix.com") | |
| def query_openai(prompt: str, code_content: str) -> str: | |
| """ | |
| 调用 OpenAI API 处理代码 | |
| Args: | |
| prompt: 提示词 | |
| code_content: 需要处理的代码内容 | |
| Returns: | |
| str: OpenAI 的响应结果,如果出错则返回 None | |
| """ | |
| headers = { | |
| 'Authorization': f'Bearer {API_KEY}', | |
| 'Content-Type': 'application/json' | |
| } | |
| data = { | |
| 'model': 'gemini-2.5-pro-preview-05-06', | |
| 'messages': [ | |
| {'role': 'system', 'content': prompt}, | |
| {'role': 'user', 'content': f'Please refactor the following JavaScript code:\n\n{code_content}'} | |
| ], | |
| 'temperature': 0.3, | |
| 'max_tokens': 30000 | |
| } | |
| try: | |
| response = requests.post(f'{API_PROVIDER}/v1/chat/completions', headers=headers, json=data) | |
| response.raise_for_status() | |
| content = response.json()['choices'][0]['message']['content'].strip() | |
| # 删除所有代码块标记 | |
| content = content.replace('```json', '') | |
| content = content.replace('```javascript', '') | |
| content = content.replace('```', '') | |
| content = content.strip() | |
| return content | |
| except Exception as e: | |
| print(f"调用 OpenAI API 出错: {e}") | |
| return None | |
| def load_prompt(): | |
| """加载转换提示词""" | |
| prompt_file = Path('scripts/convert_code_prompt.txt') | |
| if prompt_file.exists(): | |
| with open(prompt_file, 'r', encoding='utf-8') as f: | |
| return f.read() | |
| else: | |
| print(f"警告:找不到提示词文件 {prompt_file}") | |
| return "" | |
| def find_js_files(base_dir): | |
| """递归查找所有 JS 文件""" | |
| js_files = [] | |
| base_path = Path(base_dir) | |
| for root, dirs, files in os.walk(base_path): | |
| for file in files: | |
| if file.endswith('.js'): | |
| file_path = Path(root) / file | |
| relative_path = file_path.relative_to(base_path) | |
| js_files.append({ | |
| 'full_path': file_path, | |
| 'relative_path': relative_path, | |
| 'dir_name': relative_path.parent, | |
| 'file_name': file | |
| }) | |
| return js_files | |
| def process_js_file(file_info, prompt, output_base_dir): | |
| """处理单个 JS 文件""" | |
| print(f"正在处理: {file_info['relative_path']}") | |
| # 读取原始文件 | |
| try: | |
| with open(file_info['full_path'], 'r', encoding='utf-8') as f: | |
| original_code = f.read() | |
| except Exception as e: | |
| print(f"读取文件失败 {file_info['full_path']}: {e}") | |
| return False | |
| # 检查文件大小,如果超过80000个字符 (约20000 tokens),则跳过 | |
| if len(original_code) > 80000: | |
| print(f"文件过大,跳过: {file_info['relative_path']} (大小: {len(original_code)} 字符)") | |
| return False | |
| # 调用 LLM 处理 | |
| processed_code = query_openai(prompt, original_code) | |
| if processed_code is None: | |
| print(f"LLM 处理失败: {file_info['relative_path']}") | |
| return False | |
| # 创建输出目录 | |
| output_dir = Path(output_base_dir) / file_info['dir_name'] | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| # 写入处理后的文件 | |
| output_file = output_dir / file_info['file_name'] | |
| try: | |
| with open(output_file, 'w', encoding='utf-8') as f: | |
| f.write(processed_code) | |
| print(f"成功输出: {output_file}") | |
| return True | |
| except Exception as e: | |
| print(f"写入文件失败 {output_file}: {e}") | |
| return False | |
| def main(): | |
| """主函数""" | |
| # 配置路径 | |
| source_dir = 'modules/chart_engine/template/d3-js' | |
| output_dir = 'modules/chart_engine/template/d3-js-new' | |
| # 检查源目录是否存在 | |
| if not Path(source_dir).exists(): | |
| print(f"错误:源目录不存在 {source_dir}") | |
| return | |
| # 加载提示词 | |
| prompt = load_prompt() | |
| if not prompt: | |
| print("错误:无法加载提示词") | |
| return | |
| # 查找所有 JS 文件 | |
| print(f"扫描目录: {source_dir}") | |
| js_files = find_js_files(source_dir) | |
| print(f"找到 {len(js_files)} 个 JS 文件") | |
| # 创建输出基础目录 | |
| Path(output_dir).mkdir(parents=True, exist_ok=True) | |
| # 处理每个文件 | |
| success_count = 0 | |
| total_count = len(js_files) | |
| with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor: | |
| future_to_file = {executor.submit(process_js_file, file_info, prompt, output_dir): file_info for file_info in js_files} | |
| for i, future in enumerate(concurrent.futures.as_completed(future_to_file), 1): | |
| file_info = future_to_file[future] | |
| print(f"\n进度: {i}/{total_count}") | |
| try: | |
| if future.result(): | |
| success_count += 1 | |
| except Exception as exc: | |
| print(f"{file_info['relative_path']} 生成时发生错误: {exc}") | |
| # 添加延迟避免 API 限制 (如果需要,可以在 process_js_file 内部或此处根据API策略调整) | |
| # time.sleep(0.1) # 调整或移除此处的延时,因为并发处理时,单个线程内的延时可能已足够 | |
| print(f"\n处理完成!") | |
| print(f"成功处理: {success_count}/{total_count} 个文件") | |
| print(f"输出目录: {output_dir}") | |
| if __name__ == "__main__": | |
| main() | |