标书智能体测评:提纲生成代码与提示词对比

2026-06-15阅读 0热度 0
智能体

使用Python与React开发一款开源的AI标书撰写智能体,确实具备实际落地价值。

本篇为系列第二期,重点讲解如何基于已解析的项目概述与技术评分需求,生成一份切实可用的投标文件提纲。

一份优质标书,提纲就是骨架。要让AI自动生成合格的提纲,必须攻克三个核心难点:

  • 结构化输出——提纲层级若模糊,后续正文生成极易偏离方向,必须预先定义清晰的嵌套结构。
  • 输出长度限制——标书动辄数十万字,提纲本身也很长。即使大模型宣称支持百万级上下文,实际有效输出通常仅两千字左右,长提纲根本无法一次性生成。
  • 可编辑性——AI再强大,也无法一次性满足所有定制需求。提纲必须支持手动调整,且修改后不能破坏原有的层级关系。

下面逐一拆解这些挑战。

一、短标书 + 高能AI模型

若标书篇幅较短(例如三五万字),且使用像 glm-4.5doubao-seed-1-6 这类可连续输出约八千字的模型,方案只需一个递归JSON结构即可。

JSON结构

{
  "outline": [
    {
      "id": "1",
      "title": "",
      "description": "",
      "children": [
        {
          "id": "1.1",
          "title": "",
          "description": "",
          "children":[
              {
                "id": "1.1.1",
                "title": "",
                "description": ""
              }
          ]
        }
      ]
    }
  ]
}

提示词

SystemPrompt

你是一位专业的标书撰写专家。请根据提供的项目概述和技术评分要求,生成技术标部分的目录结构。

要求:
1. 目录结构需完整覆盖技术标所有必要章节
2. 章节标题需专业、精准,符合投标文件编制规范
3. 一级目录名称必须与技术评分要求中的章节名称保持一致;若评分要求中未提供章节名称,则依据其内容自行拟定
4. 目录层级设为三级
5. 输出标准JSON格式,包含章节编号、标题、描述及子章节
6. 仅输出JSON结果,禁止附带任何其他文字

JSON格式要求:
{
  "outline": [
    {
      "id": "1",
      "title": "",
      "description": "",
      "children": [
        {
          "id": "1.1",
          "title": "",
          "description": "",
          "children":[
              {
                "id": "1.1.1",
                "title": "",
                "description": ""
              }
          ]
        }
      ]
    }
  ]
}

UserPrompt

请根据以下项目信息生成标书目录结构:

项目概述:
{overview}

技术评分要求:
{requirements}

请生成完整的技术标目录结构,确保覆盖所有技术评分要点。

二、长标书 + 普通AI模型

如果只有 glm-4-air 这类价格低廉但能力有限的模型,却要生成数十万字标书所需的超长提纲,则需要换一种策略。

瓶颈很明显:

  1. 上下文窗口短,最多输出一千五百字左右
  2. 输出稳定性差,JSON这类结构化格式频繁出错

应对思路:

  1. 先让AI生成一级目录(必须与技术评分要求一一对应)
  2. 再逐条遍历一级目录,分别生成二级和三级目录(多任务并发,需保证各任务生成的目录互不重复)
  3. 校验返回的JSON格式是否合法
  4. 最终拼装为完整目录

这套流程理论上可以无限扩展提纲长度。

生成一级标题

SystemPrompt

### 角色
你是专业的标书编写专家,擅长根据项目需求编写标书。

### 任务
1. 根据给定的项目概述(overview)和评分要求(requirements),撰写技术标部分的一级提纲

### 说明
2. 只设计一级标题,数量需与"评分要求"逐项对应
3. 一级标题名称需进行适当修改,不得直接复制"评分要求"中的原文

### Output Format in JSON
{
    "rating_item":"原评分项",
    "new_title":"根据评分项修改的标题"
}

UserPrompt

### 项目信息


{overview}



{requirements}



直接返回json,不要任何额外说明或格式标记

生成二级标题

为了提高结果稳定性,不让AI自行构建JSON框架,而是提前用代码搭好骨架,仅让AI填充内容。

拼接JSON框架
此处额外引入 nodes_distribution 参数,目的是让二三级目录的数量差异化,随机挑选两个重点章节增加层级深度,更贴近真实标书。具体实现细节可直接查看源码。

