使用ai进行技术文档的翻译(目录)
碎碎念那边有说到有二次开发的口头机会,文档基本是英文。之后现在ai应用又挺流行,且ai应用在翻译也是很早一个技能,所以就想着翻译一下需要的文档信息了。(也算是ai辅助学习了吧)
总体思路是这样的:先获取相关的目录,之后根据目录去处理具体的页面,最后连起来可用。
1、获取相关的目录
1.1、获取 ObjectARX and Managed .NET 部分目录
找到了接口传送的json地址:https://help.autodesk.com/view/OARX/2026/CHS/data/toctree.json
数据比较多,直接使用ai先不说长度够不够,对token消耗多不多,仅考虑题目随时可能会发,而且从收到题目到处理交付的时间只有7天,所以我仅需要 ObjectARX and Managed .NET 目录下的东西。
【预处理1:获取子json】
所以我要先遍历这个json之后截取 ObjectARX and Managed .NET 目录及子目录,保存成一个新的子json。关键代码如下:
def find_node_by_value(node, target, depth=0):
"""
通过值查找节点
"""
if isinstance(node, dict):
for key, value in node.items():
indent = " " * depth
if value == target:
print(f"{indent}✅ 找到!返回节点")
return node
# 递归搜索,并接收返回值
result = find_node_by_value(value, target, depth + 1)
if result:
return result # 向上传递
elif isinstance(node, list):
for i, item in enumerate(node):
result = find_node_by_value(item, target, depth + 1)
if result:
return result
return None
本来是想根据 json 拿 ai 自动生成一个静态的可用的网站的,不过后来因为数据太多,我电脑又太老了,所以改变了策略。使用数据库保存信息,之后再用代码正常组装。
【预处理2:遍历子json存入未翻译的目录树】
获取完了子 json,接下来就是遍历他,保留树的结构,把他存进数据库里,方便之后使用。
把子 json 给 ai,让 ai 统计了下这个 json 的 key 和对应的数量(实践发现他的统计会有一些误差,但是还是可以用的),他统计出来主要的 key 为:ttl、id、ln、children、type,从数据来看 id 和 ln 都似乎是地址,不过 ln 会比 id 少点,抽查了几个 id 的也都能访问,所以我决定存的信息包括:ttl、id 还有其目录结构和 ttl 对应的中文翻译。
大概这么一个表,字段有:
id(主键自增id)、
parent_id(对应的父id)、
title(对应 json 的 ttl)、
title_cn(之后要存的对应ttl的中文翻译)、
url(对应 json 的 id,要做一些些处理 ?guid=具体的id,测试角度?key=value是get请求参数)、
level(所属层级)、
sort_order(所属层级的排序)、
created_at(创建时间)
部分参考代码如下:
def escape_sql_string(s):
"""转义SQL字符串"""
if s is None:
return 'NULL'
s = str(s).replace("\\", "\\\\").replace("'", "\\'")
return f"'{s}'"
def traverse_json(node, id_counter, parent_id, depth, sort_order, sql_values):
"""
递归遍历JSON,收集SQL值
"""
if isinstance(node, dict):
# 获取当前节点的ID
current_id = id_counter[0]
id_counter[0] += 1
# 提取节点信息
title = node.get('ttl', '')
url = node.get('id', '')
# 构建SQL值
sql_value = f"({current_id}, {parent_id}, {escape_sql_string(title)}, {escape_sql_string(url)}, {depth}, {sort_order})"
sql_values.append(sql_value)
# 打印进度
print(f"处理: {title[:50]} (ID: {current_id})")
# 处理子节点
if 'children' in node and node['children']:
for i, child in enumerate(node['children']):
traverse_json(
child,
id_counter,
current_id, # 子节点的父ID是当前节点ID
depth + 1,
i + 1,
sql_values
)
elif isinstance(node, list):
for i, item in enumerate(node):
traverse_json(
item,
id_counter,
parent_id,
depth,
i + 1,
sql_values
)
def generate_single_insert_sql(data, table_name='默认表名'):
"""
生成单条INSERT语句(包含所有VALUES)
"""
sql_values = []
id_counter = [1] # ID从1开始
print("开始遍历JSON...")
traverse_json(data, id_counter, 0, 0, 1, sql_values)
if not sql_values:
return ""
print(f"\n共生成 {len(sql_values)} 条记录")
# 构建单条INSERT语句
prefix = f"INSERT INTO `{table_name}` (`id`, `parent_id`, `title`, `url`, `level`, `sort_order`) VALUES \n"
values_part = ",\n".join(sql_values)
return prefix + values_part + ";"
这个代码生成的sql集合的根节点要做额外处理,根目录的父节点要设置为null,也可以在代码里面加个标记判断。
【预处理3:AI翻译title】
作为一个失业的宝子来说几块钱也是钱呀嘤嘤嘤(羡慕有工作的宝子,单位付账哦)……(不推广,但是如果我没工作之前我估计翻译正文要白嫖下……测试的角度解决开发问题?哈哈哈,pai要米,网页不要米……脑子一转无头浏览器UI自动化约等于……)这边预处理是用的api……
因为目录比较多,翻译考虑要不要用流式,结果流式并不能改善上下文长度,最后还是不用流式。这里要注意几个点可能可以节约下token:
1.流式和非流式本身没有太大的区别,计算都是按照中文、英文、符号来算的不是按照返回方式的,当然命中和非命中价格也不一样。(但是,敲重点:流式和非流式取值的部分代码不一样;比如python语言:非流式获取 response.choices[0].message.content ,流式获取 for chunk in response: if chunk.choices[0].delta.content:chunk.choices[0].delta.content 具体可以查下对应的官网api)
2.你发送的和他返回的才是上下文和(也就是说本来比如8K上限,你的关键字提示文案超级详细,精准命中,但是你的提示文案+你的素材已经6K了,那么能输出的只剩2K了;同理要是你的你的提示文案+你的素材是4k,那么能输出的就还有4K),了解这个会关系到你分几次去请求,避免结果被截断。所以可以人为的先做预处理节约你的提示文案和素材,当然富裕的可以先不考虑。
3.要是你要上下文关联需要反哺历史给ai,这样似乎又增加了本不富裕的提示文案+素材,还好我的仅翻译就行,不过为了不截断请求,所以需要合适的分批,因为计算价格的方式就决定了,多次分批会增加的成本是请求部分的内容,所以就决定了素材也要对应的切分。
我采用了分批查询数据库,且为了更好的压缩素材,我把查询结果转换成字典(字典的id作为key,title作为value),我要求返回翻译的时候把原来id对应的值替换成翻译的结果,并且也要求返回的时候用紧凑模式。
部分参考代码如下:
def query_to_json(start_id, end_id):
"""执行查询并返回数据列表"""
conn = None
try:
conn = pymysql.connect(**DB_CONFIG)
with conn.cursor(pymysql.cursors.DictCursor) as cursor:
sql = f"SELECT id, title FROM document_tree WHERE id >= {start_id} AND id < {end_id}"
# 要是id有规律就用上面的,没有可用的序号标记就用limit和offset
# sql = f"SELECT id, title FROM document_tree where title_cn is null limit {start_id} , {end_id}"
print('--' * 20)
print(sql)
print('--' * 20)
cursor.execute(sql)
results = cursor.fetchall()
return results
except Exception as e:
print(f"查询失败 [{start_id}, {end_id}): {e}")
return []
finally:
if conn:
conn.close()
def generate_new_sql(dict_str: str, batch_num: int, output_file: str) -> bool:
# 根据传入的字典翻译
print(f"正在流式生成新的字典 (批次 {batch_num})...")
print(dict_str)
user_prompt = f"""请将以下字典的value翻译成中文,翻译的内容覆盖,保持紧凑。要求:直接输出紧凑格式的字典,不要添加任何注释或说明,原始字典信息:{dict_str}"""
try:
response = client.chat.completions.create(
model="deepseek-chat",
messages=[
{"role": "system", "content": "你是CAD C#二次开发专家,擅长中英文翻译。"},
{"role": "user", "content": user_prompt}
],
stream=False
)
content = response.choices[0].message.content
print(content)
data = json.loads(content)
with open(output_file, 'a', encoding='utf-8') as f:
# 考虑sql要直接运行,所以直接用sql的注释来写批次
f.write(f"\n-- ========== Batch {batch_num} ==========\n")
# 直接遍历字典生成更新的sql
for key, value in data.items():
sql = f"UPDATE document_tree SET title_cn = '{value.replace("'", "''")}' WHERE id = {key};\n"
print(sql)
f.write(sql)
print(f" 批次 {batch_num} 完成")
return True
except Exception as e:
print(f" AI调用失败: {e}")
return False
if __name__ == "__main__":
x = 150
y = 16
total_queried = 0
skipped_batches = 0
output_file = r"D:\CAD学习准备\cadBook\new_更新翻译sql1.txt"
print("开始处理...")
print(f"总数据量预估: {x * y} 条")
print("=" * 60)
for i in range(y):
start_id = x * i
end_id = x * (i + 1)
print(f"\n批次 {i + 1}/{y}: 查询ID范围 [{start_id}, {end_id})")
json_result, results = query_to_json(start_id, end_id)
# json_result, results = query_to_json(start_id, x)
# print("=" * 60)
# print(f"offset:{start_id},limit:{x}")
# print("=" * 60)
if not results:
print(f" 批次 {i + 1} 无数据,跳过")
skipped_batches += 1
continue
total_queried += len(results)
print(f" 查询到 {len(results)} 条记录")
# results 是数组,直接转字典
result_dict = {item["id"]: item["title"] for item in results}
# 紧凑格式输出
# ensure_ascii=False 允许输出非 ASCII 字符(如中文),不转义为 \uXXXX
# separators=(',', ':') 使用逗号和冒号作为分隔符,移除多余空格,使输出紧凑
# 压缩成最小字符串发给AI
compressed = json.dumps(result_dict, ensure_ascii=False, separators=(',', ':'))
# 调用AI
ok = generate_new_sql(compressed, i + 1, output_file)
if ok:
print(f" 批次 {i + 1} 处理成功")
else:
print(f" 批次 {i + 1} 处理失败")
print("\n" + "=" * 60)
print("处理完成!")
print(f" 查询总记录数: {total_queried}")
运行生成的更新sql,至此目录的数据都已经准备好了。可以使用sql直接用,也可以好看点加上后端请求前端渲染展示。
嘛补个数据库成果图:

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)