1. 项目概述:一个能上网、会记忆、有性格的Telegram AI助手
如果你在寻找一个能真正“干活”的AI助手,而不仅仅是陪你闲聊,那么Crusty可能会让你眼前一亮。这不仅仅是一个套了层Telegram壳的ChatGPT,它是一个功能完整的智能体(Agent),拥有网页浏览、长期记忆、模块化性格系统,甚至能帮你管理日程和调用本地服务。简单来说,你可以把它理解为一个24小时待命、能通过Telegram远程指挥的数字员工,它能理解复杂指令,使用工具去执行任务,并把结果和思考过程反馈给你。
我最初被它吸引,是因为厌倦了那些需要反复解释上下文、对话一长就失忆的聊天机器人。Crusty的核心价值在于它的确定性对话线程和长期记忆。这意味着,你早上让它查的资料,晚上再问相关问题时,它还记得之前的对话脉络,而不是像个金鱼一样只有7秒记忆。它的“工具箱”也很实在:真正的无头浏览器进行网页抓取(带隐身模式)、基于SQLite/Postgres的向量记忆存储、自动的上下文摘要,以及一个心跳调度器来执行定时任务。最让我觉得有意思的是它的“人格系统”,你可以通过编辑Markdown文件来定义它的性格和行事风格,让它从一个公事公办的助手,变成你专属的、有特定口癖和思维模式的伙伴。
2. 核心架构与设计哲学解析
2.1 模块化人格系统:从“工具”到“伙伴”的关键
Crusty的设计起点很高,它没有把自己定位成一个冰冷的任务执行器,而是引入了“人格(Cogs)”的概念。在项目根目录或配置目录下的cogs/文件夹里,几个Markdown文件构成了它的灵魂。
SOUL.md:这是核心人格定义文件。在这里,你不仅定义助手的名字、性别(如果需要),更重要的是定义它的核心行为准则、价值观和禁忌。例如,你可以规定它必须优先考虑用户隐私,不得执行任何破坏性操作,或者在信息不确定时必须主动声明。这相当于给AI划定了行动边界和道德指南。IDENTITY.md:这决定了它的沟通风格。是严谨专业的学术口吻,还是活泼亲切的朋友语气?回复喜欢用长段落还是分点列表?是否会使用特定的表情符号或口头禅?这个文件让你能定制出一个符合你沟通习惯的对话伙伴。HEARTBEAT.md:这是它的“潜意识”或“后台进程”指令集。心跳调度器(Heartbeat Scheduler)会定期(如每30分钟)唤醒AI,并让它阅读这个文件中的指令。你可以在这里让它定期检查某个网站更新、整理记忆库、或者生成每日摘要。这赋予了Crusty主动性和计划性,而不仅仅是被动响应。
实操心得:修改人格文件后,需要重启Crusty才能生效。一个高效的技巧是,先在
SOUL.md中强调“安全第一”和“在操作前确认”的原则,这能极大减少AI因误解而执行危险命令的几率。IDENTITY.md的调教需要耐心,通过几次对话反馈来微调,才能得到最合拍的沟通体验。
2.2 确定性对话线程与记忆管理:告别混乱的上下文
这是Crusty解决传统聊天机器人痛点的核心技术。想象一下,你和助手在讨论一个编程问题,中途你分享了一个错误日志链接。传统AI可能会把这个链接当作普通对话内容。而Crusty的“确定性对话线程”机制会识别出这是一个可执行工具(如浏览网页)的输入,并自动在正确的上下文中调用浏览器工具去分析那个页面。
其工作流程可以拆解为:
- 线程激活与复用:每条消息都会关联到一个“线程(Thread)”。如果你直接回复某条消息,Crusty会精准地延续那个线程的上下文。如果你是发起新消息,它会自动寻找并复用最近活跃的线程(在
CONVERSATION_THREAD_ACTIVE_WINDOW_MINUTES定义的时间窗口内,默认30分钟)。这保证了对话的连贯性。 - 记忆的存储与检索:对话不会无限地塞进提示词(Prompt)。Crusty会使用嵌入模型(Embedding)将对话片段转换为向量,存储到SQLite(本地轻量)或Postgres + pgvector(生产级)中。当新问题到来时,它通过向量相似度搜索,从记忆库中找出最相关的历史对话,作为上下文喂给AI。这突破了模型本身的上下文长度限制。
- 自动摘要与上下文窗口管理:当对话轮次太多时,Crusty会自动将较旧的对话内容总结成一段精炼的摘要,然后用“摘要+近期详细对话”的形式维护上下文。这既保留了长期记忆的要点,又为新的思考腾出了宝贵的Token空间(由
MAX_CONTEXT_TOKENS控制,默认24000)。这个过程对用户是无感的,你只会觉得这个助手记性特别好。
2.3 ACP发现机制:连接本地生态系统的桥梁
ACP是Crusty设计中最具前瞻性的功能之一。ACP全称可能是“Agent Communication Protocol”,你可以把它理解为Crusty发现和集成本地其他AI智能体或服务的“插件系统”。
它的工作方式非常智能:
- 首次启动扫描:Crusty启动时,会像一个网络管理员一样,快速扫描本地常用端口(如3000, 8000, 8080),并向这些端口上常见的路径(如
/acp,/api/acp)发送探测请求,寻找兼容的ACP服务。 - Stdio代理启动:你还可以通过
ACP_STDIO_AGENTS_JSON配置,告诉Crusty:“我电脑上还有一个叫‘goose’的AI程序,你可以用goose acp serve这个命令启动它并与之通信。” Crusty会负责启动和管理这些子进程。 - 工具自动注册:一旦发现或启动了一个ACP代理,Crusty会自动为其创建一个专属工具。例如,发现了一个处理桌面自动化任务的ACP代理,主AI助手就能直接调用类似
acp_goose_desktop这样的工具去操作你的电脑。 - 持久化与缓存:发现的ACP端点信息会被保存到数据库。下次启动时直接加载,无需重新扫描,实现快速启动。
这意味着Crusty可以成为你本地AI工具生态的“中央控制器”。一个擅长数据分析的本地模型、一个专精图像生成的工具,都可以通过ACP被Crusty集成,然后你只需要在Telegram里用自然语言命令它去协调这些专业工具完成任务。
3. 从零开始的部署与深度配置指南
3.1 Docker部署:最推荐的生产级方案
官方强烈推荐使用Docker,这是有道理的。Crusty依赖无头Chromium进行网页浏览,而Chromium在宿主机上的安装和依赖管理可能很棘手。Docker镜像打包了所有依赖,包括一个配置好的Chromium,确保了环境的一致性。
基础运行命令详解:
docker run -d \ --name crusty \ # 给容器起个名字,方便管理 -e OPENAI_API_KEY=your-api-key \ # 核心:你的OpenAI API密钥 -e TELEGRAM_BOT_TOKEN=your-telegram-bot-token \ # 核心:从@BotFather获取的机器人令牌 -e CRUSTY_WORKSPACE=/workspace \ # 指定工具(如读写文件)的默认工作目录 -v crusty-data:/app/data \ # 持久化卷,用于保存数据库(记忆)、配置等 -v $(pwd):/workspace \ # 将宿主机当前目录挂载到容器的/workspace,这样AI就能操作你电脑上的文件了 ghcr.io/cloudwithax/crusty:latest-d代表后台运行。crusty-data是一个Docker管理的命名卷,即使容器删除,你的聊天记忆和配置也不会丢失。$(pwd):/workspace这个挂载至关重要,它打通了容器内AI与宿主机文件的通道。AI执行“写文件”工具时,文件就会出现在你当前的目录下。
使用Docker Compose进行优雅管理:对于长期使用,docker-compose.yml是更专业的选择。它把配置代码化,易于版本管理和一键启停。
version: '3.8' services: crusty: image: ghcr.io/cloudwithax/crusty:latest container_name: crusty restart: unless-stopped # 崩溃或宿主机重启后自动拉起,保障服务可用性 environment: - OPENAI_API_KEY=${OPENAI_API_KEY} # 建议从.env文件读取,避免密钥硬编码 - TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN} - CRUSTY_WORKSPACE=/workspace - OPENAI_MODEL=gpt-4o # 可指定模型,如gpt-4-turbo-preview - HEARTBEAT_EVERY=30m # 心跳任务执行间隔 - ACP_DISCOVERY_ENABLED=true # 启用ACP发现 volumes: - crusty-data:/app/data - ./:/workspace # 挂载当前项目目录 - ./my-custom-cogs:/app/cogs:ro # 挂载自定义人格目录,:ro表示只读,防止容器意外修改 volumes: crusty-data:创建一个.env文件在相同目录,填入你的密钥:
OPENAI_API_KEY=sk-... TELEGRAM_BOT_TOKEN=1234567890:ABC...然后运行docker compose up -d即可。
3.2 本地安装与调试(适用于开发者)
如果你需要修改源码或深度调试,本地安装是必须的。Crusty使用Bun作为运行时,这比Node.js在启动速度和包管理上有优势。
# 1. 克隆项目 git clone https://github.com/cloudwithax/crusty.git cd crusty # 2. 安装依赖(Bun会读取package.json并安装) bun install # 3. (可选)全局链接CLI工具,这样可以在任何地方运行`crusty`命令 bun link # 4. 运行设置向导,它会交互式地帮你创建.env文件 crusty setup # 按照提示输入OpenAI API Key和Telegram Bot Token # 5. 启动(前台运行,方便看日志) crusty start # 或作为守护进程启动(类systemd,仅限Linux/macOS) crusty start -d本地运行时,所有数据默认会存放在~/.config/crusty/目录下。你可以在这里找到数据库文件、日志以及默认的cogs目录。
3.3 关键环境变量解析与调优
除了必须的API密钥,以下变量对性能和行为有显著影响,值得仔细配置:
| 变量名 | 默认值/示例 | 作用与调优建议 |
|---|---|---|
OPENAI_MODEL | gpt-4o | 指定使用的AI模型。gpt-4-turbo性价比高,gpt-4o最新最快。根据任务复杂度和预算选择。 |
HEARTBEAT_EVERY | 30m | 心跳任务执行频率。格式如10m(10分钟)、1h(1小时)。太频繁消耗API Token,太慢则定时任务不灵敏。 |
MAX_CONTEXT_TOKENS | 24000 | 上下文窗口的最大Token数。需留有余地(例如模型上限128K,设成100K),因为系统提示词、工具描述等会占用一部分。 |
CONVERSATION_THREAD_... | 30 | 线程活跃窗口(分钟)。超过此时长未互动,新消息将创建新线程。根据你的对话习惯调整。 |
CRUSTY_WORKSPACE | /workspace(Docker) | 重要:AI工具(如文件操作)的基准路径。确保该路径有读写权限,并指向你希望AI操作的文件区域。 |
CRUSTY_CREDENTIALS_... | (无) | 如果使用需要加密存储凭证的工具(如某些数据库连接),必须设置一个长随机字符串作为主密钥。 |
ACP_DISCOVERY_TIMEOUT_MS | 750 | ACP HTTP探测超时时间。内网服务可调低(如200)加快启动;网络不稳定可调高。 |
注意事项:修改环境变量后,需要重启Crusty容器或进程才能生效。对于Docker,可以使用
docker compose restart crusty。
4. 核心功能实操与高级用法
4.1 网页浏览与“隐身模式”
Crusty的网页浏览不是简单的HTTP请求,而是通过一个真正的无头Chromium浏览器来渲染页面。这意味着它能处理JavaScript动态加载的内容,像SPA(单页应用)或者需要登录的网站。
基本使用:你只需要在对话中发送一个链接,或者说“请浏览一下https://example.com并总结主要内容”,Crusty就会自动调用浏览工具。它会提取页面文本、标题、主要链接等信息,并智能地总结。
“隐身模式”的深层含义:这里的“隐身”并非指完全无法被追踪,而是指Crusty在发起请求时,会使用一个更接近普通浏览器的User-Agent,并管理Cookies和会话,模拟人类浏览行为,以降低被一些简单反爬机制拦截的概率。但这不能绕过高级的反爬系统(如Cloudflare的5秒盾)。对于重要的公开信息抓取,始终要尊重网站的robots.txt和服务条款。
实操示例:
用户:“我想了解今天Hacker News上的热门话题。” Crusty会执行:
browse_web工具,目标URL为https://news.ycombinator.com。它会获取页面,提取所有文章标题和链接,然后使用AI进行归纳总结,最后回复你:“今天HN上前三的热门话题是:1. 关于XX新编程语言的讨论;2. 一篇关于量子计算纠错的论文;3. 某知名科技公司开源的内部工具。这是详细链接:[链接1], [链接2], [链接3]。”
4.2 技能系统:创建可复用的指令包
技能(Skills)是Crusty的“宏”或“预设指令集”。你可以将一系列复杂的、多步骤的指令打包成一个技能,然后通过/skill命令轻松调用。
创建自定义技能:
- 在
~/.config/crusty/skills/(本地安装)或挂载的./cogs/skills/(Docker)目录下,创建一个新文件夹,例如daily_report。 - 在该文件夹内创建
SKILL.md文件。 - 按照 Agent Skill Format 编写技能内容。一个简单的技能文件如下:
# Daily Standup Report Generator ## Description Helps the user generate a daily work standup report. ## Instructions 1. Ask the user for what they accomplished yesterday. 2. Ask the user for their plan today. 3. Ask the user if there are any blockers. 4. Synthesize the answers into a well-formatted Markdown report. 5. Offer to save the report to a file named `standup-YYYY-MM-DD.md` in the workspace. ## Example Interaction User: "I want to do my standup." Agent: "Sure! What did you accomplish yesterday?" - 重启Crusty或使用
/skill reload命令(如果支持)加载新技能。 - 在Telegram中,你可以通过
/skill daily_report来触发这个技能流程。
实操心得:技能是提升效率的利器。我将常用的“代码审查”、“周报生成”、“特定网站信息监控”都做成了技能。编写技能指令时,要尽可能清晰、步骤化,并预判AI可能遇到的歧义,在指令中提前约束。好的技能能让AI从一个通用助手,变成你的专属业务专家。
4.3 提醒系统与自然语言时间解析
Crusty内置了一个相当聪明的提醒系统。你不需要用“14:30”这样的格式,直接用自然语言说就行。
使用方法:
你:“提醒我两小时后给客户回个电话。” Crusty会解析“两小时后”这个时间点,创建一条提醒,并回复:“好的,已设置提醒:'给客户回个电话',时间大约在 [计算出的具体时间]。” 时间一到,Crusty会在Telegram中主动@你或发送消息提醒。
其背后是AI模型强大的自然语言理解能力,能够解析“明天早上”、“下周五下午三点”、“每周末”等复杂时间表达式。你可以通过/reminders命令查看所有待处理的提醒。
4.4 记忆的查看与管理
记忆是Crusty的核心,你也拥有管理它的工具。
/memory:查看记忆系统的统计数据,如存储了多少条记忆片段、向量数据库类型等。/clear:危险操作。这会重置当前对话线程并清除与该线程相关的短期上下文,但通常不会删除已存入长期向量数据库的记忆(具体行为取决于配置)。主要用于当对话跑偏或混乱时,快速开启一个新话题。/context:显示当前对话线程的上下文使用情况,比如已经用了多少Token,包含了哪些历史消息和记忆片段。这有助于你判断是否需要进行手动清理。
5. 故障排除与性能优化实战记录
即使设计得再完善,在实际部署和运行中总会遇到各种问题。以下是我在长期使用中积累的一些常见问题与解决方案。
5.1 Docker容器启动失败或立即退出
这是最常见的问题,通常原因和解决步骤如下:
- 检查日志:这是第一步,也是最重要的一步。运行
docker logs crusty(如果容器已创建但未运行)或docker logs -f crusty(实时查看)。 - 常见错误1:环境变量缺失
- 日志特征:在启动初期出现
Error: Required environment variable OPENAI_API_KEY is not set或类似提示。 - 解决方案:确保
docker run命令或docker-compose.yml文件以及对应的.env文件中正确设置了OPENAI_API_KEY和TELEGRAM_BOT_TOKEN。注意.env文件需要放在docker-compose.yml同目录,且变量名在Compose文件中要用${}引用。
- 日志特征:在启动初期出现
- 常见错误2:端口冲突或权限问题
- 日志特征:可能报错不明显,容器直接Exited (1)。
- 解决方案:Crusty本身不一定暴露端口,但挂载的目录可能存在权限问题。确保你挂载的本地目录(如
./:/workspace)对Docker容器内的用户(通常是非root用户)是可读写的。可以尝试先去掉-v ./:/workspace挂载,看是否能正常启动。
- 常见错误3:Chromium启动失败(多见于某些Linux宿主机或资源限制)
- 日志特征:日志中出现
Failed to launch chromium、no usable sandbox等错误。 - 解决方案:Docker镜像通常已配置好沙箱。如果不行,可以尝试在
docker run命令中添加--security-opt seccomp=unconfined和--shm-size="2g"参数,前者放宽安全限制,后者给共享内存扩容,这对Chromium运行很重要。
- 日志特征:日志中出现
5.2 网页浏览功能失效或返回空白
- 现象:发送链接后,AI回复“我浏览了页面,但没找到内容”或直接超时。
- 排查步骤:
- 检查网络:确保Docker容器能访问外网。尝试在容器内执行
docker exec crusty curl -I https://example.com测试连通性。 - 检查目标网站:该网站可能启用了严格的反机器人措施(如Cloudflare)。Crusty的“隐身模式”对此能力有限。可以尝试让AI浏览
http://httpbin.org/user-agent这样的测试网站,看是否能正确返回User-Agent信息,以确认浏览功能本身是正常的。 - 查看详细日志:启动时增加环境变量
DEBUG=puppeteer:*(Docker环境变量设置),可以输出Chromium的详细调试日志,帮助定位是网络、渲染还是脚本执行的问题。 - 资源限制:网页浏览是资源密集型操作。确保Docker容器分配了足够的内存(至少1GB,建议2GB)。在
docker-compose.yml中可以通过deploy.resources.limits.memory设置。
- 检查网络:确保Docker容器能访问外网。尝试在容器内执行
5.3 AI响应慢或Token消耗过快
- 分析原因:
- 上下文过长:每次对话都会携带完整的上下文历史(经过摘要处理),如果历史很长,每次请求的Prompt就会很大,导致生成速度慢、Token消耗多。
- 模型过载:如果使用GPT-4系列,本身速度就比GPT-3.5慢。
- 网络延迟:到OpenAI API服务器的网络状况不佳。
- 优化策略:
- 调整
MAX_CONTEXT_TOKENS:适当调低此值,例如从24000调到16000,强制进行更积极的摘要,减少每次请求的负担。 - 定期使用
/clear:对于已经结束、不相关的长话题,主动使用/clear命令开始新线程,清空当前上下文。 - 切换模型:对于不需要极高推理能力的日常任务,在
.env中将OPENAI_MODEL改为gpt-3.5-turbo,速度会快很多,成本也大幅下降。 - 使用技能:将固定流程封装成技能,技能指令本身是精炼的,可以减少不必要的上下文传递。
- 调整
5.4 ACP发现功能未找到本地服务
- 确认服务是否真的在运行并监听:在宿主机上使用
netstat -tulpn | grep :3000(以3000端口为例)检查你的ACP服务是否在运行且监听在0.0.0.0或127.0.0.1。 - 检查网络模式:Docker容器默认使用自己的网络命名空间。如果ACP服务运行在宿主机上,容器需要通过宿主机的IP(如
host.docker.internal在Mac/Windows,或172.17.0.1在Linux的默认桥接网络)来访问。确保ACP_DISCOVERY_HOSTS环境变量包含了正确的宿主机器地址。 - 调整发现参数:
ACP_DISCOVERY_PORTS: 确保包含了你的ACP服务实际监听的端口。ACP_DISCOVERY_TIMEOUT_MS: 如果网络较慢,适当调大超时时间。ACP_DISCOVERY_ENABLED: 确保设为true。
- 查看日志:启动时关注日志中关于ACP发现的部分,看它扫描了哪些地址和端口,以及探测结果是什么。
5.5 记忆似乎没有起作用
- 理解记忆的运作方式:记忆(向量检索)不是每次对话都100%触发。只有当AI认为需要历史信息来更好地回答当前问题时,它才会去记忆库中搜索。你可以尝试问一个非常具体、且在过去对话中详细讨论过的问题来测试。
- 检查数据库:如果是Docker部署,确认数据卷
crusty-data已正确挂载且持久化。可以进入容器查看/app/data目录下是否有SQLite文件(memory.db)。 - 手动触发记忆检索:在对话中,你可以尝试使用更明确的指令,如“根据我们之前关于XXX的讨论,你现在怎么看YYY?”,这更有可能触发AI去搜索相关记忆。
经过这些实战调试,我的Crusty已经稳定运行了数月,成为了我处理信息、管理琐事和进行创意构思的得力副手。它的价值不在于炫技,而在于将强大的AI能力封装成了一个可靠、可定制、能真正融入工作流的工具。从最初的简单问答,到如今能协调多个本地服务完成复杂任务,这个过程本身就像是在培养一个逐渐成长的数字伙伴。如果你也受困于传统聊天机器人的局限,不妨花点时间部署和调教一下Crusty,它带来的效率提升和交互体验的改变,很可能会超出你的预期。