LLM应用开发:基于/goal功能的任务分解与执行架构实践
2026/7/24 14:39:18 网站建设 项目流程

在实际 LLM 应用开发中,很多团队会遇到一个典型困境:大模型本身能力很强,但如何让它稳定、高效地执行一个明确的、多步骤的任务目标(Goal)?直接向模型抛出一个复杂指令,结果往往不可控,可能出现逻辑混乱、步骤遗漏或格式错误。DAIR.AI 的 Elvis Saravia 提出的/goal功能设计,正是为了解决这一问题。它本质上是一种工程模式,通过结构化输入、步骤拆解和工具调用,让 LLM 能够像执行程序一样处理复杂任务。

本文将围绕如何构建一个独立的、具备/goal功能的 LLM 应用展开。我们会从核心概念入手,解释/goal的工作机制,然后基于一个假设的模型服务(如 GPT-5.6-Sol)设计一套完整的实现方案。这套方案会涵盖环境准备、依赖配置、核心代码实现、运行验证以及生产环境中常见的错误排查。无论你是在研究 LLM 应用架构,还是希望提升现有 Agent 的任务执行效率,这篇文章都能提供一条清晰的实践路径。

1. 理解 /goal 功能的核心机制

1.1 /goal 要解决什么问题

在没有明确任务管理机制的情况下,直接让 LLM 处理复杂目标,比如“请分析这个季度的销售数据,找出下降原因,并生成一份改进报告”,模型可能会一次性输出大量文本,但其中可能夹杂着无关信息、逻辑跳跃或未按步骤执行。/goal功能的核心思想是将一个宏观目标(Goal)分解为一系列可执行、可验证的原子任务(Tasks),并按照预设或动态生成的计划(Plan)逐步推进。

这种机制的优势在于:

  • 可控性:每个步骤的输入、输出和成功标准都是明确的,便于跟踪和干预。
  • 可复用性:针对某一类目标(如数据分析、报告生成),可以沉淀出标准化的任务模板。
  • 容错性:单个步骤失败不会导致整个目标崩溃,可以重试或采用备用方案。
  • 效率:通过并行执行独立任务或优化任务顺序,可以提升整体执行效率。

1.2 /goal 功能的基本工作流程

一个典型的/goal功能执行流程包含以下几个关键环节:

  1. 目标解析(Goal Parsing):接收用户输入的自然语言目标,解析出其核心意图和关键约束条件。
  2. 计划生成(Plan Generation):根据解析出的目标,生成一个有序的任务列表(Plan)。每个任务应包含:任务描述、所需工具或资源、成功标准、依赖关系。
  3. 任务执行(Task Execution):按照计划顺序(或根据依赖关系确定的并行路径)执行每个任务。执行过程通常涉及调用外部工具(如数据库查询、API 调用、代码执行)或 LLM 自身的推理能力。
  4. 结果整合与验证(Result Integration & Validation):收集每个任务的执行结果,并验证是否满足成功标准。如果某个任务失败,可能触发重试或计划调整。
  5. 最终输出(Final Output):将所有任务的结果整合成最终的、符合用户要求的输出形式(如一份报告、一段代码、一个决策建议)。

在这个过程中,LLM(如 GPT-5.6-Sol)扮演着“大脑”的角色,负责解析、规划和高阶推理,而具体的工具调用和数据操作则由外部系统完成。

1.3 关键组件与数据格式

为了实现上述流程,我们需要定义几个核心的数据结构。这些结构通常使用 JSON 格式在系统各部分间传递。

Goal 请求格式

{ "goal": "分析本季度销售数据,找出销售额下降的原因,并生成改进报告。", "parameters": { "data_source": "database://sales_q2", "report_format": "markdown" } }

Plan 数据结构

