Python调用百度智能云API实现文本纠错

Python调用百度智能云API实现文本纠错

1. 作者介绍

易增平,男,西安工程大学电子信息学院,2025级研究生

研究方向:近红外光谱法鉴别纤维

电子邮件:1742154276@qq.com

董柯帆,男,西安工程大学电子信息学院,2025级研究生,张宏伟人工智能课题组

研究方向:机器视觉与人工智能

电子邮件:867068473@qq.com

2. 百度智能云平台与文本纠错技术介绍

2.1 百度智能云AI服务平台概述

百度智能云是百度面向企业与开发者打造的云智一体 AI 服务平台 。该平台依托全栈自研的算力底座与文心大模型核心技术,提供一站式模型开发、服务部署与 API 开放能力。平台广泛支持文本处理、自然语言理解、多模态交互、智能分析以及本实验所核心使用的文本纠错等多元 AI 能力。其具备服务稳定、接口标准、接入简单、按量计费、安全可控等显著优势,可快速集成到各类业务系统中,全面满足开发、测试与产业落地的全流程需求。

2.2 文本纠错技术接口说明

本实验主要调用百度智能云的自然语言处理(NLP)标准接口,关键技术网关与配置参数如下:

1:OAuth 认证授权接口(TOKEN_URL):https://aip.baidubce.com/oauth/2.0/token,用于提交安全凭证以获取临时访问令牌 access_token。

2:文本纠错应用接口(CORRECT_URL):https://aip.baidubce.com/rpc/2.0/nlp/v1/ecnet,负责接收待检测文本并返回纠错碎片与整句建议。

3:限流机制与容错:由于免费或标准接口存在QPS(每秒查询率)限制,当请求过于频繁时接口会触发错误码18(QPS 限流错误) . 系统设计了MAX_RETRIES = 3的退避重试机制以保障高可用性 。

3.Python调用百度智能云API文本纠错实验

3.1 实验准备与环境配置

在运行本实验代码前,需做好以下准备工作:

1:软件包安装:本实验基于Python 3 语言环境,核心依赖内置标准库 csv、json、os、sys、time、pathlib 。此外,需要安装第三方网络请求库:

2:数据集准备:实验采用 sighan_sample.csv 作为批量基准数据集,文件中必须包含 id、wrong(错误文本)和 correct(标准答案)三列。

