实验 01 — 环境配置¶
目标: 设置 Python 技术路线用于 GitHub Copilot SDK,使用 Agent HQ 演示应用作为 SDK 会话、流式传输和示例的可执行车辆。
用时: ~15 分钟
前置条件¶
只需要一个实施路线来完成实验。此页面使用了src/AgentOrchestrator-python/下的Python子项;.NET路线仍然保留在src/AgentOrchestrator/下。
安装这些内容之前:
- Python 3.11 或更高版本
- uv 用于依赖管理和命令执行
- GitHub Copilot CLI, 已登录
git,curl,和jq
⚠️ 对于本技术路线,您 不需要 .NET SDK。Python SDK 包名为 github-copilot-sdk 版本 1.0.9,导入时使用 copilot,项目在 pyproject.toml 中锁定。
步骤 1 — 克隆并检查¶
The Python 实现与 .NET 实现并存:
阅读 Python 技术路线概览,以获取完整的地图:
src/AgentOrchestrator-python/README.md
它镜像了 .NET 应用的每个功能:相同的 API 契约、相同的种子数据、相同的故意代码异味,以及相同的 GitHub Copilot SDK 学习路径。
⚠️ 选择一个技术路线。 您可以单独工作于 Python 或 .NET 而无需安装两者。它们也可以同时运行,因为端口不重叠:.NET 使用 5050 和 5051,而 Python 使用5070 用于 API 和 UI。
步骤 2 — 恢复依赖¶
从仓库根目录:
uv sync 创建虚拟环境并安装应用程序依赖项、开发依赖项、FastAPI、SQLModel、pytest、ruff 和 GitHub Copilot SDK。
⚠️ 除非命令明确要求你改变目录,否则请在 src/AgentOrchestrator-python 中运行 Python 命令。没有解决方案文件,也没有根级别的 Python 包可以运行。
步骤 3 — 运行测试¶
为了紧凑的 CI 风格检查:
预期结果:30个测试通过。一个验证运行产生了:
这是14个领域测试和12个MCP服务器测试——两者一一对应.NET套件——再加上4个仅限Python的契约测试,以保护浏览器/API请求的结构。
记得那个数字。后面的实验会要求你在不破坏这30个测试的情况下扩展行为。
第 4 步 — 运行 代码检查器¶
预期结果:
The linter 配置位于 pyproject.toml。
步骤 5 — 启动 API 和 UI¶
In你的第一个终端:
打开 http://localhost:5070。你应该看到空的聊天界面:

⚠️ 与 .NET 路线不同,没有 单独的 UI 服务器。FastAPI 从同一个进程的端口 5070 上提供 REST API、聊天流、静态 HTML 和 JavaScript。
💡 为什么不是5060,而是5070? Chrome、Edge 和 Firefox 拒绝打开端口5060
— 这是SIP端口,并且位于浏览器禁止访问的端口列表中,因此页面 ERR_UNSAFE_PORT 即使 curl 也能够正常工作。如果更改端口,请避免使用5060、5061和6000。
对于编辑刷新开发,添加 --reload:
⚠️ 端口已被占用? 之前的运行可能仍然在监听5070端口并提供过期代码。在重启之前,请先停止监听5070端口的进程。
第 6 步 — 验证健康端点¶
In另一个终端,仍然来自src/AgentOrchestrator-python:
预期结果:
{"status":"healthy","service":"CopilotChat","availableModels":["claude-haiku-4.5","gpt-4.1","gpt-5","claude-sonnet-4.5","claude-opus-4.5","gemini-2.5-pro"]}
这个端点不会调用模型。它证明了应用程序是可用的,并展示了如果实时模型发现失败使用的静态恢复目录。
第 7 步 — 验证 REST API¶
The Python API 保持与 .NET 一样的驼峰式 JSON 契约。这意味着 customerId, productCategory, 和 topFeatures, 不是 Python 内部的 customer_id, product_category, 和 top_features。
运行:
curl -s http://localhost:5070/api/transactions | jq 'length'
curl -s http://localhost:5070/api/segments | jq 'length'
curl http://localhost:5070/api/segments/predict/C003
预期事实:
GET /api/transactions返回 10 行GET /api/segments返回4行数据- 预测调用返回:
{"customerId":"C003","predictedSegment":"High Value","confidence":0.89,"topFeatures":["high_total_spend","multi_category","total_1700"]}
那个驼峰格式的契约已经在
app/models.py
所以相同的 curl 示例适用于所有技术路线。
第 8 步 — 验证流式传输工作¶
This证明了Copilot SDK已连接,CLI已登录,并且API可以将模型输出流式传输回浏览器或终端。
curl -sN -X POST http://localhost:5070/api/chat/stream \
-H 'Content-Type: application/json' \
-d '{"prompt":"Reply with exactly: streaming works","model":"claude-haiku-4.5"}'
预期的流式传输结构:
三件事情很重要:每个事件开始时都有data:,每个事件后面跟着一个空行,流结束时以data: [DONE]结尾。
⚠️ 该字段是 prompt,而不是 message。未识别的键会被忽略,因此一个拼写错误会导致发送一个空的提示,你将收到一个通用的问候而不是一个错误。
⚠️ 如果您看到 data: {"error": "..."} ,服务器已经接收到 SDK,但 SDK 无法完成请求。常见的原因包括未登录到 Copilot CLI 或选择了您账户无法使用的模型。
步骤 9 — 验证 SDK 实验样本¶
每个后来的 Python SDK 实验都使用该模块。现在运行一个真实的示例: sdk_labs 模块。Run one real sample now:
预期结果:
== Lab 03: tools ==
Model: claude-haiku-4.5
Prompt: How much has customer C003 spent in total?
[tool] get_customer_total(C003) -> $1,700.00
Assistant: Customer C003 has spent a total of **$1,700.00** across 2 transactions.
命令分发器位于
sdk_labs/__main__.py.
后续实验使用 uv run python -m sdk_labs events, uv run python -m sdk_labs sessions以及 uv run python -m sdk_labs mcp.
第 10 步 —— 测试 UI¶
在浏览器中打开http://localhost:5070,打开模型下拉菜单并发送一条消息以观看SSE渲染路径。
💡 产品请求体使用了 prompt,匹配 ChatRequest。一个早期版本在这里发布的是 message;由于 Pydantic 漏失了未知的键,UI 流式传输了一个空提示的回复,并且没有任何内容大声失败。现在 tests/test_chat_contract.py 断言字段 app.js 发送的是 API 读取的字段。
✅ 检查点¶
你现在应该已经拥有:
- [x] Python依赖恢复完成
uv sync - [x] 30/30 测试通过
- [x] 通过摇晃
- [x] API 和 UI 在端口 5070 上一起运行
- [x] REST endpoints 返回 seeded camelCase 数据
- [x] 一个来自真实模型的真实流式传输响应
- [x] The SDK 实验样本可通过
uv run python -m sdk_labs ...
💡 拓展练习¶
查询模型端点,并统计您的账户提供的内容:
然后检查 fallback catalog 在
app/routers/chat.py.
The live list 是真相的来源;Lab 02 解释了为什么静态列表只是 fallback。