核心内容摘要
【Seedance 2.0算力成本优化白皮书】:20年架构师亲授3类GPU调度降本法,实测单任务成本直降67.3%
如何监控运行状态DeepSeek-R1日志分析教程
为什么需要关注日志——不只是“跑起来”更要“稳得住”你刚把 DeepSeek-R1 (
5B) 拉起来输入“鸡兔同笼怎么解”页面秒回一串清晰的分步推导——太棒了但下一秒你刷新页面发现卡在加载图标或者连续问三个问题后响应时间从800ms跳到
2秒又或者某天重启后Web界面干脆打不开……这时候光靠“试试看”和“重启大法”已经不够用了。
日志不是程序员的黑匣子而是模型服务的“健康体检报告”。
它不告诉你“答案对不对”但它会如实记录模型加载时有没有缺文件、权限够不够、显存/内存是否告警每次请求进来系统花了多少毫秒在加载tokenizer、多少毫秒在推理、哪一步悄悄超时了是用户同时发了10个请求压垮了CPU还是某个长文本触发了未处理的异常中断甚至能帮你发现原来你一直用的HTTP端口被另一个程序占用了只是之前没报错只默默降级成单线程响应。
本教程不讲抽象概念只带你做三件事看懂默认日志里每一行在说什么不用背术语快速定位最常见的5类运行异常卡顿、崩溃、慢响应、启动失败、界面空白用3条命令1个配置修改让日志变成你的“运维小助手”
日志从哪里来先找到它的“出生地”DeepSeek-R1-Distill-Qwen-
5B 的日志输出路径取决于你用哪种方式启动。
别急着翻文档我们按最常见场景直接定位
1 如果你是用python app.py启动的开发调试最常用日志默认直接打印在终端窗口里像这样INFO: Started server process [12345] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://
127.
0.
1:8000 (Press CTRLC to quit) INFO:
127.
0.
1:56789 - POST /v1/chat/completions HTTP/
1 200 OK DEBUG: Input tokens: 42, Output tokens: 156, Inference time: 2842ms注意关闭终端 日志消失。
所以第一步先把它存下来# 把实时日志保存到文件后台运行Linux/macOS nohup python app.py r1-runtime.log 21 # Windows 用户可用在命令提示符中 python app.py r1-runtime.log 21小贴士21的意思是“把错误信息也一起存进去”否则你可能错过关键报错。
2 如果你是用 Docker 启动的推荐生产环境日志就藏在容器内部但不用进容器翻文件——直接用 Docker 命令实时查看# 查看最近100行适合快速扫一眼 docker logs --tail 100 deepseek-r1 # 实时跟踪新日志像看直播一样 docker logs -f deepseek-r1 # 查看某段时间的日志比如今天上午9点后的 docker logs --since
T09:00:00 deepseek-r1验证技巧在Web界面随便问一个问题立刻执行docker logs -f deepseek-r1 | grep Inference如果看到带毫秒数的那行说明日志通路已确认打通。
3 如果你改过启动脚本或用了其他框架如 Ollama、Text Generation WebUI别慌——所有主流方案都遵循一个铁律日志一定输出到标准输出stdout或指定文件。
打开你的启动命令或配置文件找这几个关键词--log-level、LOG_LEVEL→ 控制日志详细程度--log-file、LOG_FILE→ 明确指定了日志存哪或| tee→ 表示重定向到了文件或管道找不到那就用最笨也最可靠的办法# 找出进程ID ps aux | grep deepseek\|app.py\|uvicorn # 查看该进程打开了哪些文件日志文件通常在这里 lsof -p PID | grep log
日志里到底在说啥3分钟看懂核心字段刚打开r1-runtime.log满屏 INFO/DEBUG/WARNING像天书我们只盯最关键的5类信息每类配真实例子
1 启动阶段它“醒没醒过来”INFO: Application startup complete. INFO: Uvicorn running on http://
127.
0.
1:8000正常信号看到这两行说明服务已就绪可以访问网页。
ERROR: Exception in startup event handler ERROR: FileNotFoundError: [Errno 2] No such file or directory: models/qwen
5b危险信号“FileNotFoundError”直指模型文件路径错误。
检查app.py里model_path是否写错或文件是否真在那个位置注意大小写、斜杠方向。
2 请求处理每一次提问它“干了什么”INFO:
127.
0.
1:43210 - POST /v1/chat/completions HTTP/
1 200 OK DEBUG: Input tokens: 38, Output tokens: 142, Inference time: 2156ms解读
127.
0.
1是你的本地访问200 OK表示成功返回Input tokens: 38 你输入的问题被切成了38个词元越长的问题数字越大Inference time: 2156ms 真正“思考”的时间是
16秒CPU上
5B模型2秒内属优秀水平。
3 性能瓶颈为什么突然变慢了WARNING: CPU usage 95% for 30s. Consider reducing concurrent requests. DEBUG: Queue wait time: 4820ms before processing request #7这两行是黄金线索第一行警告CPU长期满载说明不是模型慢是你的CPU被榨干了第二行暴露真相第7个请求在队列里等了近5秒才轮到它——你可能同时开了8个浏览器标签狂刷问题。
4 异常中断它“倒下”前的最后一句话ERROR: RuntimeError: expected scalar type BFloat16 but found Float32 CRITICAL: Process finished with exit code 1典型环境冲突你装的PyTorch版本不支持BFloat16常见于老款CPU需降级PyTorch或加启动参数--dtype float32。
5 Web界面空白先查这行INFO:
127.
0.
1:56789 - GET / HTTP/
1 404 Not Found404 不是前端问题说明后端根本没把/路由注册好——大概率是app.py里漏写了app.get(/)或静态文件路径配置错了。
记住这个心法日志里第一个 ERROR/WARNING 出现的位置就是故障源头后面跟着的 INFO/DEBUG是它临终前的“遗言”。
实战5分钟搞定3类高频问题现在我们用真实操作代替理论。
打开你的终端照着做
1 问题Web界面打不开浏览器显示“连接被拒绝”排查步骤先确认服务是否在运行lsof -i :8000 # Linux/macOS看8000端口有没有进程占用 netstat -ano | findstr :8000 # Windows如果没结果 → 服务根本没启动。
执行python app.py 21 | head -n 20看最后几行有没有Uvicorn running on...。
如果没有重点检查OSError: [Errno 98] Address already in use—— 端口被占换端口启动python app.py --port
8
2 问题提问后一直转圈等1分钟才返回或直接超时排查步骤实时盯日志tail -f r1-runtime.log | grep -E (Inference|Queue|ERROR)发一个问题观察如果Inference time动辄5秒以上 → CPU确实吃紧关掉其他程序或限制并发见下节如果Queue wait time很高但Inference time很低 → 你一次发太多请求加限流# 在 app.py 里找到 uvicorn.run()加参数 uvicorn.run(app, host
0.
0.
0, port8000, workers1, limit_concurrency
3)
3 问题偶尔返回乱码、空回复或数学题算错这不是模型能力问题是编码/截断陷阱查日志里是否有UnicodeDecodeError→ 输入文本含不可见控制字符复制时粘贴了隐藏符号查是否有max_new_tokens16→ 这个值太小数学证明被硬生生截断。
在代码里搜max_new_tokens改成256或512查是否有temperature
0→ 完全确定性输出反而让逻辑链僵化。
日常使用建议temperature
7。
让日志更好用3个立竿见影的优化默认日志够用但想省力这3招马上提升效率
1 开启详细日志只需改1行代码打开app.py找到类似logging.basicConfig()或logger.setLevel()的地方改成import logging logging.basicConfig( levellogging.DEBUG, # 把 INFO 改成 DEBUG format%(asctime)s | %(levelname)-8s | %(name)s | %(message)s, datefmt%H:%M:%S )效果你会看到 tokenizer 加载耗时、KV Cache 内存占用、甚至每个 token 的生成概率——对调优极有用。
2 自动切割日志文件防硬盘爆满用 Python 自带的RotatingFileHandler替换原来的文件输出from logging.handlers import RotatingFileHandler handler RotatingFileHandler( r1-runtime.log, maxBytes10*1024*1024, # 单个日志最大10MB backupCount5 # 最多保留5个旧日志 )
3 关键指标一键提取告别手动翻写个3行脚本check_status.py每次运行直接汇报健康度import re with open(r1-runtime.log) as f: log f.read() print(f 最近100次平均响应: {round(float(re.findall(rInference time: (\d)ms, log)[-100:])[-1],
}ms) print(f 错误次数: {len(re.findall(rERROR|CRITICAL, log))}) print(f 当前负载: {len(re.findall(rQueue wait time, log))} 个排队请求)
6.
总结日志不是终点而是你掌控服务的起点你不需要成为运维专家也能用好日志启动时看最后10行——确认Uvicorn running和端口正确卡顿时tail -f | grep Queue——一眼识别是CPU瓶颈还是请求堆积报错时找第一条ERROR——90%的问题根源就藏在它上面那行日常加--log-level DEBUG——多出来的信息远比你想象中更有价值学会用grep和head/tail——这是比任何GUI工具都快的“日志显微镜”。
DeepSeek-R1 (
5B) 的魅力不仅在于它能在CPU上跑出逻辑链推理更在于它足够透明——所有行为都诚实地写在日志里。
你不需要猜只需要读。
现在打开你的终端执行tail -f r1-runtime.log再问它一个问题。
这一次你看到的不再是滚动的文字而是服务的心跳。