在 dltHub Platform 上部署 marimo Dashboard 并配置定时调度:LLM Zoomcamp dlt 工作坊实战指南
2026/9/17 7:25:48 网站建设 项目流程

在 dltHub Platform 上部署 marimo Dashboard 并配置定时调度:LLM Zoomcamp dlt 工作坊实战指南

【免费下载链接】llm-zoomcampLLM Zoomcamp - a free online course about real-life applications of LLMs. In 10 weeks you will learn how to build an AI system that answers questions about your knowledge base. Register here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/ll/llm-zoomcamp

本篇技术指南聚焦于 LLM Zoomcamp 2026 cohort 的 dlt 工作坊中"部署与调度"这一关键环节:当数据管线已经成功部署并写入云端存储之后,如何将 marimo 交互式 Dashboard 一并部署到 dltHub Platform、以运行模式分享给团队,并通过 cron 定时触发与job.success链式触发保持数据与报告的持续新鲜。读完本文,你将掌握__deployment__.py部署清单的组织方式、dlt.attach()在云端目标下的正确用法、uv run dlthub系列 CLI 的完整操作流程,以及平台级任务(Job)管理与调度的最佳实践。

本文基于 06-dashboard-deploy.md,并参考 05-deploy.md、07-where-to-go.md 以及 code/agent_traces_dashboard.py 等仓库源码展开。

背景:从"本地可用"到"云端共享"

在 dlt 工作坊的前序课程中,我们已经完成了两件事:

  1. 数据管线已部署并写入 playground lake:在 05-deploy.md 中,我们通过uv run dlthub loginuv run dlthub workspace connect将本地工作区连接到了 dltHub Platform,并把rest_api_pipeline.py的 destination 从duckdb切换为playground(一个托管的 S3 lake,数据可跨运行持久保存)。

  2. Dashboard 已本地可运行:在 03-debug-and-dashboard.md 中,我们构建了基于 marimo 的反应式报告agent_traces_dashboard.py,它通过dlt.attach()连接管线并以 SQL 数据单元 + Altair 图表单元的方式展示 Agent 日志分析。

但正如 05-deploy.md 开篇所强调的:本地 Dashboard 无法与团队分享。数据在云端、管线在云端,报告也必须搬到云端。本课(Part 2 的收尾)就是解决这一环:把 marimo Dashboard 部署到 dltHub Platform 并配置调度。

将 Dashboard 加入部署清单

dltHub 工作区脚手架(通过uvx dlthub-init@latest生成,见 01-overview.md)会创建一个__deployment__.py文件,它是云端部署的清单(deployment manifest),集中声明平台要运行的所有 Job(任务)与触发器。

要让平台识别 Dashboard,只需在__deployment__.py中导入 dashboard 模块并加入__all__

from agent_traces_dashboard import app as agent_traces_dashboard

这一步的实质是将 Dashboard 注册为一个交互式 Job(interactive job)。dltHub Platform 不仅能运行管线(pipeline),也能运行交互式应用——包括 marimo 笔记本和 Streamlit 应用。平台会以服务的形式启动这份报告,而不是像执行脚本那样跑一次就退出。

让 Dashboard 指向云端目标

本地开发时,Dashboard 默认从本地的 DuckDB 文件读取数据。部署到云端后,它必须读取部署环境里的数据,也就是 playground destination。

因此需要更新连接方式,在dlt.attach()中显式传入目标与数据集:

dlt.attach("agent_traces", destination="playground", dataset_name="agent_logs")

这里有一个值得注意的约束:部署笔记本(notebook)形式的 Job 时,destinationdataset_name必须显式传递给dlt.attach()。原因是部署环境没有本地开发时的默认配置上下文,若不显式指定,平台无法确定该从哪里读取数据。

对比本地写法可以更清晰地看出差异——本地 Dashboard(如 code/agent_traces_dashboard.py)只写dlt.attach("agent_traces")即可,而云端部署必须补全两个参数:

# 本地(开发环境,默认读本地 DuckDB) pipeline = dlt.attach("agent_traces") dataset = pipeline.dataset() # 云端(部署环境,必须显式指定目标与数据集) pipeline = dlt.attach("agent_traces", destination="playground", dataset_name="agent_logs")

部署并运行

修改完成后,执行标准的"部署—运行"循环:

uv run dlthub deploy uv run dlthub run
  • uv run dlthub deploy:将当前项目作为新版本发布到平台;
  • uv run dlthub run:在云端运行已注册的 Job。

05-deploy.md 强调:每次代码变更后都应重复这个 deploy-and-run 循环,确保云端始终运行最新版本。若你的目标 destination 切换为playground(deltalake 格式),部署时若检测到缺少deltalake依赖,deploy 步骤会自动把依赖写入pyproject.toml,此时重新执行 deploy 与 run 即可。

运行模式(Run Mode):给团队看的报告视图

部署完成后,在平台 UI 中打开这份笔记本,它会以**运行模式(run mode)**呈现,而非编辑模式(edit mode):

  • 所有代码单元都被隐藏;
  • 只展示报告与可视化结果(SQL 查询的结果、Altair 图表);
  • 这是你与团队分享的标准视图——观众看不到实现细节,只看到结论。

这正是 marimo 区别于 Jupyter 的优势所在(详见 03-debug-and-dashboard.md):marimo 每个笔记本本身就是普通 Python 脚本,单元间通过依赖关系自动重算,状态始终一致,因此天然适合作为可发布的报告载体。

数据与目标解耦:同一份代码,任意目标

本课文档特别指出:此时数据存放在 playground destination,但它完全可以是 MotherDuck、BigQuery、Snowflake,甚至是 LanceDB 这样的向量数据库

