admin 管理员组

文章数量: 1184232

之前出于对英汉词典的需求,利用python代码实现了将mdict词典文件解析并保存为csv格式的文件,详见gitcode项目:GitCode - 全球开发者的开源社区,开源代码托管平台GitCode是面向全球开发者的开源社区,包括原创博客,开源代码托管,代码协作,项目管理等。与开发者社区互动,提升您的研发效率和质量。https://gitcode/ffffiii/mdict2csv/tree/main

后来需求增加:thesaurus词典包含24万词条,但只包含英文释义与同义词项,缺乏中文释义。于是,通过与其他词典的对接,成功地补充了数万条中文释义,剩20万词条须要补充中文释义。可是,该如何实现呢?

免费在线渠道似乎都无法很好地应对如此庞大的请求,于是我转向ollama部署的本地AI模型。为了追求效率,选择了gemma3:4b这样的小模型。

下面记录一下重要步骤与关键逻辑:

1)thes词典除了同义词与反义词,其实也可以当作一本英英词典(见下图),所以这次的目标就是将这些英文释义归纳转化为中文释义

2)提示词询问AI模型

import ollama

response = ollama.chat(
            model=model_name,
            messages=[
                {"role": "system",
                 "content": "你是一个专业的翻译助手,能充分理解英文原文,准确地归纳出中文释义,且将重复冗余的释义项高度凝练,返回结果中不包含英文,仅提供中文释义"},
                {"role": "user",
                 "content": f"请为以下英文归纳出对应的中文释义,要求返回的结果简明扼要,20字以内,不得出现英文原文加冒号再接中文释义的情况,不得出现‘以下是对应中文释义:’这样的引导语,不得出现*符号,不得出现韩文以及中文以外的任何语言,直接提供最终中文释义即可:\n{text}"}
            ],
            stream=False
        )

3) 核心逻辑就是遍历 源词典数据,依次对每一行的特定列进行翻译(按上面的提示词询问AI并获取中文释义)

4)运行情况:

5)以下是详细代码:

# -*- coding: utf-8 -*-
import pandas as pd
import ollama
import time
import re
from tqdm import tqdm  # 进度条显示
import datetime

def remove_think_tags(text):
    """移除文本中的<think>和</think>标签及其内容"""
    # 使用正则表达式匹配并删除标签及其内容
    # <think>.*?</think> 匹配非贪婪模式的标签内容
    cleaned_text = re.sub(r'<think>.*?</think>', '', text, flags=re.DOTALL)
    return cleaned_text.strip()

def translate_text(text, model_name='llama2'):
    """使用Ollama库的chat方法翻译文本"""
    try:
        # 构建聊天消息
        response = ollama.chat(
            model=model_name,
            messages=[
                {"role": "system",
                 "content": "你是一个专业的翻译助手,能充分理解英文原文,准确地归纳出中文释义,且将重复冗余的释义项高度凝练,返回结果中不包含英文,仅提供中文释义"},
                {"role": "user",
                 "content": f"请为以下英文归纳出对应的中文释义,要求返回的结果简明扼要,20字以内,不得出现英文原文加冒号再接中文释义的情况,不得出现‘以下是对应中文释义:’这样的引导语,不得出现*符号,不得出现韩文以及中文以外的任何语言,直接提供最终中文释义即可:\n{text}"}
            ],
            stream=False
        )

        # 提取翻译结果
        translated_text = response['message']['content'].strip()

        # 移除可能的前缀
        if translated_text.startswith('中文:'):
            translated_text = translated_text[3:].strip()
        elif translated_text.startswith('翻译:'):
            translated_text = translated_text[3:].strip()
        # 移除思考标签
        translated_text = '~'+remove_think_tags(translated_text)

        return translated_text

    except Exception as e:
        print(f"翻译出错: {e}")
        return text

