提示词工程(GOT)把思维链推理过程图结构化

Graph of Thoughts(GOT)?

思维图(Graph of Thoughts)是一种结构化的表示方法,用于描述和组织模型的推理过程。它将信息和思维过程以图的形式表达,其中节点代表想法或信息,边代表它们之间的关系。

GOT 的核心思想

  1. 节点与边的表示

    • 节点:每个节点表示一个具体的思考或信息点,可以是一个事实、问题或推论。
    • :边表示节点之间的关系,能够反映出因果关系、逻辑连接等。
  2. 动态更新:GOT 可以根据新的信息动态更新,允许模型在生成过程中实时调整思路,增强灵活性。

  3. 推理路径:通过跟踪不同的思维路径,GOT 可以帮助模型探索多种可能的解决方案,而不仅仅是单一路径。

  4. 层次性与关联性:思维图强调信息的层次性和关联性,使得复杂问题的解析更加系统化。

相比于COT, TOT 思维图 Graph of Thoughts(GOT)是一种有助于增强模型推理能力和可解释性的方法,通过结构化的信息表示,促进多层次和动态的思考,能够有效应对复杂的自然语言处理任务

个人尝试GoT 框架

  • 节点生成:通过不同提示生成多个"思想"节点(初步分析、积极分析、消极分析、总结)。
  • 边构建:记录思想之间的依赖关系(例如从初始思想到分支思想)。
  • 评分:用一个简单的评分函数评估每个思想的质量。
  • 改进:选择得分最高的思想,进一步改进,形成反馈循环。

实际问题

问题:"一个商店的商品原价是100元,打八折后卖出,再加上10元的运费,问最终价格是多少?如果顾客有20元的优惠券,最终支付多少?"

问题特点

  1. 多步骤计算
    • 原价 100 元 → 打八折(0.8 × 100 = 80 元)。
    • 加上运费 10 元(80 + 10 = 90 元)。
    • 使用 20 元优惠券(90 - 20 = 70 元)。
    • 包含两个子问题:最终价格(90 元)和最终支付金额(70 元)。
  2. 条件依赖
    • 每一步计算依赖前一步结果(折扣 → 运费 → 优惠券)。
    • 顺序性强,但也可能有不同计算路径(例如先考虑优惠券再加运费)。
  3. 潜在复杂性
    • 需要理解"八折"(0.8)的含义。
    • 可能遗漏条件(例如运费是否打折?)。
    • 需要验证结果的合理性(例如负值检查)。
  4. 推理需求
    • 不仅需要计算,还需分解问题、验证过程、优化表达。
    • 适合用 GoT 的图结构探索多角度推理,而非单一线性过程。

传统的 Chain-of-Thought (CoT) 会按顺序线性推理,而 GoT 的优势在于:

  • 并行探索:分解问题、计算、验证可以同时进行。

  • 反馈循环:验证结果后改进答案。

  • 图结构:捕捉步骤间的依赖和多样性。

设计思路

基于问题特点,我设计了一个多层次的 GoT,目标是全面解决这个问题,同时展示 GoT 的复杂性和灵活性。设计分为四个层次,每层有特定目标和节点生成逻辑。

1. 初始层:问题陈述
  • 目标:记录原始问题,作为图的根节点。
  • 设计
    • 直接使用输入文本作为一个节点。
    • 不生成新内容,仅作为后续推理的起点。
  • 节点数量:1 个。
  • 作用:提供统一的输入基准。
2. 第一层:分解问题
  • 目标:将复杂问题拆分为可管理的子部分。
  • 设计
    • 使用三种提示生成分解节点:
      1. 计算步骤:列出折扣、运费、优惠券的计算顺序。
      2. 关键变量:识别 100 元、0.8、10 元、20 元等变量。
      3. 计算顺序:探索可能的计算路径(例如先优惠再加运费)。
    • 每个提示生成一个节点,从初始节点引出。
  • 节点数量:3 个。
  • 作用:为后续计算提供不同视角的基础。