这是因为 dlt 的设计原则是"目标无关"——同一份管线代码,通过更换 destination 字符串与凭据,就能写入不同的目标系统(07-where-to-go.md 中同样重申:同样的管线代码可用于 Postgres、BigQuery、Snowflake、Redshift)。playground本质上是"命名目标"(named destination):开发时映射到 DuckDB,生产时映射到 S3 lake,但代码路径只有一条。Dashboard 的dlt.attach()因此也只需修改目标参数即可适配不同后端。

分享 Dashboard

部署完成后,有两种分享方式:

方式一:发布为公开 URL

uv run dlthub job publish agent_traces_dashboard

这会为 Dashboard 生成一个可公开访问的 URL,适合分享给外部协作者。

方式二:工作区内分享

通过平台自带的 Users and Roles(用户与角色)机制,在 workspace 内部共享。这种方式更可控,适合团队内部使用,可以精确控制谁能查看。

定时调度:让数据与报告持续保鲜

Pipeline 只跑一次是不够的——Agent 日志持续产生,需要定时重新拉取以保持数据新鲜。dlt 的调度通过声明式装饰器完成,无需任何外部调度器(如 cron 服务器)。

__deployment__.py中,为管线函数添加调度触发器:

from dlt.hub.run import trigger @run.pipeline("agent_traces", trigger=trigger.schedule("0 12 * * *")) def ingest_agent_logs(): ...

这里trigger.schedule("0 12 * * *")使用标准 cron 表达式,0 12 * * *表示每天中午 12:00 运行一次。调度信息以装饰器参数的形式声明在部署清单中,平台据此自动触发运行。

部署后,用如下命令确认调度是否生效:

uv run dlthub job list

该命令会列出当前工作区注册的全部 Job 及其调度配置。

链式触发(Followup Chains):先入库、再刷新报告

除定时调度外,平台还支持任务链(followup chains):让一个 Job 的成功触发另一个 Job。

一个典型场景是:先运行数据摄取管线,成功后自动运行 Dashboard Job 刷新报告。实现方式是利用job.success触发器把 Job 串联起来:

# 示意:ingest 成功 -> 触发 dashboard 刷新 @run.pipeline("agent_traces", trigger=...) def ingest_agent_logs(): ... @run.pipeline("agent_traces_dashboard", trigger=job.success("ingest_agent_logs")) def refresh_dashboard(): ...

从源码结构看,job.success这类链式触发器与trigger.schedule一样,都是通过dlt.hub.run暴露的声明式接口,统一作用于__deployment__.py中定义的 Job。

在平台 UI 中管理 Job

调度与运行管理并不局限于 CLI。dltHub Platform 的 UI 同样提供完整的 Job 管理能力:

  • 启动运行(start runs):手动触发某个 Job;
  • 取消运行(cancel runs):终止进行中的执行;
  • 管理调度(manage schedules):查看、暂停或修改 cron 触发器。

这意味着部署后的日常运维(看板刷新、异常重跑、调度调整)都可以在浏览器中完成,CLI 主要用于部署与状态确认。

与源码对照:Dashboard 在云端读取什么

为了理解部署后 Dashboard 实际渲染的内容,可以回到 code/agent_traces_dashboard.py 查看它的数据单元结构。这份 marimo 笔记本由若干成对的"SQL 数据单元 + Altair 图表单元"组成:

  • Log types and activity:按type统计记录数,并绘制Logs by Type柱状图;
  • Work by git branch:按git_branch统计记录数与usage__output_tokens输出 Token 消耗;
  • Content and sessions:查询logs__message__content子表(dlt 规范化后生成的子表)统计消息内容块类型,以及每个 session 的消息数分布。

其中查询语句直接体现了 dlt 规范化(normalization)的产物——嵌套对象message.content被展开为logs__message__content子表,usage对象则变成usage__output_tokens这类双下划线分隔的列(见 04-rest-api-pipeline.md)。部署到云端后,同样的查询只需把dlt.attach("agent_traces")换成指向 playground 的显式连接,报告即从云端 lake 读取数据。

小结与后续

至此,dlt 工作坊的完整链路已经闭环:

  1. 01-overview.md:脚手架与工具链准备;
  2. 02-filesystem-pipeline.md:本地 Claude 日志 → DuckDB;
  3. 03-debug-and-dashboard.md:调试管线 + 构建 marimo 报告;
  4. 04-rest-api-pipeline.md:REST API 管线拉取托管 Agent 轨迹;
  5. 05-deploy.md:管线部署到云端(playground lake);
  6. 本课(06):Dashboard 部署、运行模式分享、cron 调度与任务链。

围绕本课的几个关键技术点值得牢记:

  • 部署清单是单一入口__deployment__.py同时声明管线 Job、交互式 Dashboard Job 与调度触发器;
  • notebook 部署必须显式传参dlt.attach()需显式提供destinationdataset_name
  • 调度是声明式的:cron 表达式写在@run.pipeline(..., trigger=trigger.schedule(...))装饰器上,用uv run dlthub job list验证;
  • 链式触发自动化刷新job.success让"入库 → 刷新报告"自动串联。

若希望进一步优化,07-where-to-go.md 提供了清晰的进阶方向:将write_disposition="replace"dev_mode=True替换为基于游标列的增量加载(dlt.sources.incremental()+"merge"写入策略),使管线在百万行规模下依然高效——届时,配合本课的定时调度,你便拥有了一套生产级的、全自动的 Agent 日志分析系统。

【免费下载链接】llm-zoomcampLLM Zoomcamp - a free online course about real-life applications of LLMs. In 10 weeks you will learn how to build an AI system that answers questions about your knowledge base. Register here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/ll/llm-zoomcamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询