def translate_csv(input_file, output_file, model_name='llama2', item_column='item', definition_column='definition',max_rows=None):
    """读取CSV文件并使用Ollama模型翻译指定列,只翻译definition列为空的行"""
    # 读取CSV文件
    try:
        df = pd.read_csv(input_file,encoding='ansi')
    except:
        df = pd.read_csv(input_file,encoding='utf-8')

    # 检查指定列是否存在
    for col in [item_column, definition_column]:
        if col not in df.columns:
            print(f"错误: CSV文件中没有'{col}'列")
            return

    # 计算需要翻译的行数
    rows_to_translate = df[df[definition_column].isna() | (df[definition_column] == '') | (df[definition_column] == 'nan')].shape[0]
    print(f'max_rows:{max_rows}; rows_to_translate:{rows_to_translate}')

    # 应用最大行数限制
    if max_rows is not None and max_rows > 0:
        rows_to_translate = min(rows_to_translate, max_rows)
        print(f"设置了最大翻译行数限制: {max_rows}")

    print(f"总共有 {len(df)} 行数据,其中 {rows_to_translate} 行需要翻译")

    # 翻译每一行(只翻译definition列为空的行)
    translated_count = 0
    total_rows = df[df[definition_column].isna() | (df[definition_column] == '') | (df[definition_column] == 'nan')].shape[0]
    start_time = time.time()

    with tqdm(total=total_rows, desc="翻译进度") as pbar:
        for i, row in df.iterrows():
            item_text = str(row[item_column])
            meaning_text = str(row['meaning'])
            meaning_text = meaning_text.replace('|','; ')
            definition_text = str(row[definition_column])
            #print(f'item_text:{item_text}; meaning_text:{meaning_text}; definition_text:{definition_text}')

            # 只翻译definition列为空的行
            if pd.isna(definition_text) or definition_text.strip() == '' or definition_text.strip() == 'nan':
                if item_text.strip():  # 只翻译非空文本
                    translated_count += 1
                    start_translate_time = time.time()

                    translated_text = translate_text(meaning_text, model_name)
                    translated_text=translated_text.replace('\n', ' ')
                    print(f"\n已翻译第{translated_count}/{rows_to_translate} 行: {item_text},翻译结果: {translated_text}")
                    df.at[i, definition_column] = translated_text

                    # 阶段性保存
                    if translated_count % 100 == 0:
                        print(f"阶段性保存:已保存到 {output_file}")
                        df.to_csv(output_file, index=False, encoding='utf-8-sig')

                    # 检查是否达到最大行数限制
                    if max_rows is not None and translated_count >= max_rows:
                        print(f"已达到最大翻译行数限制 ({max_rows}),停止翻译")
                        break

                    end_translate_time = time.time()
                    elapsed_time = end_translate_time - start_translate_time
                    pbar.set_postfix_str(f"耗时: {elapsed_time:.2f}s")
                    pbar.update(1)

    # 保存翻译后的CSV文件
    df.to_csv(output_file, index=False, encoding='utf-8-sig')
    print(f"翻译完成,已保存到 {output_file}")
    print(f"总共翻译了 {translated_count} 行数据")

    # 计算总耗时
    end_time = time.time()
    total_elapsed_time = end_time - start_time
    print(f"总共耗时: {total_elapsed_time:.2f} 秒")

if __name__ == "__main__":
    # 配置参数
    INPUT_FILE = 'data/dictionary1.csv'  # 输入CSV文件路径
    OUTPUT_FILE = 'data/dictionary1.csv'  # 输出CSV文件路径
    MODEL_NAME = 'gemma3:4b'#'qwen3:0.6b'  # Ollama模型名称
    ITEM_COLUMN = 'word'  # 英文内容列名
    DEFINITION_COLUMN = 'definition'  # 定义列名(翻译结果将放入此列)

    # 执行翻译
    translate_csv(INPUT_FILE, OUTPUT_FILE, MODEL_NAME, ITEM_COLUMN, DEFINITION_COLUMN,  max_rows=3000)

* 将INPUT_FILE和OUTPUT_FILE设为同一个文件路径,这样能保持对原文件进行增补。

 

本文标签: 词条 英文 模型 英汉词典 ollama