3. 第二层:计算过程
  • 目标:基于分解结果执行具体计算。
  • 设计
    • 从第一层的每个节点引出三个计算节点:
      1. 折扣价格:计算 100 × 0.8 = 80 元。
      2. 加上运费:计算 80 + 10 = 90 元。
      3. 优惠券后价格:计算 90 - 20 = 70 元。
    • 每个第一层节点生成 3 个子节点,总计 9 个。
  • 节点数量:9 个。
  • 作用:执行核心计算,探索不同分解方式下的结果一致性。
4. 第三层:验证与优化
  • 目标:检查计算结果的正确性并改进过程。
  • 设计
    • 从第二层的每个节点引出三个验证节点:
      1. 验证正确性:检查计算是否符合问题逻辑(例如 70 元是否合理)。
      2. 优化步骤:简化计算过程(例如一步计算 100 × 0.8 + 10 - 20)。
      3. 检查遗漏:确认是否忽略条件(例如运费是否打折)。
    • 每个第二层节点生成 3 个子节点,总计 27 个。
  • 节点数量:27 个。
  • 作用:通过多角度验证提升答案可靠性。
5. 第四层:汇总最佳结果
  • 目标:整合所有分析,输出最终答案。
  • 设计
    • 从所有节点中选择得分最高的节点。
    • 使用提示"综合所有分析,给出最终答案"生成一个最终节点。
    • 从最佳节点引出边,形成闭环。
  • 节点数量:1 个。
  • 作用:提炼最优解,回答两个子问题(90 元和 70 元)。
6 评分机制
  • 目标:评估每个思想的质量,选择最佳路径。
  • 设计
    • 使用关键词匹配("原价"、"折扣"、"运费"、"优惠券"、"最终价格")+ 文本长度。
    • 关键词越多、内容越详细,得分越高。
  • 作用:模拟人类对答案完整性和准确性的判断。
7 图结构特点
  • 总节点数:1(初始)+ 3(分解)+ 9(计算)+ 27(验证)+ 1(汇总)= 41 个。
  • 边数量:3(初始到分解)+ 9(分解到计算)+ 27(计算到验证)+ 1(验证到汇总)= 40 条。
  • 复杂度:多层分支、反馈循环、非线性探索。

设计细节:

  1. 模型加载
    • 使用的本地模型 /opt/chenrui/qwq32b/base_model/qwq_32b
    • 设置 max_new_tokens=100,确保生成内容足够详细。
  2. 评分函数 score_thought
    • 检查关键词出现次数,模拟对问题关键元素的覆盖。

    • 加权文本长度,鼓励更详细的推理。

    • 示例:包含"折扣"和"运费"的节点得分高于只提"原价"的节点。

  3. 生成函数 generate_thought
    • 输入提示和前一节点文本,生成新思想。
    • 使用模型的生成能力模拟推理过程。
  4. 主函数 complex_graph_of_thoughts
    • 初始节点:直接存储输入文本。
    • 分解层:循环三种提示,生成 3 个节点,连接到初始节点。
    • 计算层:对每个分解节点循环三种计算提示,生成 9 个节点。
    • 验证层:对每个计算节点循环三种验证提示,生成 27 个节点。
    • 汇总层:选择最高分节点,生成最终答案。
    • 保存:将图结构存为 JSON。

完整代码

复制代码
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
import uuid
import json

# 模型路径
model_path = "/opt/chenrui/qwq32b/base_model/qwq_32b"

# 加载分词器和模型
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForCausalLM.from_pretrained(model_path)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
model.eval()


# 定义评分函数(基于合理性和完整性模拟评分)
def score_thought(thought_text, original_input):
    keywords = ["原价", "折扣", "运费", "优惠券", "最终价格"]
    score = sum(1 for keyword in keywords if keyword in thought_text)  # 关键词越多得分越高
    return score + len(thought_text) / 100  # 结合内容长度


# 生成思想节点
def generate_thought(input_text, prompt, max_new_tokens=100):
    full_prompt = f"{prompt}\n输入: {input_text}"
    inputs = tokenizer(full_prompt, return_tensors="pt").to(device)
    outputs = model.generate(**inputs, max_new_tokens=max_new_tokens, num_return_sequences=1)
    return tokenizer.decode(outputs[0], skip_special_tokens=True)


