本文来自《AI 应用开发课程》月份 1 课程文档,已整理为网站文章版本。
学习目标
学完本节后,你应当能够:
- 为研发助手增加命令行入口。
- 让 CLI 只负责参数接收和结果展示。
- 保证 CLI 不复制业务逻辑。
前置知识
- 已完成项目需求与架构设计
1. 为什么要有 CLI
因为它是最快的使用与验证方式:
- 不需要前端
- 不需要接口调试工具
- 更适合研发场景
月份 1 用 CLI 可以快速验证核心服务是否合理。
2. CLI 层的职责
只做以下事情:
- 接收命令参数
- 调用 service
- 打印结果
不要:
- 直接拼模型请求
- 直接写工具注册逻辑
- 直接处理底层异常细节
3. 推荐命令设计
例如:
uv run python -m app.cli.main summarize-diff --file sample.diff
uv run python -m app.cli.main extract-todos --text "请实现登录接口并补测试"
4. 典型实现结构
app/cli/
├── __init__.py
└── main.py
main.py 中:
- 解析参数
- 创建 service
- 调用 service
- 打印结构化结果
5. 输出建议
CLI 输出要可读,但不要花哨。
建议至少输出:
- 功能名
- 输入摘要
- 模型输出
- 如果失败则输出错误信息
6. 实操任务
- 先做一个最小命令
- 把“抽取待办项”接入 CLI
- 再接一个“生成 commit message”或“总结错误日志”
7. 自测题
- 为什么 CLI 是月份 1 的理想第一入口?
- 为什么 CLI 不应该持有完整业务逻辑?
- CLI 层最应该复用哪一层?
8. 验收标准
- 至少一个命令可执行
- 能看到结构化输出
- 核心逻辑来自 service 层而不是 CLI 层
9. 本章与前文关系
上一章已经把综合项目的范围和架构定下来了。现在进入真正落地阶段时,最先做 CLI,而不是最先做 API,是一个非常刻意的教学选择。
原因很简单:
- CLI 更轻
- 调试成本更低
- 更适合快速验证业务层
这会帮助你先把核心业务跑顺,再去处理 HTTP 细节。
10. 本章在研发助手项目中的位置
CLI 是研发助手最贴近开发者工作流的入口。它特别适合:
- 本地快速调用
- 录屏展示
- 调试 Prompt 和 Tool Calling
- 在没有前端时先验证主链路
CLI 不是临时玩具,而是项目第一阶段最实用的入口。
11. 一个更完整的 CLI 文件级示例
app/cli/main.py
"""研发助手 CLI 入口。"""
from __future__ import annotations
import argparse
from app.clients.llm_client import LLMClient
from app.models import ChatMessage, ChatRequest
from app.services.chat_service import ChatService
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(description="rd-assistant CLI")
parser.add_argument(
"--task",
required=True,
help="请输入要让研发助手处理的任务文本",
)
return parser
async def run_task(task_text: str) -> None:
llm_client = LLMClient()
chat_service = ChatService(llm_client=llm_client)
request = ChatRequest(
messages=[
ChatMessage(role="system", content="你是一个严谨的研发助手。"),
ChatMessage(role="user", content=task_text),
]
)
response = await chat_service.chat(request)
print("=== 模型输出 ===")
print(response.answer)
def main() -> None:
parser = build_parser()
args = parser.parse_args()
import asyncio
asyncio.run(run_task(args.task))
if __name__ == "__main__":
main()
12. 逐段解释这份完整示例
为什么 CLI 层只解析参数
因为参数解析本身是入口职责,不应该和业务逻辑混在一起。
为什么 run_task 里直接组装 ChatRequest
因为 CLI 的职责是把用户输入变成业务层可接受的结构,而不是直接处理 HTTP 或模型细节。
为什么最终调用的是 chat_service.chat()
因为这正是你在为后面 FastAPI 入口做复用准备。
13. 一个更接近项目主线的增强方向
你可以继续增加不同命令,例如:
extract-todosgenerate-commit-message
但月份 1 建议保持一个简单原则:
- 命令数量可以慢慢加
- 核心 service 不要分裂成多套重复实现
14. 调试与排错:本章最常见问题
问题一:CLI 看起来能跑,但逻辑高度耦合
通常说明你把太多业务逻辑塞进了 main.py。
问题二:异步入口报错
通常是事件循环使用不当,或者把异步逻辑直接放到了同步流程里。
问题三:参数解析和业务结构没有对齐
这会让后面 FastAPI 接入时不得不重写一套转换逻辑。
15. 本章完成后你应该具备的能力
完成本章后,你应当做到:
- 能为综合项目提供一个最小 CLI 入口。
- 能让 CLI 复用核心 service。
- 能把“入口层薄、业务层厚”的原则落实到代码。
16. 从本章过渡到下一章的桥接说明
接下来进入 03-FastAPI入口实现.md。
因为你现在已经有了一条 CLI 驱动的主链路。下一步最自然的动作,就是让 FastAPI 去复用这条链路,把同样的能力暴露成服务接口。