首先放上项目地址:
GitHub - YANG-Haruka/AI-Office-Translator

思路:

1. 解析Office文件 将内容导出到本地json
2. 利用大模型应用提供的api对内容进行翻译
3. 将翻译结果与原文件进行对齐,再将结果重新写入文件
4. 导出为翻译后的新文件。

有了思路之后我们直接开搞。

一:解析Office文件

目前有多种方式解析,比如解析word文件,可以考虑使用python的docx库进行。
但是在解析excel和ppt文件时会遇见不少问题。
有没有一个更加通用的办法呢?
答案是有:

考虑到Office文件的底层格式实际上是基于XML的,因此我们可以直接解压Office文件并解析其中的XML文件,来实现对Word、Excel和PPT等文件的通用解析。具体来说:

Office文件的结构

Office文件(如.docx.xlsx.pptx)本质上是基于OpenXML标准的ZIP压缩包,解压后可以看到多个XML文件及相关资源文件(如图片等)。这些XML文件描述了文档的结构、内容和样式等信息。

解析方法

解压文件

可以使用Python的zipfile模块解压Office文件。

解析XML

解压后的文件夹中包含了大量XML文件,可以使用Python的xml.etree.ElementTreelxmlBeautifulSoup库对其进行解析。

针对不同文件的关键XML