# 复杂 GoT 主逻辑
def complex_graph_of_thoughts(input_text):
    thought_graph = {"nodes": [], "edges": []}

    # 初始节点:问题陈述
    initial_node_id = str(uuid.uuid4())
    thought_graph["nodes"].append({
        "id": initial_node_id,
        "text": input_text,
        "score": score_thought(input_text, input_text)
    })

    # 第一层:分解问题
    decompose_prompts = [
        "将问题分解为计算步骤:",
        "识别问题的关键变量:",
        "列出可能的计算顺序:"
    ]
    for prompt in decompose_prompts:
        thought = generate_thought(input_text, prompt)
        node_id = str(uuid.uuid4())
        thought_graph["nodes"].append({"id": node_id, "text": thought, "score": score_thought(thought, input_text)})
        thought_graph["edges"].append({"from": initial_node_id, "to": node_id})

    # 第二层:基于分解结果计算
    compute_prompts = [
        "计算折扣后的价格:",
        "加上运费后的总价:",
        "考虑优惠券后的最终价格:"
    ]
    first_layer_nodes = [n["id"] for n in thought_graph["nodes"][1:4]]  # 取分解层节点
    for parent_id in first_layer_nodes:
        parent_text = next(n["text"] for n in thought_graph["nodes"] if n["id"] == parent_id)
        for prompt in compute_prompts:
            thought = generate_thought(parent_text, prompt)
            node_id = str(uuid.uuid4())
            thought_graph["nodes"].append({"id": node_id, "text": thought, "score": score_thought(thought, input_text)})
            thought_graph["edges"].append({"from": parent_id, "to": node_id})

    # 第三层:验证与优化
    verify_prompts = [
        "验证计算结果的正确性:",
        "优化计算过程以简化步骤:",
        "检查是否有遗漏条件:"
    ]
    second_layer_nodes = [n["id"] for n in thought_graph["nodes"][4:]]  # 取计算层节点
    for parent_id in second_layer_nodes:
        parent_text = next(n["text"] for n in thought_graph["nodes"] if n["id"] == parent_id)
        for prompt in verify_prompts:
            thought = generate_thought(parent_text, prompt)
            node_id = str(uuid.uuid4())
            thought_graph["nodes"].append({"id": node_id, "text": thought, "score": score_thought(thought, input_text)})
            thought_graph["edges"].append({"from": parent_id, "to": node_id})

    # 第四层:汇总最佳结果
    best_node = max(thought_graph["nodes"], key=lambda x: x["score"])
    final_prompt = "综合所有分析,给出最终答案:"
    final_thought = generate_thought(best_node["text"], final_prompt)
    final_node_id = str(uuid.uuid4())
    thought_graph["nodes"].append(
        {"id": final_node_id, "text": final_thought, "score": score_thought(final_thought, input_text)})
    thought_graph["edges"].append({"from": best_node["id"], "to": final_node_id})

    # 保存结果
    with open("complex_thought_graph.json", "w", encoding="utf-8") as f:
        json.dump(thought_graph, f, ensure_ascii=False, indent=2)

    return thought_graph


# 测试复杂问题
input_text = "一个商店的商品原价是100元,打八折后卖出,再加上10元的运费,问最终价格是多少?如果顾客有20元的优惠券,最终支付多少?"
result = complex_graph_of_thoughts(input_text)
print("复杂思想图已保存到 complex_thought_graph.json")

# 输出最佳思想
best_thought = max(result["nodes"], key=lambda x: x["score"])
print(f"最佳思想: {best_thought['text']} (得分: {best_thought['score']})")
  • 多层次结构
    • 初始层:问题陈述。
    • 第一层:分解问题(3个节点)。
    • 第二层:基于分解结果计算(每个第一层节点衍生3个计算节点,共9个)。
    • 第三层:验证与优化(每个第二层节点衍生3个验证节点,共27个)。
    • 第四层:汇总最佳结果(1个节点)。
    • 总计约 40 个节点,体现复杂性。
  • 非线性推理
    • 不同分支并行探索(分解、计算、验证)。
    • 依赖关系清晰(例如计算依赖分解,验证依赖计算)。
  • 评分机制
    • 改进评分函数,结合关键词匹配和内容长度,模拟对答案合理性的评估。

