基于 LangGraph 搭建反思迭代 Agent:实现文章自动优化

一、前言

在大模型应用落地中,单次生成的内容常常存在逻辑松散、表达生硬、内容不达标的问题。想要让 AI 产出高质量文本,单纯依靠提示词优化远远不够。

今天给大家分享一套基于 LangGraph 实现的反思迭代智能体(Agent) ,模仿人类 "写作→自查问题→修改优化" 的思考流程,让大模型自动循环打磨内容,直到质量达标或达到迭代上限。本文以通义千问大模型为例,完整实现生成 - 评估 - 反思 - 重写的闭环工作流。

二、整体设计思路

整个 Agent 核心是三段式循环工作流,搭配条件判断实现流程终止,完全复刻人工写作反思逻辑:

  1. 内容生成:首次产出初稿,后续根据反思建议迭代改写;
  2. 质量评估:从内容完整度、逻辑、语言三个维度,对文章打出 0~1 的量化分数;
  3. 反思优化:根据低分定位文章问题,输出具体修改建议;
  4. 条件路由:设置双重终止规则,分数≥0.9 或 达到最大迭代次数,自动停止循环。

整体流程拓扑: 启动 → 生成文稿 → 质量评估 → 【条件判断】

  • 达标 / 迭代用尽 → 结束流程
  • 不达标 → 反思提建议 → 回到生成环节,循环优化

三、技术栈说明

  • LangGraph:LangChain 生态下的图编排框架,用于搭建有状态、可循环、带条件分支的 Agent 工作流;
  • 通义千问(ChatTongyi):作为核心大模型,承担生成、评估、反思三大任务;
  • python-dotenv:管理密钥等环境变量,保障接口安全;
  • TypedDict:定义全局状态结构体,统一流转数据。

四、核心代码解析

1. 环境与状态定义

首先加载环境变量、初始化大模型,并使用TypedDict定义全局状态。状态是 LangGraph 的核心,所有节点共享同一份状态数据,实现信息流转。

python

运行

复制代码
import os
from typing import TypedDict
from dotenv import load_dotenv
from langchain_community.chat_models import ChatTongyi
from langgraph.constants import START, END
from langgraph.graph import StateGraph

# 加载环境变量
load_dotenv()
# 初始化通义千问大模型
llm = ChatTongyi(
    model="qwen-max",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    temperature=0.7
)

# 定义全局状态:整个流程共享的数据
class ReflectionState(TypedDict):
    task:str          # 原始写作任务
    draft:str         # 文章草稿
    quality_score:float  # 质量评分
    reflection:str    # 反思修改建议
    iteration:int     # 当前迭代次数
    max_iterations:int # 最大迭代上限

2. 三大核心节点

LangGraph 中节点对应独立执行单元,我们拆分出三个功能节点,各司其职:

(1)文稿生成节点 generate_draft

区分首次生成迭代改写两种场景:迭代次数为 0 时直接根据任务写初稿;非 0 则结合上一轮反思建议重写内容。

python

运行

复制代码
def generate_draft(state: ReflectionState):
    task = state["task"]
    iteration=state["iteration"]
    if iteration==0:
        prompt=f"生成一篇关于{task}的文章,大约150字"
    else:
        previous_draft=state["draft"]
        reflection=state["reflection"]
        prompt=f"根据以下建议重写文章,保持150字左右:原文{previous_draft},改进建议{reflection}"
    response=llm.invoke(prompt)
    return {"draft":response.content, "iteration":iteration+1}
(2)质量评估节点 evaluate_quality

设计统一评估标准,让大模型输出 0~1 的量化分数,同时做异常兜底,防止模型返回非数字内容导致程序报错。

python

运行

复制代码
def evaluate_quality(state: ReflectionState):
    draft=state["draft"]
    task=state["task"]
    prompt=f"""评估文章质量,按内容、逻辑、语言综合给出0-1分数(保留两位小数),仅输出数字:
    任务:{task}  文章:{draft}"""
    score_text = llm.invoke(prompt).content.strip()
    try:
        score = float(score_text)
        score = max(0.0, min(1.0, score))
    except ValueError:
        score = 0.5
    return {"quality_score":score}
(3)反思建议节点 reflect_and_improve

结合文稿、评分分析问题,输出简短、可落地的修改方向,为下一轮改写提供依据。

python

运行

复制代码
def reflect_and_improve(state:ReflectionState):
    draft=state["draft"]
    task=state["task"]
    score=state["quality_score"]
    prompt=f"分析文章问题并给出简短改进建议(50字内):任务{task},评分{score},内容{draft}"
    reflection = llm.invoke(prompt).content
    return {"reflection":reflection}

3. 条件路由与图编排

