模块化AI编排系统设计:DAG+契约驱动的Orchestrator实践
1. 项目概述为什么需要一个“模块化 AI 创作与编排系统”我做了一个叫 EverSpark Forge 的系统它不是另一个聊天界面也不是套着大模型外壳的玩具产品。它是我在过去三年里亲手拆解、重装、再推翻重建了七次的 AI 工程实践沉淀——一个真正面向“AI 原生工作流”的模块化创作与编排系统。核心关键词就五个AI、模块化、编排系统、EverSpark Forge、Orchestrator。这五个词串起来不是营销话术而是我每天在终端里敲命令、改配置、调日志、压测并发时反复验证的技术锚点。简单说EverSpark Forge 解决的是这样一个现实困境当你想用 AI 完成一件稍复杂的事——比如“根据用户上传的旅行照片生成带地理标签的短视频脚本 配乐建议 小红书风格文案 同步输出英文版”你得手动打开至少四个不同平台复制粘贴三次以上校验四轮格式中间任何一个环节出错比如图片识别漏了关键地标、文案风格偏移、英文翻译漏掉语气词整个流程就得重来。这不是 AI 不够强而是我们缺乏一套像“乐高积木工业流水线”那样的底层支撑积木模块可互换、可复用流水线编排器能定义顺序、分支、重试、超时、状态回滚。EverSpark Forge 就是这个流水线积木仓的统一体。它适合三类人第一类是内容创作者想把重复性 AI 动作固化成一键流程比如“每日早报生成”第二类是中小团队的技术负责人不想从零造轮子但又不愿被 SaaS 平台锁死需要私有化、可审计、可插拔的 AI 编排底座第三类是 AI 工程师正在探索 Agent 架构落地路径需要真实可调试、可观测、可压测的 Orchestrator 实现参考。它不承诺“无限制”“无审核”“免费”它只承诺一件事让你清楚知道每个 AI 调用发生在哪一毫秒、由哪个模块触发、输入是什么、输出是否符合 schema、失败时如何降级——所有逻辑都在你眼皮底下运行。我把它命名为 EverSpark Forge是因为“EverSpark”代表持续激发的智能火花——不是单次问答的闪光而是可积累、可传导、可组合的智能脉冲“Forge”则是锻造场强调它是一个需要动手锤炼、不断锻打的工程产物而非开箱即用的黑盒。接下来我会带你一层层剥开它的设计肌理不讲虚的只讲我踩过的坑、调过的参数、写死的约束条件以及为什么每一个选择都不可替代。2. 整体架构设计模块化不是堆砌编排不是调度2.1 模块化设计的三层硬约束很多人一提“模块化”第一反应就是“把功能拆成函数”。但在 AI 系统里这远远不够。EverSpark Forge 的模块化建立在三个刚性约束之上缺一不可第一层输入/输出契约IO Contract强制标准化。每个模块Module必须声明明确的input_schema和output_schema采用 JSON Schema Draft-07 格式。例如一个“图像地理信息提取”模块其input_schema必须包含image_url: string, timeout_ms: integer 30000output_schema必须返回{ lat: number, lng: number, place_name: string, confidence: number }。这不是可选项——编排器在加载模块前会进行严格校验schema 不匹配直接拒绝注册。我试过放宽松口子结果三个月后系统里出现 17 个版本的“地址字段”有的叫location有的叫geo_tag有的返回字符串有的返回对象嵌套调试成本翻了四倍。现在所有模块的输入输出都像插座和插头一样严丝合缝。第二层执行上下文隔离Execution Context Isolation。每个模块运行在独立的沙箱环境中。技术实现上我们采用轻量级容器Podman rootless mode cgroups v2 限频 seccomp 白名单。这意味着一个模块因大模型响应慢导致内存暴涨不会拖垮整个编排进程一个模块尝试读取/etc/passwd被 seccomp 拦截只会返回PermissionDenied错误不会污染全局环境。这里有个关键细节我们禁用了CAP_SYS_ADMIN但显式授予CAP_NET_BIND_SERVICE因为很多模块需要绑定本地端口启动临时服务如 Whisper 的语音转文字微服务。这个粒度控制是经过 5 轮安全审计后定下的底线。第三层状态无感Stateless by Design。模块本身不维护任何跨请求状态。所有状态流转必须通过编排器显式传递。比如“多轮对话摘要”模块它不自己缓存历史消息而是依赖编排器传入conversation_history: array[object]并返回summary: string。这样做的代价是每次调用都要序列化传输历史但换来的是极致的可测试性——你可以用固定输入100% 复现模块行为也换来水平扩展能力——任意增加模块实例数无需考虑状态同步。我们曾为追求性能引入过 Redis 缓存模块内部状态结果在灰度发布时发现缓存键命名冲突导致两个不同用户的对话摘要混在一起紧急回滚。从此“状态必须外置”写进了所有模块开发规范第一条。2.2 编排系统Orchestrator的核心范式DAG 事件驱动EverSpark Forge 的编排器不是简单的任务队列而是一个基于有向无环图DAG的事件驱动引擎。它的设计哲学是“流程即数据编排即编程”。DAG 是骨架不是装饰。每个工作流Workflow被定义为一个 YAML 文件其中nodes描述模块节点edges描述数据流向。关键在于edges不仅指定“从 A 到 B”还必须声明data_mapping—— 即 A 的哪个输出字段映射到 B 的哪个输入字段。例如edges: - from: image_analyzer to: script_generator data_mapping: lat: geo.lat lng: geo.lng place_name: geo.place_name这个data_mapping是编排器校验的核心。如果image_analyzer输出中没有geo对象或者geo里没有lat字段编排器会在工作流加载阶段就报错而不是等到运行时才发现。这种静态检查把 83% 的流程错误拦截在部署前。事件驱动是血液不是附加功能。编排器内置一个轻量级事件总线基于 Redis Streams所有节点执行完成、失败、超时、重试都会发布事件。这意味着你不需要在模块里写埋点代码就能监听到“脚本生成耗时超过 5 秒”或“文案翻译失败率连续 3 次 5%”。我们用这些事件驱动告警企业微信机器人、自动降级当翻译模块失败时自动切换到备用规则引擎、甚至动态扩缩容当某类图像处理请求突增事件触发 Kubernetes HPA。事件总线的消费组机制还支持多消费者并行处理——运维团队看监控算法团队看质量产品团队看用户路径互不干扰。为什么不用现有编排框架我对比过 Airflow、Prefect、Temporal。Airflow 的 DAG 定义太重调度器和 Worker 分离导致本地调试困难Prefect 的 Python 原生 DSL 在跨语言模块集成时很别扭Temporal 的长时运行Long Running能力虽强但对 AI 场景常见的“短时爆发、高并发、低延迟”支持不足。EverSpark Forge 的编排器从第一天就设计为单进程、内存优先、事件中心化——它不追求管理百万级任务而是确保每毫秒的决策都可追溯、可干预、可重放。2.3 EverSpark Forge 的独特定位介于胶水层与平台之间市面上常见两类 AI 工具一类是“胶水层”比如 Zapier 或 Make它们用可视化连线把 API 串起来但模块能力弱、错误处理粗糙、无法深度定制另一类是“平台层”比如 LangChain 或 LlamaIndex它们提供强大抽象但要求你写大量 Python 代码且默认假设所有模块都在同一进程内运行。EverSpark Forge 卡在这两者中间它提供比胶水层更严格的契约和更细的控制粒度又比平台层更低的代码侵入性——你只需按契约写好模块剩下的编排、监控、扩缩容、权限管理全由 Forge 托管。这种定位决定了它的边界它不提供大模型训练能力不内置向量数据库不封装前端 UI。但它提供一个“最小可行编排核”——只要你的模块能暴露 HTTP 接口或 gRPC 接口就能接入。我们已成功接入 47 种异构模块Python 写的 PyTorch 模型服务、Go 写的 OCR 微服务、Rust 写的音频处理 WASM 模块、甚至 Shell 脚本包装的 FFmpeg 命令。它们唯一的共同点是遵守 Forge 的 IO 契约和健康检查协议。3. 核心模块解析从“AI Agent”到可交付单元3.1 “AI Agent”在 EverSpark Forge 中的真实形态网络热词里高频出现的 “AI Agent”常被描述为“能自主思考、规划、执行的智能体”。但在 EverSpark Forge 的语境下Agent 不是一个神秘实体而是一组协同工作的模块实例由编排器动态组装。一个典型的“旅行内容 Agent”工作流包含 6 个模块user_input_parser解析用户自然语言指令提取结构化参数目的地、偏好、预算等image_analyzer调用多模态模型分析上传图片输出地理坐标与场景标签script_generator结合地理信息与用户偏好生成分镜脚本music_suggester根据脚本情绪曲线推荐配乐库中的曲目copywriter_zh将脚本转化为小红书风格中文文案copywriter_en将中文文案翻译并本地化为美式英语。这六个模块每个都是独立部署、独立升级、独立监控的单元。编排器根据用户请求的workflow_id加载对应 DAG并实时决定执行路径——比如当user_input_parser识别出用户未上传图片则跳过image_analyzer直接进入script_generator的兜底模式基于文本描述生成。这种“动态组装”能力让同一个 Agent 可以应对完全不同的输入组合而无需修改任何模块代码。提示Agent 的“智能”不来自单个模块而来自编排器对模块间数据流的精准控制。我们曾把script_generator模块的温度值temperature设为 0.9结果生成脚本过于发散后来改为根据image_analyzer的confidence值动态调整confidence 0.8 时 temperature0.3严谨 0.5 时 temperature0.7创意兜底。这种策略只能在编排层实现模块自身无法感知上下文。3.2 模块开发实战一个可复用的“多语言文案生成器”模块以copywriter_zh模块为例展示如何开发一个符合 Forge 规范的生产级模块第一步定义 IO Schemaschema.yamlinput_schema: type: object properties: script: type: string description: 分镜脚本原文含时间戳和画面描述 platform: type: string enum: [xiaohongshu, weibo, zhihu] default: xiaohongshu tone: type: string enum: [casual, professional, humorous] default: casual required: [script] output_schema: type: object properties: content: type: string description: 生成的文案正文 word_count: type: integer minimum: 1 maximum: 1000 readability_score: type: number minimum: 0 maximum: 100 required: [content, word_count, readability_score]第二步实现核心逻辑main.py我们不直接调用大模型 API而是封装成可插拔的“策略引擎”class CopywritingStrategy: def __init__(self, model_provider: str): self.provider model_provider # 这里初始化对应 provider 的 client如 OpenAI、Ollama、本地 vLLM def generate(self, script: str, platform: str, tone: str) - dict: # 构建 prompt包含平台特征小红书需 emoji 和话题标签、语气要求 prompt self._build_prompt(script, platform, tone) response self.client.chat.completions.create( modelqwen2-7b, messages[{role: user, content: prompt}], temperature0.3, max_tokens512 ) return { content: response.choices[0].message.content.strip(), word_count: len(response.choices[0].message.content.split()), readability_score: self._calc_readability(response.choices[0].message.content) } # 模块入口接收 HTTP POST 请求 app.post(/invoke) def invoke(request: Request): try: payload await request.json() # 自动校验 payload 是否符合 input_schema使用 jsonschema 库 validate(instancepayload, schemainput_schema) strategy CopywritingStrategy(payload.get(model_provider, ollama)) result strategy.generate( payload[script], payload.get(platform, xiaohongshu), payload.get(tone, casual) ) # 自动校验 result 是否符合 output_schema validate(instanceresult, schemaoutput_schema) return {status: success, data: result} except ValidationError as e: return {status: error, message: fSchema validation failed: {str(e)}} except Exception as e: return {status: error, message: fInternal error: {str(e)}}第三步容器化与健康检查DockerfileFROM python:3.11-slim COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . /app WORKDIR /app EXPOSE 8000 HEALTHCHECK --interval30s --timeout3s --start-period5s --retries3 \ CMD curl -f http://localhost:8000/health || exit 1 CMD [uvicorn, main:app, --host, 0.0.0.0:8000, --port, 8000]第四步注册到 Forgemodule_config.yamlname: copywriter_zh version: 1.2.0 description: 小红书/微博/知乎风格中文文案生成器 endpoint: http://copywriter-zh:8000/invoke health_check: http://copywriter-zh:8000/health input_schema_path: schema.yaml output_schema_path: schema.yaml resources: cpu_limit: 1000m memory_limit: 2Gi gpu_required: false这个模块上线后copywriter_en只需复用相同的结构替换 prompt 模板和模型调用逻辑即可。模块间的差异被压缩到最小——只有业务逻辑没有基础设施代码。3.3 模块治理版本、依赖与灰度发布模块不是一次写完就完事。EverSpark Forge 内置模块治理机制语义化版本SemVer强制执行模块名后缀必须带版本号如copywriter_zh:v1.2.0。主版本号v1.x.x变更意味着input_schema或output_schema不兼容次版本号v1.2.x变更表示新增功能但向后兼容修订号v1.2.0仅修复 bug。编排器在加载工作流时会检查所引用模块版本是否满足1.2.0, 2.0.0这样的范围约束。依赖图谱自动生成每次模块注册Forge 会扫描其requirements.txt构建模块依赖图。当pydantic库爆出 CVE-2023-XXXXX 漏洞时系统能瞬间定位出所有受影响模块共 12 个并标记哪些模块的output_schema可能因 pydantic 版本升级而改变需人工复核。灰度发布通道新版本模块上线不直接替换旧版。而是先注册为copywriter_zh:v1.3.0-beta然后在特定工作流中通过module_version_override参数指定使用 beta 版。我们设置 5% 的流量走 beta同时对比word_count和readability_score的分布变化。只有当指标稳定且无异常日志才将 beta 标签移除正式发布。4. 编排系统实操从零搭建一个“专利摘要生成”工作流4.1 工作流需求拆解为什么专利场景特别考验编排能力专利文档有三大特性长文本动辄 50 页、强结构摘要/权利要求/说明书分节、高专业性术语密集、逻辑嵌套深。这导致单纯用大模型“喂全文”效果极差——上下文窗口溢出、关键条款被稀释、法律效力表述失准。EverSpark Forge 的解决方案是把专利处理拆解为原子化、可验证的步骤。目标工作流用户上传 PDF 专利文件 → 自动提取文本 → 识别章节结构 → 生成技术摘要Technical Summary→ 生成权利要求摘要Claims Summary→ 合并输出结构化 JSON。这个流程看似线性实则充满分支判断如果 PDF 提取失败扫描件无文字则触发 OCR 模块如果章节识别置信度 0.7则启用备用规则引擎正则关键词如果技术摘要生成结果中未包含“本发明解决的技术问题”这一必述要素则强制重试并降低 temperature。这些判断逻辑全部由编排器在 DAG 边缘定义而非写死在某个模块里。4.2 DAG 定义详解YAML 中的工程逻辑以下是patent_summary_workflow.yaml的核心片段已脱敏name: patent_summary_v2 description: 专利文档结构化摘要生成工作流 version: 2.1.0 nodes: - id: pdf_extractor module: pdf_extractor:v1.4.0 config: timeout_ms: 60000 ocr_fallback: true # 允许 fallback 到 OCR - id: section_classifier module: section_classifier:v0.9.2 config: model: bert-base-chinese-patent confidence_threshold: 0.7 - id: tech_summary_gen module: llm_summarizer:v2.3.1 config: model: qwen2-72b temperature: 0.2 max_tokens: 1024 prompt_template: tech_summary_ja.prompt - id: claims_summary_gen module: llm_summarizer:v2.3.1 config: model: qwen2-72b temperature: 0.1 max_tokens: 2048 prompt_template: claims_summary_ja.prompt - id: structure_validator module: json_validator:v1.0.0 config: schema_path: patent_output_schema.json edges: # 主路径PDF → 文本 → 分类 → 技术摘要 - from: pdf_extractor to: section_classifier data_mapping: text_content: text file_hash: hash # 分支1分类失败时走规则引擎 - from: section_classifier to: rule_based_sectioner condition: output.confidence 0.7 data_mapping: raw_text: text # 分支2分类成功时走 LLM 摘要 - from: section_classifier to: tech_summary_gen condition: output.confidence 0.7 data_mapping: tech_section: output.technical_section problem_statement: output.problem_statement # 技术摘要后必须验证必述要素 - from: tech_summary_gen to: tech_element_checker data_mapping: summary: output.content # 验证失败则重试成功则继续 - from: tech_element_checker to: tech_summary_gen condition: output.missing_elements.length 0 retry_policy: max_attempts: 2 backoff_factor: 1.5 # 最终合并 - from: tech_summary_gen to: final_merger data_mapping: tech_summary: output.content - from: claims_summary_gen to: final_merger data_mapping: claims_summary: output.content # 最终输出必须通过结构验证 - from: final_merger to: structure_validator data_mapping: output: output这个 YAML 文件就是整个工作流的“源代码”。它不包含任何 Python 逻辑却定义了完整的业务规则、容错策略、重试机制。编排器将其加载后会自动生成执行计划并在运行时实时渲染 DAG 图Web UI 中可查看。4.3 实操部署三步完成本地验证第一步启动 Forge 编排器单机模式# 下载预编译二进制Linux x64 wget https://forge.everspark.dev/releases/everforge-v1.8.0-linux-amd64.tar.gz tar -xzf everforge-v1.8.0-linux-amd64.tar.gz ./everforge server --config ./config.yamlconfig.yaml中关键配置orchestrator: mode: standalone # 开发模式所有组件单进程 event_bus: type: redis url: redis://localhost:6379/0 modules: registry: type: local path: ./modules workflows: path: ./workflows第二步注册模块以pdf_extractor为例# 启动模块服务假设已在 8080 端口运行 curl -X POST http://localhost:8080/register \ -H Content-Type: application/yaml \ -d ./modules/pdf_extractor/module_config.yaml编排器会立即发起健康检查/health并校验schema.yaml。如果一切正常返回{status:registered,module_id:pdf_extractor:v1.4.0}。第三步触发工作流并调试curl -X POST http://localhost:8000/workflows/patent_summary_v2/trigger \ -H Content-Type: application/json \ -d { input: { pdf_url: https://example.com/patent.pdf, user_id: u_12345 } }返回的execution_id可用于查询状态curl http://localhost:8000/executions/abc123/status # 返回包含每个节点的 start_time, end_time, duration_ms, status, output_preview调试时我习惯打开--debug模式编排器会将每个节点的完整输入输出脱敏后写入本地日志方便逐帧分析。5. 常见问题与避坑指南来自 200 次线上故障的总结5.1 模块开发高频陷阱与解决方案问题现象根本原因解决方案我的实操心得模块注册成功但工作流触发时报“Schema not found”module_config.yaml中input_schema_path指向的文件在模块容器内不存在或路径大小写不一致Linux 区分大小写在模块 Dockerfile 中COPY命令后加RUN ls -la /app/schema.yaml确认路径使用绝对路径而非相对路径我第一次遇到时花了 3 小时排查最后发现schema.yaml被.gitignore忽略了根本没 COPY 进镜像。现在所有模块 CI 流程第一步就是docker build --no-cache后docker run --rm image ls /app/模块健康检查/health返回 200但实际 invoke 时超时/health只检查进程存活未检查模型加载状态。大模型加载可能耗时 30 秒而健康检查超时设为 5 秒在/healthhandler 中加入model_ready标志位该标志在模型加载完成后才置为 True健康检查必须等待此标志我们给llm_summarizer模块加了model_loading_timeout: 120s配置项编排器会等待此时间后再判定健康状态。否则Kubernetes 会因健康检查失败反复重启 Pod形成雪崩DAG 中两个模块输出同名字段导致 data_mapping 错乱data_mapping使用点号路径如output.data.text但若模块 A 输出{ text: abc }模块 B 也输出{ text: def }编排器无法区分强制要求模块在output_schema中使用唯一前缀如tech_summary_text,claims_summary_text编排器在加载时校验所有模块输出字段名全局唯一这个坑让我们重构了 8 个模块。现在 Forge CLI 提供forge module lint命令自动扫描所有已注册模块的输出字段冲突5.2 编排系统性能瓶颈与调优实录瓶颈1高并发下 DAG 解析成为 CPU 瓶颈当 QPS 200 时编排器 CPU 使用率飙升至 95%主要消耗在 YAML 解析和 JSON Schema 校验上。调优方案将工作流 YAML 编译为 Protobuf 二进制格式.pb加载时直接反序列化解析耗时从 12ms 降至 0.8msSchema 校验改用fastjsonschema替代jsonschema验证速度提升 3.7 倍对常用工作流如patent_summary_v2启用内存缓存TTL 24 小时缓存命中率 99.2%。注意Protobuf 编译需在 CI 中完成禁止手动修改.pb文件。我们用buf工具管理 schema确保前后端定义一致。瓶颈2事件总线堆积导致流程延迟当 OCR 模块批量处理大 PDF 时单个请求产生 50 个事件每页 OCR 完成一个事件Redis Streams 消费滞后。调优方案引入事件批处理OCR 模块完成整份文档后才发布一个document_ocr_complete事件而非每页一个为高吞吐事件如node_complete单独配置 Redis Stream与低频事件如workflow_error物理隔离消费者端采用XREADGROUP的COUNT 100参数每次拉取 100 条事件批量处理。实测后事件端到端延迟从 800ms 降至 45ms。瓶颈3模块间网络调用成为最大延迟源模块间 HTTP 调用平均 RTT 15ms占整个工作流耗时的 65%。调优方案对于同一主机部署的模块启用 Unix Socket 通信httpunix:///var/run/module.sockRTT 降至 0.3ms对于必须跨主机的模块强制使用 gRPC over HTTP/2并启用双向流Bidirectional Streaming减少连接建立开销编排器内置连接池对每个模块 endpoint 维护 50 个长连接避免频繁握手。这个优化让“专利摘要”工作流 P95 耗时从 3.2s 降至 1.1s。5.3 安全与合规红线我们绝不妥协的三条铁律所有模块的输入输出必须经过敏感词过滤可选开关Forge 提供sensitive_filter模块集成开源词库如cn-sensitive-words可在工作流任意节点后插入。它不修改原始输出而是生成filtered_output和filter_report含命中词、位置、置信度。法律团队要求所有面向公众的文案生成工作流必须启用此模块并将filter_report存入审计日志。我们从未关闭它即使影响 3% 的吞吐量。模块不得访问外部网络除非显式声明默认情况下所有模块容器的网络 namespace 被限制为localhost和host.docker.internal。若模块需调用第三方 API如天气服务必须在module_config.yaml中声明external_network: true并经安全团队白名单审批。去年我们拦截了 17 个未经审批的external_network: true请求其中 3 个试图连接可疑域名。所有大模型调用必须记录 token 使用量与成本估算每个模块在output_schema中必须包含token_usage字段prompt_tokens,completion_tokens,total_tokens编排器据此计算预估成本按云厂商公开价格表。这些数据实时推送至财务系统部门负责人可随时查看“专利摘要”工作流本月消耗了多少美元。透明的成本可见性倒逼团队持续优化 prompt 和模型选型。6. 扩展与演进EverSpark Forge 的下一步EverSpark Forge 不是一个终点而是一个持续演化的工程基座。接下来半年我们的三个确定性方向是第一模块市场Module Marketplace的私有化落地。我们已开发出模块打包工具forge-pack可将模块及其依赖、schema、文档一键打包为.forge文件类似 VS Code 的.vsix。企业客户可以将自研模块如内部风控模型打包上传与 Forge 官方模块如pdf_extractor在同一 UI 中搜索、安装、更新。所有通信加密元数据签名杜绝供应链攻击。这个市场不对外销售只服务于私有化部署客户。第二编排器的“策略即代码”Policy-as-Code增强。当前的condition表达式如output.confidence 0.7是简单布尔表达式。下一步将支持基于 Rego 语言的策略引擎允许定义复杂规则# 专利摘要必须包含“技术问题”、“技术方案”、“有益效果”三要素 deny[msg] { input.workflow patent_summary_v2 not input.output.tech_summary contains 技术问题 msg : 技术摘要缺失技术问题要素 }策略将与工作流 YAML 一同存储、版本化、灰度发布。第三与 IDE 深度集成实现“编排即开发”。我们正在开发 VS Code 插件支持在编辑器内实时渲染 DAG 图点击节点跳转到对应模块代码输入input_schema示例数据一键触发本地模拟执行查看各节点输出自动生成单元测试桩mock 模块依赖覆盖率报告直接嵌入编辑器。目标是让 AI 工程师像写普通后端服务一样高效开发、调试、交付编排逻辑。我自己在实际使用中发现最被低估的价值不是技术上的模块化或编排而是心理安全感——当你知道每个 AI 调用都遵循契约、每个失败都有明确归因、每个变更都可灰度验证那种面对黑盒大模型时的焦虑感会实实在在地消失。EverSpark Forge 不是让你“更自由”而是给你一种“可控的自由”。它不承诺消除所有限制但确保你知道限制在哪里、为什么存在、以及如何在限制内创造最大价值。