运行结果

最佳思想: 综合所有分析,给出最终答案:

输入: 检查是否有遗漏条件:

输入: 加上运费后的总价:

输入: 识别问题的关键变量:

输入: 一个商店的商品原价是100元,打八折后卖出,再加上10元的运费,问最终价格是多少?如果顾客有20元的优惠券,最终支付多少? 该问题的关键变量包括:

  1. **原价**:商品的原始价格为100元。

  2. **折扣率**:打八折,即商品价格的80%。

  3. **运费**:额外收取的10元费用。

  4. **优惠券**:顾客可使用的20元优惠券。

需要分步骤计算:

  • 首先计算折扣后的商品价格:100元 × 0.8 = 80元。

  • 然后加上运费:80元 + 10元 = 90元。

  • 最后应用优惠券:90元 - 20元 = 70元。

因此,最终支付金额为70元。需要注意优惠券的使用顺序是否会影响结果,但通常优惠券在总价基础上抵扣,因此上述计算合理。

如果问题中优惠券的使用条件或顺序有特别说明(例如是否在运费前使用),需要根据具体条件调整计算步骤。但根据常规情况,上述解答是正确的。 您的分析基本正确,但需要确认以下几点以确保没有遗漏条件:

1. **优惠券的使用条件**

  • 优惠券是否仅适用于商品价格(折扣后价格),还是也包括运费?

  • 如果优惠券不能用于运费,那么计算方式可能不同:

  • 商品折扣后价格:80元

  • 运费:10元(不可用优惠券)

  • 优惠券抵扣商品部分:80元 - 20元 = 60元

  • 最终总价:60元(商品) + 10元(运费) = **70元**(结果不变,但逻辑不同)。

2. **优惠券的使用顺序**

  • 是否有规定优惠券必须在运费前使用?通常优惠券是抵扣 (得分: 12.51)

生成complex_thought_graph.json

GOT 可视化

将 complex_thought_graph.json 转为图片

复制代码
import networkx as nx
import matplotlib.pyplot as plt
import json

# 设置支持中文的字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows
plt.rcParams['axes.unicode_minus'] = False

# 读取 JSON 数据
with open("complex_thought_graph.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# 创建有向图
G = nx.DiGraph()

# 添加节点
for node in data["nodes"]:
    label = f"{node['text'][:10]}...\nScore: {node['score']:.2f}"
    G.add_node(node["id"], label=label)

# 添加边
for edge in data["edges"]:
    G.add_edge(edge["from"], edge["to"])

# 设置布局
pos = nx.spring_layout(G)

# 绘制并保存
plt.figure(figsize=(20, 15))  # 增大画布以容纳更多节点
nx.draw(G, pos, with_labels=True, labels=nx.get_node_attributes(G, "label"),
        node_size=2000, node_color="lightblue", font_size=6, font_weight="bold",
        arrows=True, arrowstyle="->", arrowsize=15)

plt.title("Complex Graph of Thoughts Visualization", fontsize=16)
plt.savefig("complex_thought_graph.png", dpi=300, bbox_inches="tight")
print("图已保存为 complex_thought_graph.png")
  • 节点数量:约40个节点。
  • 推理深度:4层结构,包含分解、计算、验证和汇总。
  • 多样性:多个分支探索不同角度(例如计算顺序、验证方法)。
  • 结果优化:通过评分选择最佳路径并汇总。

节点太多了看不清了,用ds.js 渲染个拖拉拽的html

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Interactive Graph of Thoughts</title>
    <style>
        html, body {
            margin: 0;
            padding: 0;
            height: 100vh;
            overflow: hidden;
        }
        svg {
            width: 100%;
            height: 100%;
            display: block;
        }
        .node circle {
            fill: lightblue;
            stroke: #333;
            stroke-width: 1.5px;
        }
        .node text {
            font-size: 12px;
            pointer-events: none;
        }
        .link {
            stroke: #999;
            stroke-opacity: 0.6;
        }
        #error {
            color: red;
            font-family: Arial, sans-serif;
            position: absolute;
            top: 10px;
            left: 10px;
        }
    </style>
