☰
基于 Marvin 构建 Prefect 社区 Slack 智能机器人:完整部署指南与源码深度解析
2026/10/10 5:51:07 网站建设 项目流程
  • AI Agent
  • Agent 框架
  • AI 应用

【免费下载链接】marvin

an ambient intelligence library

项目地址:https://gitcode.com/gh_mirrors/ma/marvin
点击查看免费下载

本篇技术指南以仓库内 examples/slackbot/README.md 为主体骨架,结合examples/slackbot/目录下的完整源码(api.py、core.py、settings.py、slack.py 等)深度展开。读者将掌握:如何从零搭建一个具备长期记忆、用户画像、Prefect 知识检索、GitHub 问题搜索与社区线程检索能力的 AI Slack 机器人,理解其「FastAPI + Prefect Flow + pydantic-ai Agent + 向量存储」的整体架构,并能独立完成本地开发、配置、测试与生产部署。

项目定位:一个"有记忆、懂 Prefect"的 AI Slack 机器人

slackbot是 Marvin 仓库中一个完整可运行的生产级示例应用,定位是为 Prefect 社区 Slack 提供 AI 驱动的支持服务。它由 AI 模型(GPT-5 或 Claude 系列)驱动,具备两类核心能力:

  • 记忆能力:跨会话持久化用户画像(user facts),通过向量存储(TurboPuffer)实现用户上下文检索;
  • 领域知识能力:内置 Prefect 特定的知识检索工具,可搜索 Prefect 官方文档、GitHub issues、最新 release notes,并可通过外部 MCP 服务器检索社区 Slack 历史线程。

从源码结构看(examples/slackbot/pyproject.toml),它依赖marvin(工作区内置)、prefect>=3.6.12(Flow/Task 编排)、pydantic-ai(Agent 运行时)、raggy[tpuf](TurboPuffer 向量存储)、claude-agent-sdk(Claude 研究子代理)与logfire[fastapi](可观测性)。

项目结构:四个模块撑起一条完整事件处理链路

README 给出了顶层结构,结合源码可细化为:

examples/slackbot/ ├── src/slackbot/ │ ├── api.py # FastAPI 应用与 Slack 事件处理器(/chat 端点) │ ├── core.py # 数据库、Agent 与记忆管理(create_agent、build_user_context) │ ├── settings.py # 配置管理(环境变量 + Prefect Secrets/Variables) │ ├── __main__.py # 入口点(uvicorn 启动) │ ├── slack.py # Slack API 集成:发消息、取线程、进度消息、图片下载 │ ├── search.py # Prefect 知识检索(文档、CLI、release notes) │ ├── assets.py # 用户事实(user facts)的存储/读取/修正/删除 │ ├── research_agent.py # Claude Agent SDK 研究子代理 │ ├── strings.py # token 估算与截断工具 │ ├── wrap.py # Prefect 与 pydantic-ai 工具调用监控桥接 │ └── _internal/ # 内部实现:模板、线程状态、消息存储、个性化、可观测性等 ├── Dockerfile.slackbot # 生产容器镜像 ├── pyproject.toml # 依赖与打包配置 └── README.md

事件处理链路(源自 api.py):

  1. Slack 将事件 POST 到 FastAPI 的/chat端点;
  2. 端点解析SlackPayload,对url_verification返回challenge,对event_callback分发处理:team_join发送欢迎消息,其余走handle_messagePrefect Flow;
  3. handle_message(api.py)执行消息去重、频道限制检查、用户上下文构建、并发加载个人摘要与 Slack 线程上下文,最后调用run_agent执行 Agent 推理并回帖。

本地开发环境搭建

README 说明 slackbot 可以极简配置在本地运行。依赖安装(在仓库根目录执行):

uv sync --extra slackbot

该命令通过pyproject.toml中的[tool.hatch.build.targets.wheel]打包src/slackbot,并拉取 pyproject.toml 中声明的全部依赖(含marvin、prefect>=3.6.12、raggy[tpuf]等)。

启动机器人(另一终端):

uv run --extra slackbot -m slackbot

__main__.py(examples/slackbot/src/slackbot/main.py)在启动时从 Prefect Secret 加载 OpenAI/Anthropic API Key(缺少环境变量时),然后以uvicorn.run("slackbot.api:app", ...)启动 FastAPI 服务,test_mode开启时启用--reload热重载(reload 目录指向examples/slackbot)。

配置体系:环境变量 + Prefect Secrets/Variables 双通道

配置管理集中在 settings.py,核心类SlackbotSettings(BaseSettings)使用env_prefix="MARVIN_SLACKBOT_",支持.env文件。

