Spaces:
Sleeping
Sleeping
File size: 5,889 Bytes
58e6885 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #!/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()
|