| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- """
- Phase 3: 公司信息收集模板生成
- 基于招标文件 + 历史投标文件,生成投标公司需要补充的信息清单。
- 输出为简化版 JSON:仅有"名称"、"内容/文件地址"、"来源参考"三项。
- 用法:
- python -m phase3_collection.generate_template
- 或:
- from phase3_collection.generate_template import generate_template
- template = generate_template(tender_text, bid_toc)
- """
- import sys
- import os
- import json
- sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
- from llm.llm_utils import LLM
- # ── 预定义信息项(基于招标文件已知要求的兜底清单) ──
- FALLBACK_ITEMS = [
- {"名称": "公司全称", "内容/文件地址": "", "来源参考": "投标函格式、历史投标文件封面"},
- {"名称": "统一社会信用代码", "内容/文件地址": "", "来源参考": "营业执照"},
- {"名称": "注册地址", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "联系电话", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "传真", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "邮政编码", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "开户银行", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "银行账号", "内容/文件地址": "", "来源参考": "投标函格式"},
- {"名称": "营业执照扫描件", "内容/文件地址": "", "来源参考": "历史投标文件第十一项(第41页)"},
- {"名称": "法定代表人姓名", "内容/文件地址": "", "来源参考": "法定代表人授权书格式"},
- {"名称": "法定代表人职务", "内容/文件地址": "", "来源参考": "法定代表人授权书格式"},
- {"名称": "法定代表人身份证(正面)", "内容/文件地址": "", "来源参考": "历史投标文件第五章第(一)项(第19页)"},
- {"名称": "法定代表人身份证(反面)", "内容/文件地址": "", "来源参考": "历史投标文件第五章第(一)项"},
- {"名称": "授权委托人姓名", "内容/文件地址": "", "来源参考": "法定代表人授权书格式"},
- {"名称": "授权委托人职务", "内容/文件地址": "", "来源参考": "法定代表人授权书格式"},
- {"名称": "授权委托人电话", "内容/文件地址": "", "来源参考": "法定代表人授权书格式"},
- {"名称": "授权委托人身份证(正面)", "内容/文件地址": "", "来源参考": "历史投标文件第五章第(二)项"},
- {"名称": "授权委托人身份证(反面)", "内容/文件地址": "", "来源参考": "历史投标文件第五章第(二)项"},
- {"名称": "授权委托书(签字+公章扫描件)", "内容/文件地址": "", "来源参考": "格式参照招标文件第六章"},
- {"名称": "ISO 9001 质量管理体系认证证书", "内容/文件地址": "", "来源参考": "历史投标文件第十九项"},
- {"名称": "ISO 14001 环境管理体系认证证书", "内容/文件地址": "", "来源参考": "历史投标文件第十九项"},
- {"名称": "ISO 45001 职业健康安全管理体系认证证书", "内容/文件地址": "", "来源参考": "历史投标文件第十九项"},
- {"名称": "其他资质证书(保安备案/保洁能力/供应商证明)", "内容/文件地址": "", "来源参考": "历史投标文件第十二至十五项(第42-43页)"},
- {"名称": "上年度(2024年)审计报告或财务报表", "内容/文件地址": "", "来源参考": "历史投标文件第七项(第21-28页)"},
- {"名称": "近期依法缴纳税收的证明(完税凭证)", "内容/文件地址": "", "来源参考": "历史投标文件第八项第一(第29页)"},
- {"名称": "近期依法缴纳社保费的证明", "内容/文件地址": "", "来源参考": "历史投标文件第八项第二(第30页)"},
- {"名称": "信用中国无失信截图", "内容/文件地址": "", "来源参考": "历史投标文件第十项(第32页)"},
- {"名称": "政府采购网无严重违法失信截图", "内容/文件地址": "", "来源参考": "历史投标文件第九项(第31页)"},
- {"名称": "从业人员数量", "内容/文件地址": "", "来源参考": "中小企业声明函格式"},
- {"名称": "上年度营业收入(万元)", "内容/文件地址": "", "来源参考": "中小企业声明函格式"},
- {"名称": "上年度资产总额(万元)", "内容/文件地址": "", "来源参考": "中小企业声明函格式"},
- {"名称": "企业规模类型(中型/小型/微型)", "内容/文件地址": "", "来源参考": "中小企业声明函格式"},
- {"名称": "拟派项目经理姓名", "内容/文件地址": "", "来源参考": "项目经理情况表格式(招标文件第39页)"},
- {"名称": "项目经理出生年月", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理文化程度", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理毕业院校及专业", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理从事物业服务工作年限", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理职业资格", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理技术职称", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理主要工作经历和业绩", "内容/文件地址": "", "来源参考": "项目经理情况表格式"},
- {"名称": "项目经理近半年社保缴纳证明", "内容/文件地址": "", "来源参考": "招标文件评分标准—项目经理(3分)"},
- {"名称": "项目管理团队主要人员信息", "内容/文件地址": "", "来源参考": "招标文件第40页—管理人员汇总表"},
- {"名称": "各专业技术人员执业/职业资格证书", "内容/文件地址": "", "来源参考": "历史投标文件—各主管持证情况"},
- {"名称": "近三年办公楼物业业绩合同扫描件", "内容/文件地址": "", "来源参考": "招标文件评分标准—业绩(5分)"},
- {"名称": "类似业绩业主评价(满意度证明)", "内容/文件地址": "", "来源参考": "历史投标文件第十八项(第245页)"},
- {"名称": "企业获奖证明", "内容/文件地址": "", "来源参考": "历史投标文件第二十项(第261页)"},
- {"名称": "雇主责任险和公众责任险购买承诺", "内容/文件地址": "", "来源参考": "招标文件评分标准—责任保险(4分)"},
- {"名称": "拟投入本项目的设备一览表", "内容/文件地址": "", "来源参考": "招标文件第42页—设备一览表格式"},
- {"名称": "公司简介", "内容/文件地址": "", "来源参考": "历史投标文件公司概况介绍"},
- {"名称": "公司现有管理制度目录", "内容/文件地址": "", "来源参考": "招标文件第37页—管理制度一览表格式"},
- ]
- def generate_template(
- tender_text: str = None,
- bid_toc: list = None,
- output_path: str = None,
- use_llm: bool = False,
- ) -> dict:
- """
- 生成投标公司信息收集模板。
- Args:
- tender_text: 招标文件全文(可选,LLM 模式下使用)
- bid_toc: 历史投标文件目录(可选,LLM 模式下使用)
- output_path: 保存路径
- use_llm: 是否使用 LLM 动态生成(默认 False,使用预定义清单)
- Returns:
- 模板 JSON 字典
- """
- if use_llm and tender_text and bid_toc:
- items = _llm_generate(tender_text, bid_toc)
- else:
- items = FALLBACK_ITEMS
- template = {
- "投标公司信息收集表": {
- "说明": "投标公司根据此表提供信息,填充'内容/文件地址'列即可。",
- "数据来源": {
- "招标文件": "data/松江区机关事务管理局物业管理服务招标文件.pdf",
- "历史投标文件参考": "data/松江区机关事务管理局物业管理服务项目投标文件.pdf",
- },
- "信息项": items,
- }
- }
- if output_path:
- os.makedirs(os.path.dirname(output_path) or ".", exist_ok=True)
- with open(output_path, "w", encoding="utf-8") as f:
- json.dump(template, f, ensure_ascii=False, indent=2)
- print(f"[Phase3] 模板已保存: {output_path} ({len(items)} 项)")
- return template
- def _llm_generate(tender_text: str, bid_toc: list) -> list:
- """使用 LLM 动态生成信息项(备用路径)"""
- llm = LLM()
- # 构建历史投标目录文本
- toc_lines = []
- for item in bid_toc[:60]:
- indent = " " * (item.get("level", 1) - 1)
- toc_lines.append(f"{indent}{item['title']} (p.{item.get('page','')})")
- bid_toc_text = "\n".join(toc_lines)
- system = (
- "你是一个投标文件分析助手。根据招标文件要求和历史投标文件内容,"
- "列出投标公司需要提供的所有信息和材料清单。\n\n"
- "输出 JSON 数组,每个元素包含:\n"
- '- "名称": 信息项名称\n'
- '- "内容/文件地址": 留空字符串\n'
- '- "来源参考": 招标文件第几章或历史投标文件第几页\n\n'
- "覆盖以下类别:\n"
- "- 公司基本信息(名称、地址、联系人等)\n"
- "- 法定代表人/授权委托人信息(姓名、身份证照片等)\n"
- "- 资质证书(营业执照、体系认证、专业资质等)\n"
- "- 财务状况(审计报告、纳税和社保凭证等)\n"
- "- 企业声明函(中小企业声明、无失信声明等)\n"
- "- 团队人员(项目经理、主要管理人员信息)\n"
- "- 历史业绩(合同扫描件、业主评价等)\n"
- "- 报价信息(报价明细)\n"
- "- 设备资源(设备一览表)\n\n"
- "只输出 JSON 数组,不要额外文字。"
- )
- user = (
- "请列出投标公司需要提供的全部信息材料。\n\n"
- f"===== 招标文件关键章节 =====\n"
- f"{tender_text[:15000]}\n\n"
- f"===== 历史投标目录 =====\n"
- f"{bid_toc_text[:10000]}"
- )
- result = llm._call(system, user, max_tokens=8192,
- temperature=0.2,
- response_format={"type": "json_object"})
- parsed = json.loads(result)
- # 兼容数组或 {items: [...]} 两种返回格式
- if isinstance(parsed, list):
- return parsed
- for key in parsed:
- if isinstance(parsed[key], list):
- return parsed[key]
- return FALLBACK_ITEMS
- # ── CLI ──
- if __name__ == "__main__":
- import sys
- sys.stdout.reconfigure(encoding="utf-8")
- generate_template(output_path="output/phase3_company_template.json")
- with open("output/phase3_company_template.json", "r", encoding="utf-8") as f:
- data = json.load(f)
- items = data["投标公司信息收集表"]["信息项"]
- print(f"\n共 {len(items)} 项信息待补充:")
- for item in items:
- print(f" □ {item['名称']}")
|