必需配置(Prefect Secrets)

README 列出 5 个必需 Secret,建议在 Prefect Cloud 或本地 Prefect 服务器中通过 UI/CLI 配置:

Secret 名称用途
test-slack-api-tokenSlack Bot User OAuth Token(Bot Token,形如xoxb-...)
openai-api-keyOpenAI 模型密钥(使用 GPT 系列模型时)
anthropic-api-keyClaude 系列模型密钥
marvin-slackbot-github-tokenGitHub API Token,用于搜索 GitHub issues
tpuf-api-keyTurboPuffer 向量存储 API Key

源码印证:SlackbotSettings为每个 Secret 定义了默认名称字段(如github_token_secret_name、openai_api_key_secret_name、anthropic_key_secret_name);_apply_post_validation_defaults(settings.py)会在启动时若环境变量TURBOPUFFER_API_KEY缺失,则自动尝试Secret.load("tpuf-api-key")注入。

必需配置(Prefect Variables)

模型分层通过 Prefect Variables 配置,三个层级各司其职(README 注释 + settings.py 三处 property 共同印证):

Variable 名称用途默认值回退 Variable
marvin_bot_model主回答 Agent(产品面向的"人声")anthropic:claude-sonnet-5marvin_ai_model
marvin_utility_model结构化非语音工作:记忆综合、线程总结(便宜档)anthropic:claude-haiku-4-5marvin_memory_synthesis_model
marvin_research_modelClaude Agent SDK 研究子代理anthropic:claude-haiku-4-5无
marvin_system_prompt基础系统提示词覆盖DEFAULT_SYSTEM_PROMPT(定义于 _internal/templates.py)无
admin-slack-id管理员 Slack 用户 ID,用于创建讨论/错误时通知空(可选)无

关键机制:Provider 归一化。所有模型值支持完整的 pydantic-aiprovider:model字符串;若为裸名称,_ensure_provider(settings.py)自动按前缀映射:claude-*→anthropic:...,gpt-*→openai-responses:...(后者因为 OpenAI reasoning 模型在/v1/chat/completions上拒绝 function tools + reasoning 组合,必须走 Responses API)。

热更新系统提示词:marvin_system_prompt逐消息读取(_base_system_prompt见 core.py),修改后无需重新部署即可生效。

可选环境变量(MARVIN_SLACKBOT_ 前缀)

MARVIN_SLACKBOT_TEST_MODE=true # 启用热重载(开发模式) MARVIN_SLACKBOT_HOST=0.0.0.0 # 服务监听地址(默认 0.0.0.0) MARVIN_SLACKBOT_PORT=4200 # 服务端口(默认 4200) MARVIN_SLACKBOT_LOG_LEVEL=INFO # 日志级别(自动转大写) MARVIN_SLACKBOT_SLACK_API_TOKEN=xoxb-... # Slack Bot Token(或用 test-slack-api-token Secret) MARVIN_SLACKBOT_MAX_TOOL_CALLS_PER_TURN=50 # 单轮最大工具调用数(默认 50) MARVIN_SLACKBOT_USER_MESSAGE_MAX_TOKENS=500 # 用户消息最大 token 数(默认 500) TURBOPUFFER_API_KEY=abcd1234 # 向量存储密钥(未设置时回退到 tpuf-api-key Secret)

补充源码中未写入 README 但同样生效的字段:settings.py 还支持MARVIN_SLACKBOT_DB_FILE(SQLite 路径,默认marvin_chat.sqlite,仅用于线程去重状态)、MARVIN_SLACKBOT_LOG_FORMAT(彩色日志格式)、MARVIN_SLACKBOT_VECTOR_STORE_TYPE(向量存储类型,当前限定turbopuffer)、MARVIN_SLACKBOT_USER_FACTS_NAMESPACE_PREFIX(用户事实命名空间前缀,默认user-facts-)、MARVIN_SLACKBOT_LOGFIRE_*(Logfire 可观测性配置)。

Slack App 配置:五步接入 Slack 事件