Word(.docx:主要内容在word/document.xml中,样式信息在word/styles.xml中。

Excel(.xlsx:工作表内容在xl/worksheets/sheet1.xml等文件中,数据表关系在xl/sharedStrings.xml中。

PPT(.pptx:幻灯片内容在ppt/slides/slide1.xml等文件中。

优点

通用性强:对所有Office文件类型都适用。

灵活性高:可以精确提取文件中的任何内容,而不仅仅是通过库提供的接口。

示例代码

以下是解析.docx文件的简单示例:

import zipfile
import xml.etree.ElementTree as ET

# 解压docx文件
def extract_docx_content(file_path):
    with zipfile.ZipFile(file_path, 'r') as docx_file:
        # 解压的文件列表
        file_list = docx_file.namelist()
        # 读取主内容文件
        if 'word/document.xml' in file_list:
            content = docx_file.read('word/document.xml')
            # 解析XML内容
            root = ET.fromstring(content)
            # 提取所有文本
            namespaces = {'w': 'http://schemas.openxmlformats.org/wordprocessingml/2006/main'}
            texts = [node.text for node in root.findall('.//w:t', namespaces) if node.text]
            return ''.join(texts)
    return None

# 使用示例
docx_path = 'example.docx'
content = extract_docx_content(docx_path)
print(content)


二:大模型翻译

目前有多种本地调用大模型的插件,比如Ollama,LM Studio等,此处使用Ollama进行介绍。

ollama pull qwen2.5

目前发现使用Qwen系列模型对于翻译的结果较好。使用其他模型比如Llama3.2时,会经常出现错乱的情况,所以这里推荐使用Qwen系列的模型。
模型下载完成后可以通过该命令验证,他会显示你下载好的模型。

ollama list

C:\Users\Administrator>ollama list
NAME                    ID              SIZE      MODIFIED
qwen2.5:latest          845dbda0ea48    4.7 GB    6 hours ago
qwen2.5-coder:14b       3028237cc8c5    9.0 GB    5 days ago
qwen2.5-coder:32b       4bd6cbf2d094    19 GB     5 days ago
llama3.1:8b             42182419e950    4.7 GB    4 weeks ago
qwen2.5:32b             9f13ba1299af    19 GB     4 weeks ago
mistral-small:latest    d095cd553b04    12 GB     4 weeks ago
gemma2:27b              53261bc9c192    15 GB     4 weeks ago

这里是一个在python中简单调用ollama的示例代码

import requests

def call_ollama(prompt, model="qwen2.5", base_url="http://localhost:11434"):
    """
    调用 Ollama 模型的函数

    :param prompt: 提示文本
    :param model: 模型名称,默认为 qwen2.5
    :param base_url: Ollama API 的基础 URL,默认为本地运行的端口
    :return: 模型的返回结果
    """
    url = f"{base_url}/api/chat"
    headers = {"Content-Type": "application/json"}
    payload = {
        "model": model,
        "messages": [{"role": "user", "content": prompt}],
    }

    response = requests.post(url, json=payload, headers=headers)
    if response.status_code == 200:
        return response.json()["reply"]
    else:
        raise Exception(f"Error {response.status_code}: {response.text}")

# 示例调用
if __name__ == "__main__":
    prompt = "What is the capital of France?"
    try:
        response = call_ollama(prompt)
        print("Response from Qwen-2.5:")
        print(response)
    except Exception as e:
        print(f"Error: {e}")

参数说明

prompt:用户输入的文本,用于提供给模型生成响应。

model:要调用的模型名称,例如 qwen2.5

base_url:本地运行的 Ollama 服务地址。如果服务运行在远程服务器,请修改为对应的 URL。

返回结果

代码会返回模型的生成内容。如果需要更复杂的对话(如上下文处理或系统角色设定),可以在 messages 参数中添加更多消息内容,例如:

payload = {
    "model": "qwen2.5",
    "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Tell me about AI."}
    ],
}

至于更多的设置,比如大模型的参数(max_tokens等)请参考ollama官方文档。

Prompt的设置,我这里放一个简单的例子,用于将文件翻译为中文:
各个参数的意义请学习大模型的基础知识。
 

{
    "system_prompt": "你是一位真正擅长{Text_Target_Language}和{Text_Source_Language}文化的本地化专家,你需要将{Text_Source_Language}文本翻译成{Text_Target_Language}。严格按照以下要求完成翻译:\n1. 不要添加任何多余的内容,例如开场白、总结、解释等。\n2. 按照逐行翻译,每行单独翻译对应的行,保持格式一致。\n3. 保留原文中的特殊符号、转义字符、格式化代码、换行符、回车符等。\n### 原文文本格式如下 ###\n{{\"<文本id>\":\"<原文文本>\"}}\n### 以json格式输出译文 ###\n{{\"<文本id>\":\"<已翻译文本>\"}}\n仅输出上述 JSON 格式内容,无需任何额外内容。",
    "user_prompt": "这是你接下来的翻译任务,请仅翻译以下文本,直接按照 JSON 格式输出结果,无需任何额外说明或解释:",
    "previous_prompt": "这是上一段的上下文内容,请按照以下格式输出翻译结果:",
    "previous_text_default": {
        "0": "你好",
        "1": "这里是一个自动翻译系统",
        "2": "我会自己翻译"
    }
}


三:将翻译结果与源文件对齐

1. 文本分隔

由于模型输入长度的限制,我们无法将所有需要翻译的文本一次性输入到模型中进行处理。然而,如果将文本过于细化,一次只输入一两段短文本,模型可能无法建立足够的上下文,从而导致翻译精度显著下降。这种情况下,翻译的连贯性和一致性都会受到影响,尤其是在处理需要上下文理解的内容时。

为了解决这一问题,我们需要采用一种高效的方法:对于过短的文本,可以将其合理拼接成较长的段落,从而在模型输入中提供更完整的上下文信息;而对于超长的文本,则需要将其适当分隔成模型可以接受的长度,同时在分段之间保留关键的上下文线索,以确保翻译结果的连贯性。

这种方法既可以充分利用模型的上下文处理能力,又能够避免因输入长度超出限制而导致的截断问题,从而在短文本和长文本场景中都能获得更高质量的翻译效果。这种分段与拼接的策略在实践中非常重要,尤其是在处理具有多层次语义的复杂文档时,可以显著提高翻译的流畅性和准确性。

具体的实现方法请参考

AI-Office-Translator/textProcessing/text_separator.py at main · YANG-Haruka/AI-Office-Translator · GitHub
 

2. 文本对齐
 

对齐的方式其实非常简单,我们只需要在提取文字的时候,在提取每个位置的文字时,增加编号,比如这是我的生成方式:

[
    {
        "count": 1,
        "slide_index": 1,
        "text_node_index": 1,
        "type": "text",
        "value": "company growth"
    },
    {
        "count": 2,
        "slide_index": 1,
        "text_node_index": 2,
        "type": "text",
        "value": "MOVING UP"
    },

将数据输入给模型,模型会按照顺序将结果返回,最终只需要将编号对齐,将内容依次替换即可。


四:保存文件

同样,利用python中的处理xml文件的库,替换文字后将文件重新压缩并转换为对应的Office文件格式即可,这里也不再赘述。


总结

综上,一个简单的快速使用本地大模型翻译Office文件的应用就完成了,至于App的显示,由于笔者能力有限,暂时使用gradio库做了一个简单的界面,之后如果有精力也会拓展使用Pyqt6等。

这种利用本地大模型实现功能的思路还有很多,比如基于Whisper语音识别,大模型总结就可以打造一个视频总结工具。之后如果有时间我会将这部分的实现也分享给大家。
 

Logo

ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!

更多推荐