【RAG】知识库搭建-文档预处理-数据清洗:基于异步的AI文本批处理系统实践

知识库搭建-文档预处理-数据清洗:基于异步的AI文本批处理系统实践

项目背景

在构建企业级知识库和RAG(检索增强生成)系统时,文档预处理和数据清洗是至关重要的环节。原始文档往往存在格式不统一、内容冗余、质量参差不齐等问题,这些问题会直接影响到向量数据库的检索质量和后续AI模型的表现。为了解决这个问题,我开发了一个基于Python的异步文本批处理系统。通过这个系统的处理,我们可以显著提升知识库的质量,为后续的向量检索和AI应用打下坚实的基础。

技术架构

项目采用了以下核心技术栈:

  • Python 3.x
  • asyncio:用于异步并发处理
  • aiohttp:处理异步HTTP请求
  • OpenAI兼容API:用于文本处理
  • tqdm:提供进度条显示
  • Pathlib:处理文件路径

核心功能

  1. 多格式支持:支持txt、md、doc、docx等多种文本格式
  2. 异步处理:使用Python的asyncio实现高效的并发处理
  3. 并发控制:通过信号量限制最大并发数,避免API限制
  4. 自动化管理:自动创建输入输出目录,统一文件命名
  5. 错误处理:完善的异常处理机制
  6. 进度显示:实时显示处理进度

完整代码

1、batch_processor.py

python 复制代码
import os
import asyncio
from pathlib import Path
from typing import List
import openai
from tqdm import tqdm
from datetime import datetime
from config import API_KEY, API_BASE, MODEL_NAME, PROMPT_TEMPLATE, INPUT_DIR, OUTPUT_DIR

