ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在 Flower AgentApp 中使用 OpenAI SDK:从运行时凭证注入到流式响应发布

在 Flower AgentApp 中使用 OpenAI SDK:从运行时凭证注入到流式响应发布 在 Flower AgentApp 中使用 OpenAI SDK从运行时凭证注入到流式响应发布【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower本文是一份面向 Flower 开发者的实战指南讲解如何在 Flower AgentApp 中借助 OpenAI Python SDK 发起模型请求Flower 会在 AgentApp 进程内提供与 OpenAI 兼容的 Responses 端点并注入其访问地址与凭据因此你的代码无需持有任何模型提供商的 API Key。读完本文你将掌握 AgentApp 模板的搭建、运行时环境变量的正确用法、流式事件向 Flower Chat 的发布机制、与 connectors 的协同方式以及对话历史的读取方法并能在当前仓库源码层面理解其底层实现。本文内容对应 Flower 的 AgentApp 能力当前仓库中 AgentApp 示例项目 将 Flower 目标版本锁定为1.35.0flwr-version-target 1.35.0OpenAI SDK 依赖区间为openai2.16.0,3.0.0。相关文档请参见 AgentApp 运行时原理 与 协作研究 Agent 教程。前置理解AgentApp 与 OpenAI 兼容的 Responses 端点AgentApp是一个 Flower 应用组件包含 Agent 的控制流模型应该做什么、可以调用哪些工具、工作何时完成。Flower 负责执行该应用并通过一个与 OpenAI 兼容的 Responses 端点为 AgentApp 提供模型访问能力connectors连接器与前端可见的事件则通过AgentSession暴露给应用代码。关键点在于模型请求的 URL 与凭据由运行时注入而不是由开发者在项目中配置。从源码看Flower 在执行 AgentApp 进程时通过_set_runtime_environment函数注入两个环境变量见 run_agentapp.pyos.environ[_RUNTIME_BASE_URL_ENV] f{scheme}://{address}/v1/runtime os.environ[_RUNTIME_API_KEY_ENV] token其中_RUNTIME_BASE_URL_ENV即FLWR_RUNTIME_BASE_URLRuntime API 的基础 URL_RUNTIME_API_KEY_ENV即FLWR_RUNTIME_API_KEY用于对该 AgentApp 进程发起的请求做鉴权。这两个变量只在 AgentApp 运行期间存在由 Flower 在执行器启动 AgentApp 进程时注入因此你的代码可以在运行时安全地读取它们。从 AgentApp 模板开始推荐直接从 Flower Hub 上发布的 AgentApp 模板创建项目$ uvx --from flwr1.35.0 flwr new flwrlabs/agent $ cd agent $ uv sync模板已经包含兼容的 Flower 与 OpenAI SDK 依赖见 hub/apps/agent/pyproject.tomldependencies [flwr1.35.0,2.0, openai2.16.0,3.0.0]如果你的项目是已经存在的 AgentApp需要在pyproject.toml中设置 Flower 目标版本[tool.flwr.app] flwr-version-target 1.35.0然后更新依赖$ uv add flwr1.35.0,2.0 openai2.16.0,3.0.0flwr-version-target限定了应用所声明的运行时契约Flower 在构建 Flower App BundleFAB和运行时会校验这一版本约定。pyproject.toml中的[tool.flwr.app.components]一节还需要声明 AgentApp 对象的加载位置例如[tool.flwr.app.components] agentapp agent.agent_app:appmodule:attribute格式告诉 Flower 从哪里导入AgentApp对象详见 AgentApp 运行时原理。重要不要在项目或其配置中添加任何模型提供商的 API Key。模型请求的凭据由 Flower 运行时注入项目本身不应携带密钥。在 AgentApp 内创建 OpenAI 客户端Flower 启动 AgentApp 进程时会注入两个环境变量FLWR_RUNTIME_BASE_URLFlower 内部 Runtime API 的基础 URLFLWR_RUNTIME_API_KEY对该 AgentApp 进程发起的请求进行鉴权。将两者原样传给OpenAI不要做任何修改。SDK 在创建 response 时会自动拼接/responses路径client OpenAI( base_urlos.environ[FLWR_RUNTIME_BASE_URL], api_keyos.environ[FLWR_RUNTIME_API_KEY], max_retries0, )这里有两个值得注意的实践在 main 函数内部创建客户端这样flwr build等命令在导入模块时不会因为缺少正在运行的 Flower 运行时而失败——环境变量只在 AgentApp 运行时才存在。设置max_retries0因为每一次 Responses 请求都会创建一个 Flower 模型任务model task。如果 SDK 自动重试可能会把同一个任务创建多次。区分两个容易混淆的变量FLWR_RUNTIME_BASE_URL 不是 FLWR_MODEL_API_ENDPOINT。前者只在运行中的 AgentApp 内部可用指向 Flower 自身的运行时端点后者用于为自托管的 SuperLink 配置上游模型提供商属于 AgentApp 代码之外的运行时配置。从源码可以印证这一设计_set_runtime_environment将端点设置为{scheme}://{address}/v1/runtime其中address来自运行时地址token来自任务凭据——两者都在进程启动时由执行器注入属于运行期环境而非应用配置。将响应流式发布给 Flower 客户端Flower 的运行时在 AgentApp 主动发布之前会一直把模型任务的事件保持为私有。因此如果你调用的是 SDK 的流式接口需要遍历流中的每个事件并通过agent.events.emit将其发布Flower Chat 和浏览器才能渲染出响应内容import os from flwr.agentapp import AgentApp, AgentSession from flwr.app import Context from openai import OpenAI MODEL openai/gpt-5.6-sol app AgentApp() app.main() def main(agent: AgentSession, context: Context) - None: Send the configured input to the model. prompt context.run_config.get(agent.input) if not isinstance(prompt, str) or not prompt.strip(): raise ValueError(agent.input must be a non-empty string) client OpenAI( base_urlos.environ[FLWR_RUNTIME_BASE_URL], api_keyos.environ[FLWR_RUNTIME_API_KEY], max_retries0, ) stream client.responses.create( modelMODEL, inputprompt.strip(), streamTrue, ) output_text [] for event in stream: agent.events.emit(event.to_dict()) if event.type in {error, response.failed}: raise RuntimeError(fModel response failed: {event}) if event.type response.output_text.delta: output_text.append(event.delta) print(.join(output_text))event.to_dict()把 SDK 的类型化事件转换为 Flower 期望的 JSON 对象应用同时收集文本增量delta这样完整的回答会出现在 AgentApp 的日志中。关于流式事件还有两点值得说明运行时只识别部分请求字段。Flower 的 Responses 端点支持model、input、stream、tools、tool_choice、instructions、previous_response_id、reasoning、max_output_tokens、metadata与text其中model必须是非空字符串input可以是文本或输入项序列详见 AgentApp 运行时原理。默认模型提供商api.flower.ai目前不支持通过previous_response_id继续对话需要后续请求时请从存储的消息中重建input协作研究 Agent 教程 中的「Rebuild conversation input」一节提供了完整示例。发布 AgentApp 自行生成的文本print(...)只会写入 AgentApp 的日志并不会向 Flower Chat 发布一条 assistant 响应。如果 AgentApp 已经生成了面向用户的最终文本且该文本并非来自 SDK 流需要依次发布一个输出增量事件和一个完成事件assistant_text Hello from the AgentApp! agent.events.emit( { type: response.output_text.delta, delta: assistant_text, } ) agent.events.emit({type: response.completed})输出增量事件response.output_text.delta把 assistant 文本加入运行事件流完成事件response.completed告诉 Flower Chat 以及其他运行事件客户端响应已经结束。对于模型生成的输出更推荐直接转发原始的 SDK 事件这样客户端能收到完整的响应事件序列。需要明确两点agent.events.emit(...)发布的是结构化事件只有运行事件客户端能识别为响应输出的事件类型才会被渲染为 assistant 文本发布这些事件会使其通过agent.events.get_trace()在后续运行中可见但不会把它们加入Context。从实现上看RuntimeAgentEvents.emit会校验事件必须包含非空的字符串type字段然后以紧凑 JSON 形式进入后台发布队列由名为flwr-agent-event-publisher的后台线程批量上报到运行时见 session.py。与 connectors 配合使用模型请求走client.responses.create而连接器的发现与执行仍然落在AgentSession上agent.connectors.tools(...)返回可供 SDK 使用的工具模式tool schemasagent.connectors.call(...)执行模型请求的函数调用agent.events.emit(...)向运行事件流发布事件agent.events.get_trace()读取当前 run series 中每一次运行的事件。SDK 返回的是类型化输出项。将函数调用项function-call item传给agent.connectors.call之前先用item.to_dict()转换为普通字典。关于完整的有界工具循环bounded tool loop参见 构建协作研究 Agent。AgentSession在框架中的抽象定义位于 base.pyAgentConnectors提供tools(names)与call(tool_call)AgentEvents提供get_trace()与emit(event)。运行时实现位于 session.py其中agent.connectors.tools(TOOL_REFS)可以一次返回某个内置引用对应的工具也可能返回某个账户连接器如slack对应的多个动作工具。读取对话历史在调用 AgentApp 之前Flower 会把非空的agent.input记录为一条 user-message 事件。使用agent.events.emit(...)发布的事件以及连接器活动都会存放在同一条 run-series trace 中。在后续某次运行开始时读取该 tracetrace agent.events.get_trace() for entry in trace: event_type entry[event] event_data entry[data]每个条目都是一个信封envelope除event与解析后的 JSONdata外还包含id、timestamp、run_id和task_id字段这一结构正是RuntimeAgentEvents.get_trace从GetRunSeriesEvents响应中构造出来的见 session.py。在构造下一次模型输入之前应当过滤掉连接器、推理reasoning、失败与未完成的事件——例如用户消息使用message事件而流式 assistant 文本使用response.output_text.delta与response.refusal.delta连接器与推理事件不应被当作对话消息。完整的「从 trace 重建用户与 assistant 消息」加载器见 构建协作研究 Agent其conversation_messages函数按run_id分组将每条用户消息与对应完成的 assistant 响应配成一轮对话并在遇到error、response.failed、response.incomplete时丢弃未完成的部分避免把失败响应当作成品答案回放给模型。对话连续性属于 AgentApp 的行为而非运行时的自动行为。只有当 AgentApp 需要超出事件 trace 之外的应用自定义状态时才使用Contextcontext.run_config存放来自pyproject.toml的默认配置与每次运行覆盖的融合结果context.state用于持久化 run series 的应用状态context.run_id标识当前运行。构建并运行 AgentApp$ uv run flwr build $ uv run flwr login supergrid $ uv run flwr run . supergrid --streamflwr build将项目打包为 Flower App BundleFABflwr login supergrid登录 SuperGridflwr run . supergrid --stream在 SuperGrid 上运行当前项目并以流模式输出。运行时在启动 AgentApp 时会注入上述两个环境变量。不要自行设置、记录或持久化FLWR_RUNTIME_API_KEY——它是一次运行专用的凭据只应被原样读入客户端。如需覆盖默认输入可参考 构建协作研究 Agent 中的用法$ uv run flwr run . supergrid \ --run-config agent.inputCompare two recent public explanations of federated AI. \ --stream故障排查针对 OpenAI SDK 客户端的常见问题ModuleNotFoundError: openai运行uv sync或手动添加 SDK 依赖openai2.16.0,3.0.0缺少运行时 URL 或密钥通过 Flower 运行应用而不是直接以 Python 模块方式启动——两个环境变量只由 Flower 运行时注入鉴权失败开启一次新的运行使用新运行注入的凭据凭据与运行绑定一次运行对应一套请求字段不受支持将请求与 AgentApp 运行时原理 中列出的受支持模型字段逐一比对。最后请记住这个端点的作用域仅限于正在运行的 AgentApp。它不是面向浏览器、外部服务或独立启动的 SDK 客户端的公开模型 API。从源码看整体运行机制把以上实践映射到框架源码可以形成一条完整链路见 run_agentapp.py执行器启动 AgentApp 进程通过_set_runtime_environment注入FLWR_RUNTIME_BASE_URL与FLWR_RUNTIME_API_KEY进程从pyproject.toml的[tool.flwr.app.components]读取agentapp module:attribute用load_app加载AgentApp对象Flower 构造RuntimeAgentSession封装RuntimeAgentConnectors与RuntimeAgentEvents并把它与融合后的Context一起传入app(agent..., context...)你的app.main()函数内创建 OpenAI 客户端、发起responses.create、把事件经agent.events.emit发布到运行事件流进程退出时Flower 将Context推送一次并记录运行是完成COMPLETED、失败FAILED还是被停止。AgentApp本身是一个极简的注册器app AgentApp()后用app.main()装饰器注册唯一的 main 函数__call__在运行时执行它见 agent_app.py。整个过程中你只需要关心AgentSessionconnectors 与 events和Contextrun_config / state / run_id两个入口——模型访问的复杂度被运行时与 OpenAI 兼容端点完全封装了。【免费下载链接】flowerFlower: A Friendly Federated AI Framework项目地址: https://gitcode.com/GitHub_Trending/flo/flower创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表