这是实现循环 + 分支 的关键:通过路由函数判断流程走向,再用StateGraph拼接所有节点和边。

python

运行

复制代码
# 路由函数:判断是否继续迭代
def should_continue(state:ReflectionState):
    score=state["quality_score"]
    iteration=state["iteration"]
    max_iter=state["max_iterations"]
    if score>=0.9 or iteration>=max_iter:
        return "end"
    return "reflect"

# 构建流程图
def build_graph():
    builder=StateGraph(ReflectionState)
    # 注册节点
    builder.add_node("generate_draft",generate_draft)
    builder.add_node("evaluate_quality",evaluate_quality)
    builder.add_node("reflect_and_improve",reflect_and_improve)
    # 连接普通边
    builder.add_edge(START,"generate_draft")
    builder.add_edge("generate_draft","evaluate_quality")
    # 条件分支
    builder.add_conditional_edges(
        source="evaluate_quality",
        path=should_continue,
        path_map={"reflect":"reflect_and_improve", "end":END}
    )
    # 循环边:反思后回到生成节点
    builder.add_edge("reflect_and_improve","generate_draft")
    return builder.compile()

4. 入口函数与运行调用

封装执行逻辑,初始化状态并启动工作流,最终打印迭代次数、最终评分和成品内容。

python

运行

复制代码
def run_reflection_loop(task,max_iterations):
    graph=build_graph()
    initial_state={
        "task":task,"draft":"","quality_score":0.0,
        "reflection":"","iteration":0,"max_iterations":max_iterations
    }
    final_state=graph.invoke(initial_state)
    # 打印最终结果
    print(f"总迭代次数: {final_state['iteration']}")
    print(f"最终分数: {final_state['quality_score']:.2f}")
    print("最终文章:\n", final_state['draft'])
    return final_state

if __name__=="__main__":
    # 测试:主题+最大迭代3次
    run_reflection_loop(task="人工智能的发展历程", max_iterations=3)

五、完整代码

复制代码
import os
from typing import TypedDict

from dotenv import load_dotenv
from langchain_community.chat_models import ChatTongyi
from langgraph.constants import START, END
from langgraph.graph import StateGraph

load_dotenv()

# 初始化 LLM
llm = ChatTongyi(
    model="qwen-max",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    temperature=0.7
)


#定义state
class ReflectionState(TypedDict):
    task:str  #任务描述
    draft:str   #当前草稿
    quality_score:float #质量分数
    reflection:str  #反思内容
    iteration:int   #当前得迭代次数
    max_iterations:int   #最大迭代次数

#定义node1:生成文章/改进文章
def generate_draft(state: ReflectionState):
    """
    node1:生成初稿或改进内容
    任务:使用llm生成内容
    :param state:
    :return:
    """
    task = state["task"]
    iteration=state["iteration"]
    if iteration==0:
        print(f"Node1:生成一篇关于{task}的文章,大约150字")
        prompt=f"""
        生成一篇关于{task}的文章,大约150字"
        """
    else:
        previous_draft=state["draft"]
        reflection=state["reflection"]
        prompt=f"""
        请改进以下文章:
        原文:{previous_draft}
        改进建议:{reflection}
        请根据改进建议重写文章,保持150字左右。
        """
        print(f"提示词:根据反思改进第{iteration}次")
        print(f"反思建议:{reflection}")

    response=llm.invoke(prompt)
    draft=response.content
    print(f"生成结果:{draft}")
    return {
        "draft":draft,
        "iteration":iteration+1
    }

#定义node2:评估质量,获得分数
def evaluate_quality(state: ReflectionState):
    """
    Node2:评估质量
    任务:使用llm评估文章质量
    :param state:
    :return:
    """
    draft=state["draft"]
    task=state["task"]
    prompt=f"""
    请评估以下文章的质量:
    任务要求:写一篇关于'{task}'的文章
    文章内容:
    {draft}
    
    评估标准:
    1. 内容完整性 (是否涵盖主题)
    2. 逻辑清晰度 (结构是否合理)
    3. 语言表达 (是否流畅准确)

    请给出0-1的分数(保留两位小数),只输出数字,不要其他内容。
    例如:0.75
    """
    response=llm.invoke(prompt)
    score_text=response.content.strip()

    try:
        #提取分数
        score=float(score_text)
        score=max(0.0,min(1.0,score))  #确保在0~1之间
    except ValueError:
        print(f"无法解析分数,使用默认值0.5")
        score=0.5

    print(f"\n质量分数:{score:.2f}")

    return {"quality_score":score}