class BatchProcessor:
    def __init__(self):
        """初始化批处理器"""
        # 配置OpenAI客户端
        self.client = openai.OpenAI(
            api_key=API_KEY,
            base_url=API_BASE
        )
        
        # 创建输入输出目录
        self._create_directories()
        
        # 设置并发限制
        self.semaphore = asyncio.Semaphore(5)  # 限制最大并发数为5
        
    def _create_directories(self):
        """创建必要的目录"""
        os.makedirs(INPUT_DIR, exist_ok=True)
        os.makedirs(OUTPUT_DIR, exist_ok=True)
        
    def get_input_files(self) -> List[Path]:
        """获取输入文件列表,支持多种文本文件格式"""
        input_path = Path(INPUT_DIR)
        # 支持多种文本文件格式
        text_extensions = ['.txt', '.md', '.doc', '.docx', '.rtf', '.html', '.htm']
        input_files = []
        for ext in text_extensions:
            input_files.extend(list(input_path.glob(f'*{ext}')))
        return input_files
    
    async def process_file(self, input_file: Path) -> str:
        """异步处理单个文件"""
        async with self.semaphore:  # 使用信号量控制并发
            try:
                # 读取文件内容
                with open(input_file, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # 构建提示词
                prompt = PROMPT_TEMPLATE.format(content=content)
                
                # 调用API
                response = await asyncio.to_thread(
                    self.client.chat.completions.create,
                    model=MODEL_NAME,
                    messages=[
                        {"role": "system", "content": "你是一个专业的文本优化助手。"},
                        {"role": "user", "content": prompt}
                    ],
                    temperature=0.7,
                    max_tokens=4096  # 修改为模型支持的最大token数
                )
                
                # 获取生成的内容
                generated_content = response.choices[0].message.content
                
                # 添加延迟以避免API限制
                await asyncio.sleep(1)
                
                return generated_content
                
            except Exception as e:
                print(f"处理文件 {input_file} 时出错: {str(e)}")
                return None
    
    async def save_output(self, input_file: Path, content: str):
        """异步保存输出文件,统一使用.md格式"""
        if content is None:
            return
            
        # 生成带时间戳的输出文件名,统一使用.md后缀
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_file = Path(OUTPUT_DIR) / f"{input_file.stem}_processed_{timestamp}.md"
        
        # 使用异步文件操作
        await asyncio.to_thread(
            lambda: open(output_file, 'w', encoding='utf-8').write(content)
        )
    
    async def process_all_files(self):
        """异步处理所有文件"""
        input_files = self.get_input_files()
        
        if not input_files:
            print(f"请在 {INPUT_DIR} 目录中放入要处理的文本文件")
            return
            
        print(f"找到 {len(input_files)} 个文件待处理")
        
        # 创建所有任务
        tasks = []
        for input_file in input_files:
            # 创建处理文件的任务
            task = asyncio.create_task(self.process_file(input_file))
            tasks.append((input_file, task))
        
        # 使用tqdm显示进度条
        with tqdm(total=len(tasks), desc="处理文件") as pbar:
            # 等待所有任务完成
            for input_file, task in tasks:
                content = await task
                await self.save_output(input_file, content)
                pbar.update(1)

def main():
    """主函数"""
    processor = BatchProcessor()
    # 使用asyncio.run()来运行异步主函数
    asyncio.run(processor.process_all_files())

if __name__ == "__main__":
    main() 

2、config.py

python 复制代码
import os
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

# API配置
API_KEY = os.getenv(
    "API_KEY", "sk-xxx"
)  # 从环境变量获取API密钥
API_BASE = os.getenv("API_BASE", "https://xxx/v1")  # API基础URL
MODEL_NAME = os.getenv("MODEL_NAME", "gpt-3.5-turbo")  # 使用的模型名称

# 提示词模板集合
PROMPT_TEMPLATES = {
    "optimize": """
你是一个专业的文档数据清洗专家,负责处理和优化用于RAG知识库构建的文档。请按照以下指南对提供的文档进行全面清洗和标准化处理:

### 数据清洗任务:

1. 去除无关内容:
   - 删除所有广告内容
   - 移除页眉页脚信息(如页码、章节标题等重复出现的元素)
   - 清除水印文本
   - 去除版权声明、免责声明等非核心内容
   - 删除装饰性特殊字符和符号

2. 标准化格式:
   - 将所有文本转换为UTF-8编码
   - 统一标点符号(如将全角标点转为半角,或根据文档主要语言选择合适的标点规范)
   - 规范化空格使用(删除多余空格,保持段落间隔一致)
   - 对于中文文档,确保使用标准中文标点
   - 对于英文部分,统一大小写规范(如专有名词、缩写等)

3. 处理缺失值和噪声:
   - 修正OCR错误(如"0"与"O"、"1"与"l"的混淆)
   - 识别并修复断行导致的词语分割
   - 合并被错误分割的段落
   - 修正明显的拼写和语法错误
   - 标记无法修复的损坏内容

4. 结构优化:
   - 重新组织文档的层次结构(标题、小标题、段落)
   - 确保列表格式一致(编号、项目符号等)
   - 保持表格数据的完整性和可读性
   - 确保图表引用的连贯性

5. 语义保全:
   - 确保清洗过程不改变原文档的核心含义
   - 保留专业术语和领域特定词汇
   - 维持上下文关系和逻辑连贯性

### 输出要求:

1. 严格要求:仅输出清洗后的文档内容,不要包含任何解释、说明或其他额外内容
2. 使用markdown格式输出清洗后的完整文档
3. 不要添加任何前缀、后缀或额外的评论
4. 输出结果强化:
   - 确保文档具有清晰的层次结构,使用适当的标题级别(#、##、###等)
   - 主要章节使用一级标题(#),子部分使用二级标题(##),更细分的内容使用三级标题(###)
   - 相关内容应组织在同一部分下,保持逻辑连贯性
   - 为没有明确标题的重要段落添加适当的小标题
   - 确保标题层级之间的逻辑关系清晰,避免层级跳跃

请处理以下文档内容:

{content}
""",
}

# 当前激活的提示词模板
ACTIVE_TEMPLATE = os.getenv("ACTIVE_TEMPLATE", "optimize")  # 默认使用优化模板

# 获取当前激活的提示词模板
PROMPT_TEMPLATE = PROMPT_TEMPLATES.get(ACTIVE_TEMPLATE, PROMPT_TEMPLATES["optimize"])

# 文件路径配置
INPUT_DIR = "docs"  # 输入文件目录
OUTPUT_DIR = "docs-output"  # 输出文件目录

3、requirements.txt

bash 复制代码
openai>=1.0.0
python-dotenv>=0.19.0
tqdm>=4.65.0 
aiohttp>=3.8.0

技术实现细节

1. 异步并发设计

python 复制代码
class BatchProcessor:
    def __init__(self):
        # 限制最大并发数为5,避免API过载
        self.semaphore = asyncio.Semaphore(5)
        
    async def process_file(self, input_file: Path) -> str:
        async with self.semaphore:  # 使用信号量控制并发
            # 处理逻辑
            pass

2. 智能文件处理

python 复制代码
def get_input_files(self) -> List[Path]:
    """获取输入文件列表,支持多种文本文件格式"""
    text_extensions = ['.txt', '.md', '.doc', '.docx', '.rtf', '.html', '.htm']
    input_files = []
    for ext in text_extensions:
        input_files.extend(list(input_path.glob(f'*{ext}')))
    return input_files

3. 输出文件管理

python 复制代码
async def save_output(self, input_file: Path, content: str):
    # 生成带时间戳的输出文件名
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    output_file = Path(OUTPUT_DIR) / f"{input_file.stem}_processed_{timestamp}.md"

项目优势

  1. 高效性:采用异步并发处理,显著提升处理效率
  2. 可扩展性:模块化设计,易于添加新功能
  3. 稳定性:完善的错误处理机制,确保系统稳定运行
  4. 易用性:简单的配置和使用方式,上手门槛低

使用方法

  1. 安装依赖:
bash 复制代码
pip install -r requirements.txt
  1. 配置系统:
  • 创建配置文件,设置必要的环境变量
  • 可自定义处理模板和目录路径
  1. 运行系统:
bash 复制代码
python batch_processor.py
相关推荐
技能咖43 分钟前
2025春招市场迎AI热潮:生成式人工智能(GAI)认证如何重构人才竞争力
人工智能
2301_764441331 小时前
基于BERT的序列到序列(Seq2Seq)模型,生成文本摘要或标题
人工智能·python·深度学习·bert
说私域2 小时前
开源链动2+1模式与AI智能名片赋能的S2B2C共享经济新生态
人工智能·微信·小程序·开源
蹦蹦跳跳真可爱5892 小时前
Python----计算机视觉处理(Opencv:霍夫变换)
人工智能·python·opencv·计算机视觉
livefan2 小时前
英伟达「虚拟轨道+AI调度」专利:开启自动驾驶3.0时代的隐形革命
人工智能·机器学习·自动驾驶
wd2099882 小时前
手绘的思维导图怎么转成电子版思维导图?分享今年刚测试出来的方法
人工智能·powerpoint
魔珐科技3 小时前
专访中兴通讯蒋军:AI数字人驱动企业培训,“内容生产”与“用户体验”双重提升
人工智能·aigc·ai数字人
果冻人工智能3 小时前
Linux 之父把 AI 泡沫喷了个遍:90% 是营销,10% 是现实。
人工智能
果冻人工智能3 小时前
Sal Khan 和 Bill Gates 对 AI 的看法错了
人工智能