按 README 步骤创建应用:

  1. 在 https://api.slack.com/apps 创建新 Slack App;
  2. 添加 Bot User,授予所需 OAuth Scopes:
    • app_mentions:read—— 接收 @提及事件
    • channels:read/groups:read—— 读取频道与私人群组信息
    • chat:write—— 发送消息
    • im:read/mpim:read—— 读取私聊与多人私聊
    • (源码补充)若要支持用户共享图片,还需要files:readScope——slack.py 的fetch_shared_images依赖它下载私有文件 URL;缺少该 Scope 时 Slack 会返回 HTML 登录页而非错误状态,代码通过校验content-type是否以image/开头来兜底跳过;
  3. 配置事件订阅:
    • Request URL:https://{YOUR_DOMAIN}/chat
    • Bot Events:app_mention(被提及)、team_join(新成员加入)
  4. 安装应用到工作区,将 Bot Token 填入MARVIN_SLACKBOT_SLACK_API_TOKEN或test-slack-api-tokenSecret;
  5. 将机器人邀请到目标频道。

源码中对事件类型的处理(api.py):team_join会向新成员私发WELCOME_MESSAGE(模板见 _internal/templates.py);message_changed编辑事件会被识别(_extract_message_context,api.py);针对私聊(channel 名以D开头)的直发消息会被拒绝并通知管理员。

本地运行:ngrok 隧道 + uvicorn 双进程

Slack 事件订阅要求公网可达的 HTTPS 端点,本地开发用 ngrok 暴露端口:

# 终端 1:暴露本地服务端口(与 MARVIN_SLACKBOT_PORT 保持一致) ngrok http 4200 # 终端 2:启动机器人 uv run --extra slackbot -m slackbot

将 ngrok 生成的 HTTPS 地址填入 Slack App 的 Request URL(追加/chat路径)。机器人启动日志会打印当前使用的模型(__main__.py中的logger.debug(f"Starting Slackbot with model: {settings.bot_model}"))。

测试机器人:一条 @提及触发完整推理链路

在机器人已加入的任意频道发起:

@Marvin What's new in Prefect?

机器人随后的行为(README 概述,源码印证):

  1. 搜索 Prefect 文档:research_prefect_topic工具(Claude Agent SDK 研究子代理,research_agent.py);
  2. 查看 GitHub issues:read_github_issues工具(search.py);
  3. 验证 CLI 命令与函数签名:check_cli_command、display_callable_signature、explore_module_offerings工具,避免凭记忆给出错误 API;
  4. 检索最新 release notes:get_latest_prefect_release_notes;
  5. 搜索社区 Slack 历史线程:通过MCPServerStreamableHTTP连接外部 MCP 服务器(core.py),并用TolerantToolset包裹——远程工具集可能缺失,缺了照常回答而不是叙述失败;
  6. 回忆先前交互:build_user_context(core.py)加载用户的持久化画像与相关记忆,以UserContext作为 Agent 依赖注入;
  7. 提供上下文感知的回复:回答经post_slack_message发送回线程,Markdown 链接与加粗自动转换为 Slack mrkdwn(convert_md_links_to_slack,slack.py)。

进度消息与工具追踪

用户视角下,机器人会先展示🔄 _thinking..._占位符(PROGRESS_PLACEHOLDER),随后由_personality_blurb用便宜档模型(utility_model)把标题改写成 Marvin 风格的吐槽(模板见 _internal/templates.py,超时 10 秒、失败则保留静态文案)。工具调用过程中,进度消息会实时渲染工具使用统计——这一机制由 wrap.py 的WatchToolCalls上下文管理器实现:通过 monkey-patch pydantic-ai 的AbstractToolset.call_tool,将每次工具调用包装为 Prefect task 并计数,超过max_tool_calls_per_turn(默认 50)即强制终止,防止 Agent 失控循环。回答完成后进度消息更新为✅ thought for X.X seconds。

消息长度与去重保护

  • 长度限制:count_tokens估算用户消息 token 数(strings.py),超过user_message_max_tokens(默认 500)时返回截断后的消息提示超限;
  • 重复事件去重:Slack 可能重复投递事件,handle_message通过try_acquire_thread(SQLite 表slack_thread_status,跨进程协调)按message_ts加锁;若正在处理中收到编辑事件,机器人会回帖提醒"已在处理你的第一版消息"(api.py)。

记忆系统:用户事实 + 个人摘要双层持久化

这是该示例区别于普通 Chatbot 的关键特性:

  • 用户事实(User Facts):Agent 内置四个工具——store_facts_about_user、read_fact_about_user、correct_fact_about_user、delete_facts_about_user(core.py)。模型自行判断何时将"下周仍然成立"的环境、目标、偏好写入向量存储(命名空间user-facts-{user_id});写入时按语义去重并打时间戳,读取时校验归属(只能读本人事实),修正时保留被取代的旧版本作为溯源证据,删除按主题语义近似匹配并如实汇报删除内容;
  • 个人摘要(Person Summary):load_person_summary/update_person_summary(_internal/person_summary.py)在对话结束后用便宜档模型合成用户画像摘要,供下次对话注入;
  • 记忆容错:记忆存储不可用时只降级为"更薄的 prompt",绝不导致回复失败(core.py);
  • 线程消息历史:保存在 Prefect 的WritableFileSystemblock 中(_internal/message_store.py),SQLite 仅用于去重状态;summarize_thread每 4 条消息自动总结一次线程(handle_message.on_completion钩子,api.py)。

