outline_prompts.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. """目录生成相关提示词。"""
  2. from typing import Any, Dict, List
  3. def _build_outline_system_prompt() -> str:
  4. """构建目录生成的共享系统提示词。"""
  5. return """你是一个专业的标书编写专家。根据提供的项目概述和技术评分要求,生成投标文件中技术标部分的目录结构。
  6. 如果用户提供了自己编写的目录,你要保证目录满足技术评分要求,并充分结合用户自己编写的目录。
  7. 要求:
  8. 1. 目录结构要全面覆盖技术标的所有必要章节
  9. 2. 章节名称要专业、准确,符合投标文件规范
  10. 3. 一级目录名称要与技术评分要求中的章节名称一致;如果技术评分要求中没有明确章节名称,则结合内容总结一级目录名称
  11. 4. 一共包括三级目录
  12. 5. 返回标准 JSON 格式,包含章节编号、标题、描述和子章节
  13. 6. 除了 JSON 结果外,不要输出任何其他内容
  14. JSON 格式要求:
  15. {
  16. "outline": [
  17. {
  18. "id": "1",
  19. "title": "",
  20. "description": "",
  21. "children": [
  22. {
  23. "id": "1.1",
  24. "title": "",
  25. "description": "",
  26. "children": [
  27. {
  28. "id": "1.1.1",
  29. "title": "",
  30. "description": ""
  31. }
  32. ]
  33. }
  34. ]
  35. }
  36. ]
  37. }
  38. """
  39. def _build_top_level_outline_system_prompt() -> str:
  40. """构建仅生成一级目录的系统提示词。"""
  41. return """你是一个专业的标书编写专家。根据提供的项目概述和技术评分要求,生成投标文件中技术标部分的一级目录结构。
  42. 如果用户提供了自己编写的目录,你要保证一级目录满足技术评分要求,并充分结合用户自己编写的目录。
  43. 要求:
  44. 1. 只生成一级目录,不要生成二级和三级目录
  45. 2. 一级目录名称要专业、准确,符合投标文件规范
  46. 3. 一级目录名称要尽量与技术评分要求中的章节名称一致;如果技术评分要求中没有明确章节名称,则结合内容总结一级目录名称
  47. 4. 返回标准 JSON 格式,使用 outline 字段,每个一级目录必须包含 id、title、description
  48. 5. 除了 JSON 结果外,不要输出任何其他内容
  49. JSON 格式要求:
  50. {
  51. "outline": [
  52. {
  53. "id": "1",
  54. "title": "",
  55. "description": ""
  56. }
  57. ]
  58. }
  59. """
  60. def _format_revision_suggestions(suggestions: list[str] | None) -> str:
  61. """格式化目录修正建议。"""
  62. if not suggestions:
  63. return ""
  64. suggestion_lines = [
  65. f"{index}. {item}" for index, item in enumerate(suggestions, start=1)
  66. ]
  67. return "\n\n本轮修正建议:\n" + "\n".join(suggestion_lines)
  68. def generate_outline_prompt(
  69. overview: str,
  70. requirements: str,
  71. suggestions: list[str] | None = None,
  72. ) -> List[Dict[str, str]]:
  73. """生成标准目录的提示词。"""
  74. return [
  75. {"role": "system", "content": _build_outline_system_prompt()},
  76. {"role": "user", "content": f"项目概述:\n{overview}"},
  77. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  78. {
  79. "role": "user",
  80. "content": "请生成完整的技术标目录结构,确保覆盖所有技术评分要点。"
  81. + _format_revision_suggestions(suggestions),
  82. },
  83. ]
  84. def generate_outline_with_old_prompt(
  85. overview: str,
  86. requirements: str,
  87. old_outline: str | None,
  88. suggestions: list[str] | None = None,
  89. ) -> List[Dict[str, str]]:
  90. """生成基于旧目录扩写的提示词。"""
  91. return [
  92. {"role": "system", "content": _build_outline_system_prompt()},
  93. {"role": "user", "content": f"项目概述:\n{overview}"},
  94. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  95. {"role": "user", "content": f"用户自己编写的目录:\n{old_outline or ''}"},
  96. {
  97. "role": "user",
  98. "content": "请在满足技术评分要求的前提下,充分结合用户自己编写的目录,生成完整的技术标目录结构。"
  99. + _format_revision_suggestions(suggestions),
  100. },
  101. ]
  102. def generate_top_level_outline_prompt(
  103. overview: str,
  104. requirements: str,
  105. suggestions: list[str] | None = None,
  106. ) -> List[Dict[str, str]]:
  107. """生成仅包含一级目录的提示词。"""
  108. return [
  109. {"role": "system", "content": _build_top_level_outline_system_prompt()},
  110. {"role": "user", "content": f"项目概述:\n{overview}"},
  111. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  112. {
  113. "role": "user",
  114. "content": "请仅生成一级目录列表,不要生成二级和三级目录。返回的 JSON 仍然使用 outline 字段,每个一级目录都必须包含 id、title、description。"
  115. + _format_revision_suggestions(suggestions),
  116. },
  117. ]
  118. def generate_top_level_outline_with_old_prompt(
  119. overview: str,
  120. requirements: str,
  121. old_outline: str | None,
  122. suggestions: list[str] | None = None,
  123. ) -> List[Dict[str, str]]:
  124. """生成结合旧目录的一级目录提示词。"""
  125. return [
  126. {"role": "system", "content": _build_top_level_outline_system_prompt()},
  127. {"role": "user", "content": f"项目概述:\n{overview}"},
  128. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  129. {"role": "user", "content": f"用户自己编写的目录:\n{old_outline or ''}"},
  130. {
  131. "role": "user",
  132. "content": "请在满足技术评分要求的前提下,充分结合用户自己编写的目录,仅生成一级目录,不要生成二级和三级目录。返回的 JSON 使用 outline 字段,每个一级目录都必须包含 id、title、description。"
  133. + _format_revision_suggestions(suggestions),
  134. },
  135. ]
  136. def extract_requirement_groups_messages(
  137. requirements: str,
  138. suggestions: list[str] | None = None,
  139. ) -> List[Dict[str, str]]:
  140. """提取适合作为一级目录的技术评分大类。"""
  141. system_prompt = """你是一个专业的招标文件分析专家。请从技术评分要求中提取适合作为技术标一级目录的评分大类。
  142. 要求:
  143. 1. 只提取技术评分大类,不要提取商务、报价、资质、售后服务等非技术类条目
  144. 2. 每个大类都必须适合作为技术标一级目录标题,标题要专业、简洁、完整
  145. 3. 同一大类下的细项、子项、分值说明、评分标准要归入 detail_points,不要拆成多个一级目录
  146. 4. requirement_id 必须唯一,使用 R1、R2、R3 这种格式
  147. 5. description 需要概括该大类关注的核心内容
  148. 6. detail_points 中保留该大类下的关键评分细项,使用简洁短句
  149. 7. 只返回 JSON,格式必须为 {"groups": [...]},不要输出任何其他内容
  150. JSON 格式要求:
  151. {
  152. "groups": [
  153. {
  154. "requirement_id": "R1",
  155. "title": "",
  156. "description": "",
  157. "detail_points": ["", ""]
  158. }
  159. ]
  160. }
  161. """
  162. return [
  163. {"role": "system", "content": system_prompt},
  164. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  165. {
  166. "role": "user",
  167. "content": "请提取所有适合作为技术标一级目录的技术评分大类,保持顺序稳定,并把每个大类下的评分细项归入 detail_points。"
  168. + _format_revision_suggestions(suggestions),
  169. },
  170. ]
  171. def generate_aligned_children_outline_prompt(
  172. overview: str,
  173. requirements: str,
  174. parent_item: Dict[str, Any],
  175. requirement_group: Dict[str, Any],
  176. suggestions: list[str] | None = None,
  177. ) -> List[Dict[str, str]]:
  178. """围绕指定技术评分大类生成二三级目录。"""
  179. parent_id = parent_item.get("id", "1")
  180. parent_title = parent_item.get("title", "未命名一级目录")
  181. parent_description = parent_item.get("description", "")
  182. requirement_id = requirement_group.get("requirement_id", "R1")
  183. detail_points = requirement_group.get("detail_points") or []
  184. detail_lines = "\n".join(
  185. f"- {item}" for item in detail_points if isinstance(item, str) and item.strip()
  186. )
  187. system_prompt = """你是一个专业的标书编写专家。请围绕指定的技术评分大类,为已经固定好的一级目录生成二级和三级目录。
  188. 要求:
  189. 1. 一级目录标题和顺序已经固定,不能修改、重命名、合并或删除一级目录
  190. 2. 只输出当前一级目录下的二级和三级目录,不要重复输出一级目录本身
  191. 3. 二级和三级目录要覆盖当前技术评分大类及其细项,不能越界写入其他评分大类内容
  192. 4. 返回标准 JSON,格式为 {"children": [...]},children 中只能包含当前一级目录的直接子目录
  193. 5. 每个节点必须包含 id、title、description,三级目录继续使用 children 字段
  194. 6. 章节编号必须以给定的一级目录编号为前缀,例如父级是 2,则二级目录编号从 2.1 开始,三级目录编号从 2.1.1 开始
  195. 7. 除了 JSON 结果外,不要输出任何其他内容
  196. """
  197. detail_content = detail_lines or "- 未提供明确细项,请根据评分大类描述合理展开"
  198. return [
  199. {"role": "system", "content": system_prompt},
  200. {"role": "user", "content": f"项目概述:\n{overview}"},
  201. {"role": "user", "content": f"技术评分要求原文:\n{requirements}"},
  202. {
  203. "role": "user",
  204. "content": f"当前固定一级目录:\n编号:{parent_id}\n标题:{parent_title}\n描述:{parent_description}",
  205. },
  206. {
  207. "role": "user",
  208. "content": f"当前对应的技术评分大类:\nrequirement_id:{requirement_id}\n标题:{requirement_group.get('title', '')}\n描述:{requirement_group.get('description', '')}\n细项:\n{detail_content}",
  209. },
  210. {
  211. "role": "user",
  212. "content": '请仅生成该一级目录下的二级、三级目录,一级目录标题必须保持为当前给定标题,返回格式必须是 {"children": [...]}。'
  213. + _format_revision_suggestions(suggestions),
  214. },
  215. ]
  216. def generate_aligned_children_outline_with_old_prompt(
  217. overview: str,
  218. requirements: str,
  219. parent_item: Dict[str, Any],
  220. requirement_group: Dict[str, Any],
  221. old_outline: str | None,
  222. suggestions: list[str] | None = None,
  223. ) -> List[Dict[str, str]]:
  224. """结合旧目录参考,为指定评分大类生成二三级目录。"""
  225. messages = generate_aligned_children_outline_prompt(
  226. overview=overview,
  227. requirements=requirements,
  228. parent_item=parent_item,
  229. requirement_group=requirement_group,
  230. suggestions=suggestions,
  231. )
  232. messages.insert(
  233. 5, {"role": "user", "content": f"用户自己编写的目录参考:\n{old_outline or ''}"}
  234. )
  235. messages[-1] = {
  236. "role": "user",
  237. "content": '请在覆盖当前技术评分大类细项的前提下,参考用户目录优化当前一级目录下的二级、三级目录,但不得修改当前一级目录标题,返回格式必须是 {"children": [...]}。'
  238. + _format_revision_suggestions(suggestions),
  239. }
  240. return messages
  241. def generate_children_outline_prompt(
  242. overview: str,
  243. requirements: str,
  244. parent_item: Dict[str, Any],
  245. suggestions: list[str] | None = None,
  246. ) -> List[Dict[str, str]]:
  247. """为指定一级目录生成二三级目录。"""
  248. parent_id = parent_item.get("id", "1")
  249. parent_title = parent_item.get("title", "未命名一级目录")
  250. parent_description = parent_item.get("description", "")
  251. system_prompt = """你是一个专业的标书编写专家。请围绕指定的一级目录,生成其下属的二级目录和三级目录。
  252. 要求:
  253. 1. 只输出当前一级目录下的二级和三级目录,不要重复输出一级目录本身
  254. 2. 返回标准 JSON,格式为 {"children": [...]}
  255. 3. children 中只能包含当前一级目录的直接子目录,每个节点必须包含 id、title、description
  256. 4. 二级目录下如有三级目录,同样使用 children 字段
  257. 5. 章节编号必须以给定的一级目录编号为前缀,例如父级是 2,则二级目录编号从 2.1 开始,三级目录编号从 2.1.1 开始
  258. 6. 除了 JSON 结果外,不要输出任何其他内容
  259. """
  260. return [
  261. {"role": "system", "content": system_prompt},
  262. {"role": "user", "content": f"项目概述:\n{overview}"},
  263. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  264. {
  265. "role": "user",
  266. "content": f"当前一级目录:\n编号:{parent_id}\n标题:{parent_title}\n描述:{parent_description}",
  267. },
  268. {
  269. "role": "user",
  270. "content": '请仅生成该一级目录下的二级、三级目录,返回格式必须是 {"children": [...]}。'
  271. + _format_revision_suggestions(suggestions),
  272. },
  273. ]
  274. def generate_children_outline_with_old_prompt(
  275. overview: str,
  276. requirements: str,
  277. parent_item: Dict[str, Any],
  278. old_outline: str | None,
  279. suggestions: list[str] | None = None,
  280. ) -> List[Dict[str, str]]:
  281. """为指定一级目录生成二三级目录,并结合旧目录参考。"""
  282. messages = generate_children_outline_prompt(
  283. overview=overview,
  284. requirements=requirements,
  285. parent_item=parent_item,
  286. suggestions=suggestions,
  287. )
  288. messages.insert(
  289. 4, {"role": "user", "content": f"用户自己编写的目录:\n{old_outline or ''}"}
  290. )
  291. messages[-1] = {
  292. "role": "user",
  293. "content": '请在满足技术评分要求的前提下,充分结合用户自己编写的目录,仅生成该一级目录下的二级、三级目录,返回格式必须是 {"children": [...]}。'
  294. + _format_revision_suggestions(suggestions),
  295. }
  296. return messages
  297. def review_outline_messages(
  298. overview: str,
  299. requirements: str,
  300. outline_json: str,
  301. ) -> List[Dict[str, str]]:
  302. """构建目录审核消息。"""
  303. system_prompt = """你是一个严格的招标文件目录审核专家。请审核目录是否符合项目概述和技术评分要求。
  304. 要求:
  305. 1. 重点检查目录是否完整覆盖技术评分要点
  306. 2. 检查一级目录名称是否专业、准确,是否尽量与评分项原文保持一致
  307. 3. 检查目录层级是否清晰,是否达到三级目录要求,是否存在明显遗漏、错位、重复或不合理章节
  308. 4. 只返回 JSON,格式为:{"passed": true, "suggestions": []}
  309. 5. 若不通过,suggestions 中必须给出具体、可执行的修改建议
  310. 6. 除了 JSON 外,不要输出任何其他内容
  311. """
  312. return [
  313. {"role": "system", "content": system_prompt},
  314. {"role": "user", "content": f"项目概述:\n{overview}"},
  315. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  316. {"role": "user", "content": f"待审核目录 JSON:\n{outline_json}"},
  317. {
  318. "role": "user",
  319. "content": "请判断该目录是否满足要求。若满足则返回 passed=true;若不满足则返回 passed=false,并给出具体修改建议。",
  320. },
  321. ]
  322. def review_aligned_outline_messages(
  323. overview: str,
  324. requirements: str,
  325. groups_json: str,
  326. outline_json: str,
  327. ) -> List[Dict[str, str]]:
  328. """构建一一对应模式的目录审核消息。"""
  329. system_prompt = """你是一个严格的招标文件目录审核专家。请审核目录是否与技术评分大类一一对应,并判断二三级目录是否覆盖各评分大类的细项。
  330. 要求:
  331. 1. 一级目录必须与提供的技术评分大类一一对应,数量一致、顺序一致、标题必须完全一致
  332. 2. 不允许缺失技术评分大类,也不允许新增、合并、改写一级目录
  333. 3. 二级和三级目录要围绕各自对应的技术评分大类与细项展开,避免错位、遗漏和明显重复
  334. 4. 检查完整目录是否层级清晰,整体是否达到三级目录要求
  335. 5. 只返回 JSON,格式为:{"passed": true, "suggestions": []}
  336. 6. 若不通过,suggestions 中必须给出具体、可执行的修改建议,重点说明哪个评分大类覆盖不足或结构不合理
  337. 7. 除了 JSON 外,不要输出任何其他内容
  338. """
  339. return [
  340. {"role": "system", "content": system_prompt},
  341. {"role": "user", "content": f"项目概述:\n{overview}"},
  342. {"role": "user", "content": f"技术评分要求:\n{requirements}"},
  343. {"role": "user", "content": f"技术评分大类 JSON:\n{groups_json}"},
  344. {"role": "user", "content": f"待审核目录 JSON:\n{outline_json}"},
  345. {
  346. "role": "user",
  347. "content": "请判断该目录是否满足一一对应要求。若满足则返回 passed=true;若不满足则返回 passed=false,并给出具体修改建议。",
  348. },
  349. ]