#定义node3:反思改进
def reflect_and_improve(state:ReflectionState):
    """
    Node3:反思改进
    任务:使用LLM分析问题并给出改进建议
    :param state:
    :return:
    """
    draft=state["draft"]
    task=state["task"]
    score=state["quality_score"]

    prompt=f"""
    请分析以下文章存在的问题,并给出具体的改进建议。

    任务要求: 写一篇关于'{task}'的文章
    当前文章:
    {draft}
    
    当前评分: {score:.2f}
    
    请简要指出1-2个主要问题,并给出改进方向(50字以内)。
    
    """
    response=llm.invoke(prompt)
    reflection=response.content

    print(f"\n改进建议:")
    print(f"{reflection}")

    return {"reflection":reflection}

#定义路由函数/条件边
def should_continue(state:ReflectionState):
    """
    决定是否继续改进

    终止条件:
    1、质量分数>=0.9
    2、达到最大迭代次数
    :param state:
    :return:
    """

    score=state["quality_score"]
    iteration=state["iteration"]
    max_iter=state["max_iterations"]

    print(f"\n{'=' * 60}")
    print(f"条件判断: 是否继续改进")
    print(f"{'=' * 60}")
    print(f"当前分数: {score:.2f}")
    print(f"迭代次数: {iteration}/{max_iter}")

    #终止条件1:
    if score>=0.9:
        print(f"✅ 决策: 质量达标 (>= 0.9),结束改进")
        return "end"
    #终止条件2:
    if iteration>=max_iter:
        print(f"⚠️  决策: 达到最大迭代次数,停止改进")
        return "end"

    print(f"❌ 决策: 质量不足,继续改进")
    return "reflect"

#构建图
def build_graph():

    #创建图
    builder=StateGraph(ReflectionState)

    #添加节点
    builder.add_node("generate_draft",generate_draft)
    builder.add_node("evaluate_quality",evaluate_quality)
    builder.add_node("reflect_and_improve",reflect_and_improve)

    #添加边
    #普通边
    builder.add_edge(START,"generate_draft")
    builder.add_edge("generate_draft","evaluate_quality")

    #条件边
    builder.add_conditional_edges(
        source="evaluate_quality",
        path=should_continue,
        path_map={
            "reflect":"reflect_and_improve",   #不合格->反思
            "end":END   #合格->结束
        }
    )
    #循环边
    builder.add_edge("reflect_and_improve","generate_draft")

    graph=builder.compile()

    return graph

def run_reflection_loop(task,max_iterations):
    """
    运行反思
    :param task:
    :param max_iterations:
    :return:
    """
    print("\n" + "=" * 60)
    print("反思循环 Agent 启动")
    print("=" * 60)
    print(f"任务: {task}")
    print(f"最大迭代次数: {max_iterations}")

    #构建图
    graph=build_graph()
    #初始状态
    initial_state={
        "task":task,
        "draft":"",
        "quality_score":0.0,
        "reflection":"",
        "iteration":0,
        "max_iterations":max_iterations
    }

    #执行图
    final_state=graph.invoke(initial_state)

    # 显示最终结果
    print("\n" + "=" * 60)
    print("最终结果")
    print("=" * 60)
    print(f"总迭代次数: {final_state['iteration']}")
    print(f"最终质量分数: {final_state['quality_score']:.2f}")
    print(f"\n最终文章:")
    print("-" * 60)
    print(final_state['draft'])
    print("-" * 60)

    return final_state


if __name__=="__main__":
    result=run_reflection_loop(
        task="人工智能的发展历程",
        max_iterations=3
    )
相关推荐
basketball6161 小时前
AI Infra 硬件体系与编程模型:9. 使用 NVCC 进行编译
人工智能
硅谷秋水1 小时前
HumanEgo:基于人类第一人称视角数分钟视频的零样本机器人学习
人工智能·机器学习·计算机视觉·机器人
IT_陈寒1 小时前
Vite这个坑我帮你踩了,动态导入居然这样才生效
前端·人工智能·后端
gis分享者2 小时前
OpenCV 新手入门与实战部署指南
人工智能·opencv·计算机视觉
Ronin3052 小时前
ToDesk AI如何成为Codex远程控制的国内代替品?
人工智能
测试员周周2 小时前
【AI测试智能体-面试】AI测试面试60题(附回答思路)
人工智能·python·功能测试·测试工具·单元测试·自动化·测试用例
ShyanZh2 小时前
【skill】Humanizer-zh:24条规则消灭AI写作痕迹
人工智能·ai写作·skill
电商软件开发 小银2 小时前
思域不再安全?AI+独立APP破局指南
人工智能·软件开发·数字化转型·商业模式·超级app·商业思维·ai 矩阵运营
asyxchenchong8882 小时前
最新Hermes Agent 技能封装与科研自动化:以 Meta-Analysis 为例-实现从文献检索到绘图的一站式工作流
运维·人工智能·自动化