频道限制:工作区到指定频道的映射

机器人可按工作区限制只响应指定频道,其他频道提及会收到重定向提示。README 示例的映射表位于_internal/constants.py:

WORKSPACE_TO_CHANNEL_ID = { "TL09B008Y": "C04DZJC94DC", # Prefect Community -> #ask-marvin "TAN3D79AL": "C046WGGKF4P", # Prefect -> #ask-marvin-tests # 按需追加更多工作区映射 }

需要注意:当前仓库中的 constants.py 实际为WORKSPACE_TO_CHANNEL_ID: dict[str, str] = {}(空映射),README 中的示例是生产环境的配置形态。结合 api.py 的逻辑:若某工作区未配置映射,check_if_designated_channel返回True,即默认允许所有频道;仅当映射存在时才校验频道一致性,不匹配时发送CHANNEL_REDIRECT_MESSAGE("Please post this question in <#channel_id> for assistance.",见 _internal/templates.py)并记录REDIRECTED状态。

开发特性速览

  • 热重载:MARVIN_SLACKBOT_TEST_MODE=true时 uvicorn 自动监听文件变化重启;
  • 彩色日志:默认log_format带 ANSI 颜色(时间、模块名、级别),日志级别校验自动转大写;
  • SQLite 消息历史:marvin_chat.sqlite记录线程去重状态;
  • TurboPuffer 向量存储:用户上下文与用户事实的持久化载体;
  • 灵活配置:环境变量 /.env文件 / Prefect Secrets / Prefect Variables 四种途径。

生产部署:Dockerfile 与容器化要点

生产环境可部署到 Cloud Run 等容器平台,参考 Dockerfile.slackbot。要点(源自 Dockerfile):

  • 基于python:3.13-slim,内置uv与bun;
  • 构建时执行uv sync --extra slackbot --no-dev安装依赖;
  • 预生成 tiktoken 缓存(TIKTOKEN_CACHE_DIR=/app/.cache/tiktoken),避免首个 Slack 请求时现场下载 tokenizer;
  • 安装@anthropic-ai/claude-code(研究子代理依赖);
  • 暴露端口4200,启动命令uv run --no-sync -m slackbot。

README 提到的 CI/CD 配置位于/.github/workflows/image-build-and-push-community.yaml(当前仓库目录列表未包含.github目录,可确认该工作流属于上游生产仓库的组织配置)。

测试覆盖

仓库测试目录 tests/ 提供可参考的验证路径(均与 slackbot 子模块直接相关):

  • test_slack_format.py:验证 Markdown → Slack mrkdwn 转换;
  • test_progress_blurb.py:进度消息改写逻辑;
  • test_settings.py 与 test_agent_settings.py:配置解析与模型分层;
  • test_prompt_sync.py:系统提示词热更新同步;
  • test_memory_recall.py:记忆召回;
  • test_person_context.py:个人上下文注入;
  • test_thread_summary.py:线程总结;
  • test_mcp_startup.py:MCP 工具集启动容错;
  • test_fact_corrections.py:用户事实修正;
  • test_provider_retries.py:模型提供商重试。

小结

slackbot是一个架构完整、可直接上线的 Marvin 应用范本:FastAPI 负责 Webhook 接入,Prefect Flow/Task 提供可靠编排与可观测性,pydantic-ai Agent + 分层模型(回答/工具/研究)承担推理,TurboPuffer 向量存储承载跨会话记忆,MCP 工具集扩展社区知识检索。它演示了 Marvin 生态中"AI 应用"的完整落地形态——从本地uv sync --extra slackbot到 Cloud Run 容器部署,从 Slack App 配置到生产级频道治理,均可在本仓库中直接复现与二次开发。

  • AI Agent
  • Agent 框架
  • AI 应用

【免费下载链接】marvin

an ambient intelligence library

项目地址:https://gitcode.com/gh_mirrors/ma/marvin
点击查看免费下载

相关推荐

上一篇:终极免费方案:3步解锁WeMod专业版所有高级功能
下一篇:PyPTO Pro 编程范式详解:SIMD 与 SIMT 并行模型及 AI Core 硬件抽象

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

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

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

立即咨询