def generate_one_outline_json_by_level1(level1_title: str, level1_index: int, nodes_distribution: Dict) -> Dict:
    # 获取当前一级节点下的二级节点数量和叶子节点分配
    level2_count = nodes_distribution['level2_nodes'][level1_index - 1]
    leaf_distribution = nodes_distribution['leaf_per_level2'][level1_index - 1]
    
    # 创建一级节点
    level1_node = {
        "id":f"{level1_index}",
        "title": level1_title,
        "description": "",
        "children": []
    }
    
    # 创建二级节点
    for j in range(level2_count):
        level2_node = {
            "id":f"{level1_index}.{j+1}",
            "title": "",  # 二级标题留空
            "description": "",
            "children": []
        }
        
        # 创建三级节点(叶子节点)
        leaf_count = leaf_distribution[j]
        for k in range(leaf_count):
            level2_node["children"].append({
                "id":f"{level1_index}.{j+1}.{k+1}",
                "title": "",  # 三级标题留空
                "description": ""
            })
        
        level1_node["children"].append(level2_node)
    
    return level1_node

在生成某个章节的二三级时,需将其他章节的标题也传给AI作为参考,避免内容重复。

other_outline = "\n".join([f"{j+1}. {node['new_title']}" 
                    for j, node in enumerate(level_l1) 
                    if j!= i])

SystemPrompt
(注:json_outline 为前面搭好的JSON框架)

### 角色
你是专业的标书编写专家,擅长根据项目需求编写标书。

### 任务
1. 根据提供的项目概述(overview)、评分要求(requirements)补全标书提纲的二三级目录

### 说明
2. 你会获得一段json,这是提纲的其中一个章节,请在原结构上补全标题(title)和描述(description)
3. 二级标题基于一级标题撰写,三级标题基于二级标题撰写
4. 补全内容需参考项目概述(overview)、评分要求(requirements)等信息
5. 你还会收到其他章节的标题(other_outline),需确保本章节内容不与其他章节重叠

### 注意事项
在原json上补全信息,禁止修改json结构,禁止修改一级标题

### Output Format in JSON
{json_outline}

UserPrompt

### 项目信息


{overview}



{requirements}



{other_outline}



直接返回json,不要任何额外说明或格式标记

校验生成结果与传入框架是否一致

import json
def check_json(json_str: str, schema: str | dict) -> tuple[bool, str]:
    """
    根据模板 JSON 校验目标字符串的格式是否符合要求
    
    Args:
        json_str: 要校验的 JSON 字符串
        schema: 模板 JSON 字符串或字典对象,用于定义预期的数据结构
        
    Returns:
        tuple[bool, str]: (是否验证通过, 错误信息)
        如果验证通过返回 (True, ""),否则返回 (False, 错误原因)
    """
    try:
        # 解析输入的 JSON 字符串
        try:
            data = json.loads(json_str)
        except json.JSONDecodeError as e:
            return False, f"JSON 解析错误: {str(e)}"
        
        # 处理 schema 参数
        try:
            if isinstance(schema, str):
                schema = json.loads(schema)
            elif not isinstance(schema, dict):
                return False, "schema 必须是 JSON 字符串或字典对象"
        except json.JSONDecodeError as e:
            return False, f"schema 解析错误: {str(e)}"
        
        def check_structure(target, template, path=""):
            # 处理数字类型(int 和 float 可以互换)
            if isinstance(template, (int, float)) and isinstance(target, (int, float)):
                return True, ""
                
            # 检查基本数据类型
            if type(template) != type(target) and not (isinstance(template, (int, float)) and isinstance(target, (int, float))):
                return False, f"路径 '{path}' 的类型不匹配: 期望 {type(template).__name__}, 实际 {type(target).__name__}"
                
            # 如果是列表类型
            if isinstance(template, list):
                if not template:  # 如果模板列表为空,则允许任何列表
                    return True, ""
                if not target:  # 如果目标列表为空,但模板不为空
                    return False, f"路径 '{path}' 的列表为空,但期望有内容"
                    
                # 检查列表中的每个元素是否符合模板中第一个元素的格式
                template_item = template[0]
                for i, item in enumerate(target):
                    is_valid, error = check_structure(item, template_item, f"{path}[{i}]")
                    if not is_valid:
                        return False, error
                return True, ""
                
            # 如果是字典类型
            elif isinstance(template, dict):
                # 检查所有必需的键是否存在,并且值的类型是否正确
                for key in template:
                    if key not in target:
                        return False, f"路径 '{path}' 缺少必需的键 '{key}'"
                    is_valid, error = check_structure(target[key], template[key], f"{path}.{key}")
                    if not is_valid:
                        return False, error
                return True, ""
                
            # 对于其他基本类型,返回 True
            return True, ""
                
        is_valid, error = check_structure(data, schema)
        return is_valid, error if not is_valid else ""
        
    except Exception as e:
        return False, f"未预期的错误: {str(e)}"

实际运行中,为每个生成任务设置3次重试,若校验失败则重新执行,可显著提升成功率。

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

相关阅读

更多
欢迎回来 登录或注册后,可保存提示词和历史记录
登录后可同步收藏、历史记录和常用模板
注册即表示同意服务条款与隐私政策