版本: 1.0 日期: 2026-07-07 状态: 定稿
构建 bid_proposal 包,实现"根据招标文件自动生成投标文件"的核心功能。系统读取招标 PDF,分析其中的评审标准、服务要求、资质要求等,逐项生成对应的投标响应内容,最终输出为格式化 DOCX 投标文件。
pdf_table_to_docx 包的表格提取能力,不重复造轮子。pdf_table_to_docx 的关系bid_proposal (新包)
│
├── 依赖 pdf_table_to_docx.extractor.PDFTableExtractor 用于表格提取
├── 依赖 pymupdf (已安装) 用于文本提取
└── 依赖 python-docx (已安装) 用于 DOCX 输出
bid_proposal/
├── __init__.py # 包入口
├── models.py # 【共享】所有数据类定义(A1 编写,A2 引用)
├── config.py # 【共享】配置管理(A1 编写,A2 引用)
│
├── bid_reader.py # 【A1】招标文件读取
├── requirement_analyzer.py # 【A1】需求分析(OpenAI)
│
├── proposal_generator.py # 【A2】投标内容生成(OpenAI)
├── proposal_writer.py # 【A2】投标文件 DOCX 输出
├── pipeline.py # 【A2】流程编排
├── cli.py # 【A2】命令行入口
├── __main__.py # 【A2】python -m 支持
│
└── tests/ # 测试
├── test_a1.py
└── test_a2.py
招标PDF文件
│
▼
┌──────────────┐
│ bid_reader │ pymupdf → 文本内容
│ │ pdf_table_to_docx → 表格内容
└──────┬───────┘
│ BidDocument (text + tables + pages)
▼
┌──────────────┐
│ requirement │ OpenAI API → 需求结构化分析
│ _analyzer │ 识别评审项 / 服务要求 / 资质要求
└──────┬───────┘
│ AnalysisResult (requirements + summary)
▼
┌──────────────┐
│ proposal │ OpenAI API → 逐项生成投标响应
│ _generator │ 根据需求内容 + 评分标准生成
└──────┬───────┘
│ ProposalDocument (title + sections)
▼
┌──────────────┐
│ proposal │ python-docx → 格式化DOCX
│ _writer │ 封面 / 目录 / 标题 / 正文 / 表格
└──────┬───────┘
│
▼
投标文件 DOCX
| 模块 | 职责 | 外部依赖 |
|---|---|---|
models.py |
所有数据类定义 | — |
config.py |
配置读取(API Key、模型名等) | — |
bid_reader.py |
读取招标PDF,提取文本+表格 | pymupdf, pdf_table_to_docx |
requirement_analyzer.py |
分析招标要求,结构化输出 | OpenAI API |
proposal_generator.py |
根据需求生成投标响应内容 | OpenAI API |
proposal_writer.py |
将投标内容输出为格式化DOCX | python-docx |
pipeline.py |
编排完整流程,处理异常和日志 | 以上所有模块 |
cli.py |
命令行入口 | pipeline |
models.py)from dataclasses import dataclass, field
from typing import Optional
from pdf_table_to_docx.table_parser import TableInfo
@dataclass
class BidPage:
"""招标文件中的一页"""
page_num: int # 页码(1-indexed)
text: str # 页面文本内容
@dataclass
class BidDocument:
"""招标文件结构化内容"""
pdf_path: str # PDF 文件路径
file_name: str # 文件名
total_pages: int # 总页数
pages: list[BidPage] # 所有页面文本
full_text: str # 全文拼接文本(供 AI 分析使用)
tables: list[TableInfo] # 从 PDF 提取的表格
table_count: int # 表格数量
@dataclass
class Requirement:
"""单个招标要求项"""
category: str # 类别(evaluation/service/qualification/other)
title: str # 要求标题
description: str # 详细描述
score: Optional[float] = None # 分值(评分项专用)
detail: str = "" # 评分标准详细说明
@dataclass
class AnalysisResult:
"""招标文件分析结果"""
summary: str # 招标概要
project_name: str = "" # 项目名称
evaluation_criteria: list[Requirement] = field(default_factory=list) # 评审标准
service_requirements: list[Requirement] = field(default_factory=list) # 服务要求
qualification_requirements: list[Requirement] = field(default_factory=list) # 资质要求
other_requirements: list[Requirement] = field(default_factory=list) # 其他要求
raw_response: str = "" # AI 原始响应(调试用)
@dataclass
class ProposalSection:
"""投标文件的一个章节"""
title: str # 章节标题
level: int = 1 # 层级(1=一级标题, 2=二级标题)
content: str = "" # 章节正文
requirement_ref: str = "" # 对应的招标要求引用
@dataclass
class ProposalDocument:
"""完整的投标文件内容"""
title: str # 文档标题
project_name: str = "" # 项目名称
sections: list[ProposalSection] = field(default_factory=list) # 所有章节
summary: str = "" # 投标概要
Requirement.category 使用以下四类:
| 分类值 | 说明 | 示例 |
|---|---|---|
evaluation |
评审标准/评分项 | "技术方案(30分)"、"服务团队(20分)" |
service |
服务要求/技术需求 | "物业管理服务范围"、"人员配置要求" |
qualification |
资质要求/资格条件 | "具有ISO9001认证"、"注册资本≥500万" |
other |
其他 | 投标须知、文件格式要求等 |
bid_reader.py — 招标文件读取职责:
BidDocument 对象关键设计决策:
page.get_text("text"),对中文 PDF 提取质量较好PDFTableExtractor(含跨页表格合并逻辑)full_text 为所有页面文本拼接(供 AI 分析的完整上下文)接口定义:
def read_bid_pdf(pdf_path: str) -> BidDocument:
"""读取招标 PDF,提取文本和表格。
Args:
pdf_path: 招标文件 PDF 路径
Returns:
BidDocument: 结构化招标内容
Raises:
FileNotFoundError: PDF 文件不存在
BidReadError: PDF 读取/解析失败(如文件损坏、加密等)
"""
requirement_analyzer.py — 需求分析职责:
BidDocument,使用 OpenAI API 分析其中的评审要求关键设计决策:
AnalysisResult接口定义:
class RequirementAnalyzer:
"""招标文件需求分析器。"""
def __init__(self, api_key: Optional[str] = None, model: str = "gpt-4o"):
"""初始化分析器。
Args:
api_key: OpenAI API Key,默认从 OPENAI_API_KEY 环境变量读取
model: 使用的模型名称
"""
def analyze(self, doc: BidDocument) -> AnalysisResult:
"""对招标文件进行 AI 分析,提取所有要求。
Args:
doc: 招标文件结构化内容
Returns:
AnalysisResult: 分析结果(结构化需求列表 + 摘要)
Raises:
AnalysisError: AI 分析失败(API 错误、响应格式异常等)
"""
proposal_generator.py — 投标内容生成职责:
AnalysisResult,逐项生成投标响应内容ProposalDocument关键设计决策:
接口定义:
class ProposalGenerator:
"""投标内容生成器。"""
def __init__(self, api_key: Optional[str] = None, model: str = "gpt-4o"):
"""初始化生成器。
Args:
api_key: OpenAI API Key,默认从 OPENAI_API_KEY 环境变量读取
model: 使用的模型名称
"""
def generate(self, analysis: AnalysisResult) -> ProposalDocument:
"""根据招标要求生成投标内容。
Args:
analysis: 招标分析结果
Returns:
ProposalDocument: 生成的投标内容
Raises:
GenerationError: 内容生成失败(API 错误、格式异常等)
"""
proposal_writer.py — 投标文件输出职责:
ProposalDocument 输出为格式化的 DOCX 文件关键设计决策:
pdf_table_to_docx/docx_writer.py 借鉴经验,但投标文件有独立样式需求接口定义:
def write_proposal_docx(
content: ProposalDocument,
output_path: str,
*,
page_width_cm: float = 21.0,
page_height_cm: float = 29.7,
margin_cm: float = 2.5,
) -> str:
"""将投标内容写入格式化的 DOCX 文件。
Args:
content: 投标内容
output_path: 输出路径
page_width_cm: 页面宽度(默认 A4)
page_height_cm: 页面高度(默认 A4)
margin_cm: 页边距
Returns:
str: 输出文件路径
Raises:
WriteError: DOCX 写入失败
"""
pipeline.py — 流程编排职责:
接口定义:
def run_pipeline(
pdf_path: str,
output_path: Optional[str] = None,
api_key: Optional[str] = None,
model: str = "gpt-4o",
) -> str:
"""运行完整的招标→投标生成流程。
Args:
pdf_path: 招标文件 PDF 路径
output_path: 输出 DOCX 路径(默认与输入同目录)
api_key: OpenAI API Key(默认从环境变量读取)
model: AI 模型名
Returns:
str: 输出文件路径
Raises:
BidReadError: PDF 读取失败
AnalysisError: 需求分析失败
GenerationError: 内容生成失败
WriteError: DOCX 输出失败
"""
cli.py — 命令行入口接口定义:
# 一键生成
python -m bid_proposal 招标文件.pdf
# 指定输出路径
python -m bid_proposal 招标文件.pdf -o 投标文件.docx
# 指定模型
python -m bid_proposal 招标文件.pdf --model gpt-4o
# 详细日志
python -m bid_proposal 招标文件.pdf --verbose
| 现有模块 | 复用方式 | 说明 |
|---|---|---|
pdf_table_to_docx.extractor.PDFTableExtractor |
直接实例化 | 复用表格提取和跨页合并 |
pdf_table_to_docx.table_parser.TableInfo |
类型引用 | 在 BidDocument.tables 中使用 |
| 现有模块 | 原因 |
|---|---|
pdf_table_to_docx.docx_writer |
投标文件的 DOCX 样式需求不同(封面、标题层级、页眉等) |
pdf_table_to_docx.text_scorer |
投标生成不需要 NLP 评分 |
pyproject.toml 中声明)— OpenAI API 调用pyproject.toml 中声明)— PDF 文本提取BidProposalError (base)
├── BidReadError — PDF 读取/解析失败
├── AnalysisError — AI 分析失败(API 错误、格式异常)
├── GenerationError — 内容生成失败
└── WriteError — DOCX 输出失败
| 场景 | 处理方式 |
|---|---|
| 表格提取失败 | 仅使用文本内容继续分析,日志记录警告 |
| API 部分失败 | 标记失败项为"【待人工补充】",继续后续步骤 |
| 输出目录不可写 | 回退到系统临时目录 |
| 变量 | 用途 | 默认值 |
|---|---|---|
OPENAI_API_KEY |
OpenAI API 密钥 | —(必需) |
config.py 设计import os
class Config:
"""配置管理。"""
@staticmethod
def get_openai_api_key() -> str:
"""获取 OpenAI API Key。"""
api_key = os.environ.get("OPENAI_API_KEY")
if not api_key:
raise ValueError(
"未设置 OPENAI_API_KEY 环境变量"
)
return api_key
@staticmethod
def get_default_model() -> str:
"""获取默认模型名。"""
return os.environ.get("OPENAI_MODEL", "gpt-4o")
A1 工作包(先决) A2 工作包(依赖 A1 的接口定义)
┌──────────────────────┐ ┌──────────────────────────┐
│ models.py (共享) │ │ proposal_generator.py │
│ config.py (共享) │◀─────────│ proposal_writer.py │
│ bid_reader.py │ │ pipeline.py │
│ requirement_ │ │ cli.py │
│ analyzer.py │ │ __main__.py │
└──────────────────────┘ └──────────────────────────┘
bid_reader.py + requirement_analyzer.py)实现文件:
bid_proposal/__init__.pybid_proposal/models.py — 所有数据类定义bid_proposal/config.py — 配置管理bid_proposal/bid_reader.py — 招标文件读取bid_proposal/requirement_analyzer.py — 需求分析接口契约(A1 对 A2 提供的接口):
# models.py
@dataclass class BidDocument: ...
@dataclass class Requirement: ...
@dataclass class AnalysisResult: ...
@dataclass class ProposalSection: ...
@dataclass class ProposalDocument: ...
# bid_reader.py
def read_bid_pdf(pdf_path: str) -> BidDocument: ...
# requirement_analyzer.py
class RequirementAnalyzer:
def analyze(self, doc: BidDocument) -> AnalysisResult: ...
验收标准:
详细任务见 task_a1.md。
proposal_generator.py + proposal_writer.py + pipeline.py)实现文件:
bid_proposal/proposal_generator.py — 投标内容生成bid_proposal/proposal_writer.py — 投标文件输出bid_proposal/pipeline.py — 流程编排bid_proposal/cli.py — 命令行入口bid_proposal/__main__.py — python -m 支持接口契约(A2 对 A1 的依赖):
models.py 中定义的数据类bid_reader.read_bid_pdf() 和 RequirementAnalyzer.analyze()验收标准:
详细任务见 task_a2.md。
| 方向 | 说明 | 优先级 |
|---|---|---|
| 多轮对话优化 | 用户可对生成内容提出修改意见,AI 根据反馈调整 | 中 |
| 模板匹配 | 支持用户提供历史投标文件作为风格模板 | 低 |
| 评分预测 | 根据生成内容预测评审得分,指导内容优化 | 低 |
| 参考文档库 | 支持参考多个招标文件和投标文件进行综合生成 | 低 |
| 并行生成 | 章节级并行调用 OpenAI API,加速生成 | 低 |