{ "plan_id": "plan_12345", "goal": "分析本季度销售数据...", "tasks": [ { "task_id": "task_1", "description": "从数据源提取本季度销售数据", "tool": "database_query", "parameters": {"query": "SELECT * FROM sales WHERE quarter='Q2'"}, "dependencies": [], "success_criteria": "返回非空数据集" }, { "task_id": "task_2", "description": "计算关键指标(如环比、同比)", "tool": "python_script", "parameters": {"script_name": "calculate_metrics.py"}, "dependencies": ["task_1"], "success_criteria": "输出包含销售额、增长率等指标" }, { "task_id": "task_3", "description": "分析下降原因", "tool": "llm_analysis", "parameters": {"prompt_template": "analysis_template.jinja2"}, "dependencies": ["task_2"], "success_criteria": "列出至少3条可能原因" }, { "task_id": "task_4", "description": "生成改进报告", "tool": "llm_report", "parameters": {"format": "markdown"}, "dependencies": ["task_3"], "success_criteria": "生成结构清晰的Markdown报告" } ] }

Task 执行结果格式

{ "task_id": "task_1", "status": "success", // 或 "failed", "pending" "result": {"data": [...]}, "error": null, // 如果失败,记录错误信息 "metadata": {"execution_time": 1.5} }

理解这些基础概念和流程后,我们就可以开始着手构建实现它的技术环境。

2. 环境准备与项目初始化

2.1 技术栈选型与版本要求

构建一个独立的/goal功能应用,通常需要以下技术组件。版本号是保证兼容性的关键,以下是基于常见稳定版本的推荐。

组件推荐版本作用说明备注
Python3.9+主开发语言,生态丰富3.9 以上版本对异步和类型提示支持更好
FastAPI0.104+提供/goal接口的 Web 框架异步支持好,自动生成 API 文档
LangChain0.1.0+LLM 应用框架,简化与模型交互注意版本间 API 变化较大
假设的模型客户端-用于调用 GPT-5.6-Sol 等模型需根据模型提供商 SDK 安装
Redis7.0+用作计划、任务状态和结果的缓存保证任务状态持久化和跨进程共享
SQLite/PostgreSQL-可选,用于持久化历史目标和结果简单场景用 SQLite,生产用 PostgreSQL

注意:输入材料中提到的GPT-5.6-SolGPT-5.6-Terra是假设的模型名称。在实际项目中,你需要替换为真实可用的模型端点,例如 OpenAI 的gpt-4、Anthropic 的claude-3或本地部署的开源模型。下文代码将以GPT-5.6-Sol作为占位符。

2.2 项目结构与依赖管理

建议采用清晰的项目结构来管理代码,以下是一个参考结构:

goal_llm_agent/ ├── requirements.txt ├── main.py ├── core/ │ ├── __init__.py │ ├── goal_parser.py │ ├── plan_generator.py │ ├── task_executor.py │ └── models.py ├── tools/ │ ├── __init__.py │ ├── database_tool.py │ ├── calculator_tool.py │ └── llm_tool.py ├── config/ │ └── settings.py └── tests/ └── test_goal_execution.py

创建requirements.txt文件来管理 Python 依赖:

fastapi==0.104.1 uvicorn[standard]==0.24.0 langchain==0.1.0 openai==1.3.0 redis==5.0.1 pydantic==2.5.0 python-dotenv==1.0.0 sqlalchemy==2.0.23

使用虚拟环境并安装依赖:

# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate # 安装依赖 pip install -r requirements.txt

2.3 关键配置管理

config/settings.py中集中管理配置,避免硬编码。使用python-dotenv.env文件加载敏感信息。

.env 文件示例

# 模型配置 MODEL_NAME=gpt-5.6-sol MODEL_API_KEY=your_api_key_here MODEL_BASE_URL=https://api.example.com/v1 # Redis 配置 REDIS_URL=redis://localhost:6379/0 # 应用配置 LOG_LEVEL=INFO MAX_CONCURRENT_TASKS=5

config/settings.py

import os from dotenv import load_dotenv from pydantic_settings import BaseSettings load_dotenv() class Settings(BaseSettings): # 模型配置 model_name: str = os.getenv("MODEL_NAME", "gpt-5.6-sol") model_api_key: str = os.getenv("MODEL_API_KEY", "") model_base_url: str = os.getenv("MODEL_BASE_URL", "") # Redis 配置 redis_url: str = os.getenv("REDIS_URL", "redis://localhost:6379/0") # 应用配置 log_level: str = os.getenv("LOG_LEVEL", "INFO") max_concurrent_tasks: int = int(os.getenv("MAX_CONCURRENT_TASKS", "5")) class Config: env_file = ".env" settings = Settings()

环境准备就绪后,我们就可以开始实现核心的/goal处理逻辑。

3. 核心功能模块实现

3.1 定义数据模型

首先在core/models.py中使用 Pydantic 定义清晰的数据模型,这有助于类型检查和序列化。

from typing import List, Optional, Dict, Any from pydantic import BaseModel class GoalRequest(BaseModel): goal: str parameters: Optional[Dict[str, Any]] = {} class Task(BaseModel): task_id: str description: str tool: str # 如 "database_query", "llm_analysis", "python_script" parameters: Dict[str, Any] dependencies: List[str] = [] # 依赖的 task_id 列表 success_criteria: str class Plan(BaseModel): plan_id: str goal: str tasks: List[Task] class TaskResult(BaseModel): task_id: str status: str # "pending", "running", "success", "failed" result: Optional[Any] = None error: Optional[str] = None metadata: Optional[Dict[str, Any]] = None class GoalResponse(BaseModel): goal_id: str status: str # "accepted", "planning", "executing", "completed", "failed" plan: Optional[Plan] = None final_result: Optional[Any] = None message: str

3.2 实现目标解析与计划生成

/goal功能最核心的部分是利用 LLM 将模糊的目标转化为可执行的计划。我们在core/plan_generator.py中实现。

import logging from typing import List from langchain.schema import BaseOutputParser from langchain.prompts import PromptTemplate from langchain.chains import LLMChain from core.models import GoalRequest, Plan, Task from config.settings import settings # 自定义输出解析器,用于将 LLM 的自然语言回复解析为结构化的 Task 列表 class TaskListOutputParser(BaseOutputParser): def parse(self, text: str) -> List[Task]: # 这里简化处理,实际应用中需要更鲁棒的解析逻辑 # 例如,可以要求 LLM 以特定格式(如 JSON)输出 tasks = [] lines = text.strip().split('\n') for i, line in enumerate(lines): if line.strip(): # 假设每行是任务描述,实际应根据与 LLM 的约定格式解析 task_id = f"task_{i+1}" tasks.append(Task( task_id=task_id, description=line.strip(), tool="llm_analysis", # 默认工具,后续可细化 parameters={}, dependencies=[], success_criteria=f"完成 {line.strip()}" )) return tasks class PlanGenerator: def __init__(self, llm): self.llm = llm self.logger = logging.getLogger(__name__) def generate_plan(self, goal_request: GoalRequest) -> Plan: # 构建提示词模板,引导 LLM 进行任务分解 prompt_template = PromptTemplate( input_variables=["goal"], template=""" 请将以下目标分解为一系列具体的、可顺序执行的任务步骤。每个步骤应该清晰、独立且可验证。 目标:{goal} 请按顺序列出任务步骤,每行一个任务。任务描述应具体,例如: - 第一步:收集相关数据 - 第二步:分析数据趋势 - 第三步:总结核心发现 - 第四步:提出建议方案 任务列表: """ ) # 创建 LLM 调用链 chain = LLMChain(llm=self.llm, prompt=prompt_template) try: # 调用 LLM 获取任务分解结果 result = chain.run(goal=goal_request.goal) self.logger.info(f"LLM 生成了任务分解结果:{result}") # 解析结果为 Task 列表 parser = TaskListOutputParser() tasks = parser.parse(result) # 构建完整的 Plan 对象 plan_id = f"plan_{hash(goal_request.goal) % 1000000}" # 简单生成 ID plan = Plan( plan_id=plan_id, goal=goal_request.goal, tasks=tasks ) return plan except Exception as e: self.logger.error(f"生成计划时出错:{e}") raise # 初始化 LLM(这里以 OpenAI 格式的客户端为例) from langchain.llms import OpenAI # 注意:实际使用时需根据 GPT-5.6-Sol 的 API 调整 def get_llm(): # 如果 GPT-5.6-Sol 兼容 OpenAI API,可以这样配置 return OpenAI( model=settings.model_name, openai_api_key=settings.model_api_key, openai_api_base=settings.model_base_url )

3.3 实现任务执行器

任务执行器负责调度和执行计划中的每个任务,并管理它们之间的依赖关系。在core/task_executor.py中实现。

import asyncio import logging from typing import Dict, List from core.models import Plan, Task, TaskResult from tools.database_tool import DatabaseTool from tools.llm_tool import LLMTool from tools.calculator_tool import CalculatorTool class TaskExecutor: def __init__(self): self.logger = logging.getLogger(__name__) # 注册可用工具 self.tools = { "database_query": DatabaseTool(), "llm_analysis": LLMTool(), "python_script": CalculatorTool() # 示例,实际可能是更通用的脚本执行器 } async def execute_plan(self, plan: Plan) -> Dict[str, TaskResult]: """执行整个计划,返回所有任务的结果字典""" task_results: Dict[str, TaskResult] = {} # 初始化所有任务状态为 pending for task in plan.tasks: task_results[task.task_id] = TaskResult( task_id=task.task_id, status="pending" ) # 按照任务顺序执行(简化版,未处理并行) for task in plan.tasks: # 检查依赖是否全部成功 dependencies_met = all( task_results[dep_id].status == "success" for dep_id in task.dependencies ) if not dependencies_met: task_results[task.task_id].status = "failed" task_results[task.task_id].error = f"依赖任务未完成: {task.dependencies}" continue # 执行当前任务 task_results[task.task_id].status = "running" try: result = await self.execute_single_task(task) task_results[task.task_id].status = "success" task_results[task.task_id].result = result task_results[task.task_id].metadata = {"execution_time": 1.2} # 示例 except Exception as e: task_results[task.task_id].status = "failed" task_results[task.task_id].error = str(e) self.logger.error(f"任务 {task.task_id} 执行失败: {e}") return task_results async def execute_single_task(self, task: Task): """执行单个任务""" tool = self.tools.get(task.tool) if not tool: raise ValueError(f"未知工具: {task.tool}") self.logger.info(f"执行任务 {task.task_id}: {task.description}") # 调用对应工具的 execute 方法 result = await tool.execute(task.parameters) return result

3.4 实现工具层

工具是任务执行的具体承载者。在tools/目录下实现各种工具。

tools/llm_tool.py

import logging from core.plan_generator import get_llm class LLMTool: def __init__(self): self.llm = get_llm() self.logger = logging.getLogger(__name__) async def execute(self, parameters: dict): # 从参数中获取提示词或模板 prompt = parameters.get("prompt", "") if not prompt: raise ValueError("LLM 工具需要 'prompt' 参数") try: # 调用 LLM response = await self.llm.ainvoke(prompt) return response except Exception as e: self.logger.error(f"LLM 工具执行出错: {e}") raise # 其他工具如 DatabaseTool, CalculatorTool 类似实现

4. 构建 API 接口与主程序

4.1 创建 FastAPI 应用和 /goal 端点

main.py中创建 Web 服务,暴露/goal接口。

from fastapi import FastAPI, BackgroundTasks from fastapi.responses import JSONResponse import uuid import redis import json from core.models import GoalRequest, GoalResponse from core.plan_generator import PlanGenerator, get_llm from core.task_executor import TaskExecutor from config.settings import settings app = FastAPI(title="Goal-Oriented LLM Agent", version="1.0.0") # 连接 Redis 用于状态存储 redis_client = redis.from_url(settings.redis_url) @app.post("/goal", response_model=GoalResponse) async def submit_goal(goal_request: GoalRequest, background_tasks: BackgroundTasks): # 生成唯一目标 ID goal_id = str(uuid.uuid4()) # 立即返回接受响应,实际处理在后台进行 response = GoalResponse( goal_id=goal_id, status="accepted", message="目标已接受,正在处理中" ) # 将实际处理逻辑加入后台任务 background_tasks.add_task(process_goal, goal_id, goal_request) return response async def process_goal(goal_id: str, goal_request: GoalRequest): """后台处理目标的核心逻辑""" try: # 更新状态为规划中 await update_goal_status(goal_id, "planning", "正在生成执行计划") # 1. 生成计划 llm = get_llm() plan_generator = PlanGenerator(llm) plan = plan_generator.generate_plan(goal_request) # 保存计划到 Redis plan_key = f"goal:{goal_id}:plan" redis_client.set(plan_key, plan.json()) await update_goal_status(goal_id, "executing", f"计划生成完成,共 {len(plan.tasks)} 个任务") # 2. 执行计划 task_executor = TaskExecutor() task_results = await task_executor.execute_plan(plan) # 3. 整合结果 final_result = await integrate_results(plan, task_results) # 更新最终状态 await update_goal_status( goal_id, "completed", "目标处理完成", plan=plan, final_result=final_result ) except Exception as e: await update_goal_status(goal_id, "failed", f"处理失败: {str(e)}") async def update_goal_status(goal_id: str, status: str, message: str, plan=None, final_result=None): """更新目标状态到 Redis""" status_data = { "goal_id": goal_id, "status": status, "message": message, "timestamp": ... # 添加时间戳 } if plan: status_data["plan"] = plan.dict() if final_result: status_data["final_result"] = final_result redis_client.set(f"goal:{goal_id}:status", json.dumps(status_data)) @app.get("/goal/{goal_id}/status") async def get_goal_status(goal_id: str): """查询目标处理状态""" status_data = redis_client.get(f"goal:{goal_id}:status") if not status_data: return JSONResponse( status_code=404, content={"detail": "目标不存在"} ) return json.loads(status_data) if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)

4.2 运行和测试应用

启动服务:

uvicorn main:app --reload --host 0.0.0.0 --port 8000

使用 curl 或 httpie 测试/goal接口:

curl -X POST "http://localhost:8000/goal" \ -H "Content-Type: application/json" \ -d '{ "goal": "分析本季度销售数据,找出销售额下降的原因,并生成改进报告。", "parameters": { "data_source": "sample_data.csv", "report_format": "markdown" } }'

预期响应:

{ "goal_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "accepted", "message": "目标已接受,正在处理中" }

然后通过 GET 接口查询状态:

curl "http://localhost:8000/goal/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status"

5. 常见问题排查与优化

5.1 模型调用相关错误

在实际运行中,模型调用是最容易出错的环节。以下是一些常见问题及解决方案。

问题现象可能原因检查方式处理建议
{"detail":"the 'gpt-5.6-sol' model is not supported..."}1. 模型名称拼写错误
2. API 密钥权限不足
3. 终端点不支持该模型
1. 检查MODEL_NAME配置
2. 验证 API 密钥权限
3. 查阅模型提供商文档
1. 确认模型名称正确
2. 申请正确的 API 权限
3. 更换兼容的模型或终端点
LLM request failed: provider rejected the request1. 请求格式不符合 API 要求
2. 输入长度超限
3. 频率限制
1. 检查请求的 JSON 结构
2. 查看输入 token 数量
3. 检查调用频率
1. 按照 API 文档调整请求格式
2. 压缩或分段输入
3. 添加重试机制和速率限制
响应时间过长或超时1. 网络问题
2. 模型负载高
3. 输入过于复杂
1. 检查网络连接
2. 测试简单请求的响应时间
3. 分析输入复杂度
1. 优化网络配置
2. 设置合理的超时时间
3. 简化输入或使用更小模型

代码层面的容错处理

tools/llm_tool.pyexecute方法中加入重试逻辑:

import tenacity class LLMTool: @tenacity.retry( stop=tenacity.stop_after_attempt(3), wait=tenacity.wait_exponential(multiplier=1, min=4, max=10), retry=tenacity.retry_if_exception_type(Exception) ) async def execute(self, parameters: dict): try: prompt = parameters.get("prompt", "") if not prompt: raise ValueError("LLM 工具需要 'prompt' 参数") # 设置超时 response = await asyncio.wait_for( self.llm.ainvoke(prompt), timeout=30.0 ) return response except asyncio.TimeoutError: self.logger.error("LLM 调用超时") raise except Exception as e: self.logger.error(f"LLM 调用失败: {e}") raise

5.2 任务依赖与执行逻辑问题

问题现象可能原因检查方式处理建议
任务卡在 pending 状态1. 依赖任务失败
2. 依赖检测逻辑错误
3. 任务 ID 不匹配
1. 检查依赖任务状态
2. 验证依赖检测代码
3. 核对任务 ID 命名
1. 完善错误处理机制
2. 添加更详细的日志
3. 使用更可靠的 ID 生成方案
任务执行顺序混乱1. 依赖关系定义错误
2. 并行执行冲突
1. 检查计划中的依赖关系
2. 分析执行日志
1. 使用有向无环图(DAG)验证依赖关系
2. 实现基于依赖关系的拓扑排序

改进的任务调度器

from collections import deque import networkx as nx class AdvancedTaskExecutor(TaskExecutor): async def execute_plan(self, plan: Plan) -> Dict[str, TaskResult]: task_results = {task.task_id: TaskResult(task_id=task.task_id, status="pending") for task in plan.tasks} # 构建依赖图 dag = nx.DiGraph() for task in plan.tasks: dag.add_node(task.task_id) for dep in task.dependencies: dag.add_edge(dep, task.task_id) # 检查循环依赖 if not nx.is_directed_acyclic_graph(dag): raise ValueError("计划中存在循环依赖") # 拓扑排序确定执行顺序 execution_order = list(nx.topological_sort(dag)) for task_id in execution_order: task = next(t for t in plan.tasks if t.task_id == task_id) # ... 执行逻辑与之前类似

5.3 性能优化建议

  1. 并行执行独立任务:使用asyncio.gather并行执行没有依赖关系的任务。
  2. 结果缓存:对耗时且结果不变的任务(如数据查询)实施缓存。
  3. 计划模板:对常见目标类型预定义计划模板,减少 LLM 生成计划的开销。
  4. 增量执行:支持从失败点继续执行,而不是重新开始整个计划。
  5. 资源限制:控制并发任务数量,避免资源耗尽。

6. 生产环境部署考量

6.1 安全性配置

  • API 认证:为/goal接口添加 API Key 或 JWT 认证。
  • 输入验证:对用户输入的目标和参数进行严格验证和清理。
  • 敏感信息保护:确保 API 密钥、数据库密码等敏感配置不会泄露到日志或错误信息中。
  • 访问控制:限制可访问的模型终端点和工具,防止滥用。

6.2 可观测性增强

  • 结构化日志:使用 JSON 格式记录关键事件,便于后续分析。
  • 指标收集:收集任务执行时间、成功率、模型调用延迟等指标。
  • 分布式追踪:为每个目标请求分配唯一的 Trace ID,跟踪整个处理链路。

6.3 扩展性设计

  • 插件化工具:设计工具注册机制,便于动态添加新工具。
  • 多模型支持:支持根据任务类型选择最合适的模型。
  • 水平扩展:使用消息队列(如 Celery + Redis/RabbitMQ)将任务执行分布到多个工作节点。

构建一个成熟的/goal功能 LLM 应用需要在前期的架构设计上投入足够考量。从最小可行产品开始,逐步加入错误处理、性能优化和生产级特性,是较为稳妥的演进路径。重点是要确保核心的任务分解和执行逻辑稳定可靠,这是整个系统价值的基石。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询