3:密钥获取:需在百度智能云控制台创建文本纠错应用,获取专属的 API Key Secret Key ,并将其配置于系统环境变量中(或在代码凭证函数中直接填写

3.2 实验完整代码实现

以下是本实验的完整 Python 实现源码,代码中包含了详尽的架构注释:

python 复制代码
mport csv

import json

import os

import sys

import time

from pathlib import Path



import requests

# ==================================================

# 1. 百度智能云接口地址

# ==================================================

TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token"

CORRECT_URL = "https://aip.baidubce.com/rpc/2.0/nlp/v1/ecnet"

REQUEST_TIMEOUT = 10

MAX_RETRIES = 3

RETRY_ERROR_CODE = 18

# ==================================================

# 2. 文件路径

# sighan_sample.csv 要和 aaa.py 放在同一个文件夹

# ==================================================

BASE_DIR = Path(__file__).resolve().parent

DATASET_PATH = BASE_DIR / "sighan_sample.csv"

OUTPUT_CSV = BASE_DIR / "baidu_correct_result.csv"

def get_credentials():

    """

    优先从环境变量读取密钥。

    如果你不想配置环境变量,也可以直接在这里填写。

    """

    api_key = os.getenv("BAIDU_API_KEY") or os.getenv("API_KEY") or ""

    secret_key = os.getenv("BAIDU_SECRET_KEY") or os.getenv("SECRET_KEY") or ""

    # 如果你想直接写在代码里,就取消下面两行注释,并填入自己的密钥

    # api_key = "你的 API Key"

    # secret_key = "你的 Secret Key"

    return api_key, secret_key

def get_access_token():

    """

    获取百度智能云 access_token。

    """

    api_key, secret_key = get_credentials()

    if not api_key or not secret_key:

        raise ValueError("请先配置 API_KEY 和 SECRET_KEY,或者在 get_credentials() 里直接填写。")

    params = {

        "grant_type": "client_credentials",

        "client_id": api_key,

        "client_secret": secret_key,

    }

    headers = {

        "Content-Type": "application/json",

        "Accept": "application/json",

    }

    response = requests.post(

        TOKEN_URL,

        params=params,

        headers=headers,

        timeout=REQUEST_TIMEOUT,

    )

    response.raise_for_status()

    result = response.json()

    if "access_token" not in result:

        raise RuntimeError(f"获取 access_token 失败:{result}")

    return result["access_token"]

def correct_text(text, access_token=None, max_retries=MAX_RETRIES):

    """

    调用百度文本纠错 API。

    遇到 QPS 限流 error_code=18 时自动重试。

    """

    if access_token is None:

        access_token = get_access_token()

    params = {

        "access_token": access_token,

        "charset": "UTF-8",

    }



    headers = {

        "Content-Type": "application/json",

    }

    data = {

        "text": text,

    }

    result = None

    for attempt in range(max_retries + 1):

        response = requests.post(

            CORRECT_URL,

            params=params,

            headers=headers,

            data=json.dumps(data, ensure_ascii=False).encode("utf-8"),

            timeout=REQUEST_TIMEOUT,

        )

        response.raise_for_status()

        result = response.json()

        if result.get("error_code") != RETRY_ERROR_CODE:

            return result

        if attempt == max_retries:

            return result

        wait_seconds = attempt + 1

        print(f"\n请求过快,{wait_seconds} 秒后自动重试...")

        time.sleep(wait_seconds)

    return result

def extract_corrected_text(original_text, result):

    """

    从百度 API 返回结果中提取纠错后的文本。

    """

    if "error_code" in result:

        return None

    item = result.get("item", {})

    corrected_text = item.get("correct_query", original_text)

    return corrected_text

def normalize_text(text):

    """

    简单文本标准化。

    去掉前后空格和普通空格,避免因为空格导致匹配失败。

    """

    if text is None:

        return ""

    return str(text).strip().replace(" ", "")

def load_dataset_from_csv(path):

    """

    读取 sighan_sample.csv。

    要求 CSV 至少包含三列:id, wrong, correct

    """

    if not path.exists():

        raise FileNotFoundError(f"没有找到数据集文件:{path}")

    samples = []

    with open(path, "r", encoding="utf-8-sig", newline="") as f:

        # skipinitialspace=True 可以处理逗号后面的空格

        reader = csv.DictReader(f, skipinitialspace=True)

        if reader.fieldnames is None:

            raise ValueError("CSV 文件为空,或者表头格式不正确。")

        # 去掉表头里的空格

        fieldnames = [name.strip() for name in reader.fieldnames]

        required_columns = {"id", "wrong", "correct"}

        if not required_columns.issubset(set(fieldnames)):

            raise ValueError(

                f"CSV 文件必须包含 id, wrong, correct 三列。当前表头是:{reader.fieldnames}"

            )

        for row in reader:

            # 防止表头或内容前后有空格

            clean_row = {}

            for key, value in row.items():

                if key is None:

                    continue

                clean_key = key.strip()

                clean_value = value.strip() if value is not None else ""

                clean_row[clean_key] = clean_value

            sample_id = clean_row.get("id", "")

            wrong_text = clean_row.get("wrong", "")

            correct_text_value = clean_row.get("correct", "")

            if not wrong_text:

                continue

            samples.append({

                "id": sample_id,

                "wrong": wrong_text,

                "correct": correct_text_value,

            })

    return samples

def show_result(original_text, result):

    """

    输出单句纠错结果。

    """

    print("\n========== 纠错结果 ==========")

    print("原始文本:", original_text)

    if "error_code" in result:

        print("\n接口调用失败:")

        print(result)

        if result.get("error_code") == RETRY_ERROR_CODE:

            print("\n说明:请求频率过高,已触发百度接口限流。")

        print("\n常见原因:")

        print("1. API Key 或 Secret Key 填错")

        print("2. 文本纠错服务没有开通")

        print("3. 免费次数为 0 或没有可用额度")

        print("4. 接口地址和你开通的服务版本不一致")

        return

    item = result.get("item", {})

    corrected_text = item.get("correct_query", original_text)

    score = item.get("score")

    error_num = item.get("error_num")

    print("纠错后文本:", corrected_text)

    if score is not None:

        print("置信度分数:", score)

    if error_num is not None:

        print("错误数量:", error_num)

    fragments = []

    if "vec_fragment" in item:

        fragments.extend(item.get("vec_fragment", []))

    for detail in item.get("details", []):

        fragments.extend(detail.get("vec_fragment", []))

    if fragments:

        print("\n错误片段与修改建议:")

        for i, frag in enumerate(fragments, start=1):

            ori_frag = frag.get("ori_frag", "")

            correct_frag = frag.get("correct_frag", "")

            begin_pos = frag.get("begin_pos", "")

            end_pos = frag.get("end_pos", "")

            explain = frag.get("explain", "")

            print(f"\n{i}. 原片段:{ori_frag}")

            print(f"   建议修改为:{correct_frag}")

            print(f"   位置:{begin_pos} - {end_pos}")

            if explain:

                print(f"   说明:{explain}")

    else:

        print("\n未检测到明显错误。")

    print("================================")

def save_batch_results(results, output_path):

    """

    保存批量测试结果到 CSV。

    """

    with open(output_path, "w", encoding="utf-8-sig", newline="") as f:

        fieldnames = [

            "id",

            "wrong_text",

            "standard_correct",

            "baidu_correct",

            "is_exact_match",

            "error_info",

        ]

        writer = csv.DictWriter(f, fieldnames=fieldnames)

        writer.writeheader()

        for row in results:

            writer.writerow(row)

def run_dataset_test():

    """

    从 sighan_sample.csv 读取数据,逐条调用百度文本纠错 API。

    """

    print("\n========== 批量测试:读取 sighan_sample.csv ==========")

    print(f"数据集路径:{DATASET_PATH}")

    samples = load_dataset_from_csv(DATASET_PATH)

    print(f"成功读取样本数量:{len(samples)}")

    if len(samples) == 0:

        print("数据集中没有有效样本,请检查 sighan_sample.csv。")

        return

    access_token = get_access_token()

    print("access_token 获取成功,开始批量调用百度文本纠错 API...")

    results = []

    exact_match_count = 0

    for index, sample in enumerate(samples, start=1):

        sample_id = sample["id"]

        wrong_text = sample["wrong"]

        standard_correct = sample["correct"]

        print("\n" + "-" * 60)

        print(f"第 {index} 条 / 共 {len(samples)} 条")

        print("错误句子:", wrong_text)

        print("标准答案:", standard_correct)

        try:

            result = correct_text(wrong_text, access_token=access_token)

        except requests.exceptions.RequestException as exc:

            print("网络请求失败:", exc)

            results.append({

                "id": sample_id,

                "wrong_text": wrong_text,

                "standard_correct": standard_correct,

                "baidu_correct": "",

                "is_exact_match": "False",

                "error_info": str(exc),

            })

            time.sleep(1.5)

            continue

        if "error_code" in result:

            print("接口调用失败:", result)

            results.append({

                "id": sample_id,

                "wrong_text": wrong_text,

                "standard_correct": standard_correct,

                "baidu_correct": "",

                "is_exact_match": "False",

                "error_info": str(result),

            })

            time.sleep(1.5)

            continue

        baidu_correct = extract_corrected_text(wrong_text, result)

        is_exact_match = normalize_text(baidu_correct) == normalize_text(standard_correct)

        if is_exact_match:

            exact_match_count += 1

        print("百度纠错:", baidu_correct)

        print("完全匹配:", is_exact_match)

        results.append({

            "id": sample_id,

            "wrong_text": wrong_text,

            "standard_correct": standard_correct,

            "baidu_correct": baidu_correct,

            "is_exact_match": str(is_exact_match),

            "error_info": "",

        })

        # 避免 QPS 限流

        time.sleep(1.5)

    total = len(samples)

    exact_match_rate = exact_match_count / total if total > 0 else 0

    print("\n" + "=" * 60)

    print("批量测试完成")

    print(f"样本总数:{total}")

    print(f"完全匹配数量:{exact_match_count}")

    print(f"完全匹配率:{exact_match_rate:.4f}")

    print(f"结果文件:{OUTPUT_CSV}")

    print("=" * 60)

    save_batch_results(results, OUTPUT_CSV)

def get_text_from_argv():

    """

    支持命令行直接传入待纠错文本。

    """

    if len(sys.argv) <= 1:

        return None

    text = " ".join(sys.argv[1:]).strip()

    if not text:

        return None

    if text.lower().endswith(".py") and ("python" in text.lower() or "\\" in text or "/" in text):

        return None

    return text

def main():

    print("百度智能云文本纠错系统")

    print("功能说明:")

    print("1. 输入普通文本:单句纠错")

    print("2. 输入 batch:读取 sighan_sample.csv 批量测试")

    print("3. 输入 q:退出程序")

    cli_text = get_text_from_argv()

    if cli_text:

        try:

            result = correct_text(cli_text)

            show_result(cli_text, result)

        except requests.exceptions.RequestException as exc:

            print("\n网络请求失败:")

            print(exc)

        except Exception as exc:

            print("\n程序运行出错:")

            print(exc)

        return

    while True:

        text = input("\n请输入需要纠错的文本,或输入 batch 运行数据集测试:").strip()

        if text.lower() == "q":

            print("程序已退出。")

            break

        if text.lower() == "batch":

            try:

                run_dataset_test()

            except requests.exceptions.RequestException as exc:

                print("\n网络请求失败:")

                print(exc)

            except Exception as exc:

                print("\n程序运行出错:")

                print(exc)

            continue

        if not text:

            print("输入不能为空,请重新输入。")

            continue

        try:

            result = correct_text(text)

            show_result(text, result)

        except requests.exceptions.RequestException as exc:

            print("\n网络请求失败:")

            print(exc)

        except Exception as exc:

            print("\n程序运行出错:")

            print(exc)

if __name__ == "__main__":

    main()

3.3 实验测试结果展示

系统部署并在终端环境中运行成功后,单句纠错与批量数据集跑测的表现优异,以下截取测试日志的关键正向样本:

测试案例一(字词与同音混淆错误处理)

测试案例二(同音字辨析)

3.4 现存问题与深层原因分析

在针对高难度文本与多源异构数据集进行深度批量跑测时,系统暴露出了一定的技术瓶颈 。

如上面的图片所示,核心问题主要表现为:当输入的文本中含有大量繁体中文或属于宏观语序错乱的语法病句时,该模型的识别与纠正通过率显著下降(完全匹配结果返回 False)。

根据技术细节和返回的 JSON 数据,现对该现象做以下深入剖析:

1:文本空间与泛化局限性(繁体支持弱):前三条不通过样例属于繁体中文(例如:"擁有六百年歷史的崇禮門......"、"我一身中的貴人......") 。百度智能云的普通文本纠错接口内部的语言模型更侧重于简体中文语料,对繁体文本的编码和分词支持不够稳定,极易发生漏纠现象。

2:错误类型不适配(缺乏句法逻辑整合):后两条属于明显的成分残缺或句式杂糅等语法病句(例如:"通过这次活动,使我明白了......") 。此类错误必须在掌握全句长距离依赖(Long-term Dependency)和树状语法结构的基础上进行整句结构调整 。而本实验所调用的普通纠错接口,其底座技术更偏向于词级别(Word-level)的错别字、别词及拼写检查,无法有效处理句法层面的深度逻辑重构。

未来改进方案:后续研究可尝试切换并接入百度智能云提供的高级文本纠错接口(基于大语言模型精调版),或者在数据输入前加设一层"繁转简"的文本清洗管道。

相关推荐
宸津-代码粉碎机1 小时前
Spring AI企业级RAG进阶|文档智能分片调优、ES深度整合、接口限流熔断监控生产实战
java·开发语言·人工智能·后端·spring·elasticsearch·oracle
知识浅谈1 小时前
人工智能日报 每日AI新闻(2026年6月2日):OpenAI上AWS、Anthropic递表与AI终端竞赛升温
大数据·人工智能·aws
Ai财富密码1 小时前
【Codex入门教程2】用Codex零基础手搓“双摄 App”并上架 App Store 的通关指南
人工智能·codex·gpt5.5·双摄app
qqxhb2 小时前
36|RAG 评测与回归:命中率、覆盖率、引用正确性
人工智能·数据挖掘·回归·覆盖率·命中率·正确性
神州数码云基地2 小时前
DSPy + Parlant:从手动调优到自动编译的效率加速器
人工智能·深度学习·机器学习
云烟成雨TD9 小时前
Spring AI Alibaba 1.x 系列【69】Token 用量统计
java·人工智能·spring
十三画者9 小时前
【AI学习笔记】:DeepSeek 大模型本地部署与调用实战指南
人工智能
丁常彦-自媒体-常言道9 小时前
从首发4nm智驾芯片到兜底城市领航安全,比亚迪开启AI新征程
人工智能