</head>
<body>
    <svg></svg>
    <div id="error"></div>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script>
        // 设置 SVG 尺寸
        const svg = d3.select("svg");
        let width = window.innerWidth;
        let height = window.innerHeight;

        // 读取 JSON 文件
        fetch('./complex_thought_graph.json')
            .then(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! Status: ${response.status}`);
                }
                return response.json();
            })
            .then(data => {
                if (!data.nodes || !data.edges) {
                    throw new Error("Invalid JSON format: missing 'nodes' or 'edges'");
                }

                // 准备数据
                const nodes = data.nodes.map(node => ({
                    id: node.id,
                    text: node.text.slice(0, 10) + '...',
                    score: node.score
                }));
                const links = data.edges.map(edge => ({
                    source: edge.from,
                    target: edge.to
                }));

                // 初始化力导向图
                const simulation = d3.forceSimulation(nodes)
                    .force("link", d3.forceLink(links).id(d => d.id).distance(100))
                    .force("charge", d3.forceManyBody().strength(-200))
                    .force("center", d3.forceCenter(width / 2, height / 2));

                // 绘制边
                const link = svg.append("g")
                    .attr("class", "links")
                    .selectAll("line")
                    .data(links)
                    .enter().append("line")
                    .attr("class", "link");

                // 绘制节点
                const node = svg.append("g")
                    .attr("class", "nodes")
                    .selectAll("g")
                    .data(nodes)
                    .enter().append("g")
                    .attr("class", "node")
                    .call(d3.drag()
                        .on("start", dragstarted)
                        .on("drag", dragged)
                        .on("end", dragended));

                node.append("circle")
                    .attr("r", 10);

                node.append("text")
                    .attr("dx", 12)
                    .attr("dy", ".35em")
                    .text(d => `${d.text} (Score: ${d.score.toFixed(2)})`);

                // 力仿真更新
                simulation.on("tick", () => {
                    link
                        .attr("x1", d => d.source.x)
                        .attr("y1", d => d.source.y)
                        .attr("x2", d => d.target.x)
                        .attr("y2", d => d.target.y);
                    node
                        .attr("transform", d => `translate(${d.x},${d.y})`);
                });

                // 拖拽函数
                function dragstarted(event, d) {
                    if (!event.active) simulation.alphaTarget(0.3).restart();
                    d.fx = d.x;
                    d.fy = d.y;
                }

                function dragged(event, d) {
                    d.fx = event.x;
                    d.fy = event.y;
                }

                function dragended(event, d) {
                    if (!event.active) simulation.alphaTarget(0);
                    d.fx = null;
                    d.fy = null;
                }

                // 窗口大小调整
                window.addEventListener('resize', () => {
                    width = window.innerWidth;
                    height = window.innerHeight;
                    svg.attr("width", width).attr("height", height);
                    simulation.force("center", d3.forceCenter(width / 2, height / 2));
                    simulation.alpha(1).restart();
                });
            })
            .catch(error => {
                console.error('Error loading JSON:', error);
                d3.select("#error").text(`Error loading JSON: ${error.message}`);
            });
    </script>
</body>
</html>

python -m http.server 8000

查看下GOT结构

相关推荐
大鹏的NLP博客1 年前
NLP中 大语言模型LLM中的思维链 Chain-of-Thought(CoT) GoT
自然语言处理·llm·cot·got
江小皮不皮2 年前
大模型之Prompt研究和技巧
人工智能·chatgpt·prompt·cot·got·tot·few-shot
凉、介2 年前
动态链接那些事
linux·链接·got·ld·装载
酿久诗2 年前
《Graph of Thoughts: Solving Elaborate Problems with Large Language Models》中文翻译
人工智能·语言模型·自然语言处理·got