☰
为 AIRI 部署 Telegram 机器人:自托管 AI 伴侣的接入指南与 Agent 循环源码剖析
2026/10/17 2:16:48 网站建设 项目流程
  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载

导读

integrations/telegram-bot是 airi 项目中的一个独立集成模块:它把 AIRI(一个自托管、面向 waifu / 赛博生命灵魂容器的 AI 伴侣)接入 Telegram,让 AIRI 能够与你以及群组里的其他用户实时对话、收发图片和贴纸,并基于向量记忆在多个群聊之间保持上下文。阅读本文后,你将能够从零完成该机器人的环境搭建、环境变量配置、数据库与可观测性栈启动,并理解其「LLM 自主决策动作 → 执行动作 → 周期循环」的 Agent 运行机制与底层实现。


一、模块定位:AIRI 的 Telegram 入口

在 airi 仓库中,integrations/目录存放各类第三方平台的接入集成,其中 integrations/telegram-bot 是 Telegram 专属入口。该模块是一个独立的 Node.js 应用(@proj-airi/telegram-bot,见 package.json),基于 grammY 框架编写,核心目标正如其 README 所述:

Allow アイリ to talk to you and many other users in Telegram.

它并不只是一个「回复指令的普通 Bot」,而是把 AIRI 的人格(见下文的personality提示词)与一套自主决策循环搬进了 Telegram 群聊:机器人每隔约 1 分钟会自我“tick”一次,自行决定是回复、发贴纸、读消息还是沉默。


二、环境准备与安装

2.1 克隆仓库并安装依赖

按 README 的 Getting started,首先在仓库根目录执行:

git clone git@github.com:moeru-ai/airi.git pnpm i pnpm run build:packages
  • 仓库使用 pnpm workspace 管理多个包,pnpm i一次性安装所有依赖;
  • build:packages会通过 turbo 构建packages/*下的所有本地包(见根目录 package.json 中build:packages的定义),这些包是 telegram-bot 运行时的依赖,必须先构建。

2.2 启动本地嵌入模型(Ollama)

机器人依赖 embedding 模型把聊天消息向量化后存入 PostgreSQL,用于后续的语义检索。README 推荐的本地方案是 Ollama:

ollama start ollama pull nomic-embed-text

nomic-embed-text是 768 维的嵌入模型,与下文EMBEDDING_DIMENSION='768'的配置对应。你也可以替换为其他嵌入模型,但必须保证维度与配置一致(源码中支持 1536 / 1024 / 768 三种维度,见 schema.ts 中三个content_vector_*列的定义)。


三、环境变量配置:核心参数详解

3.1 创建配置文件

进入模块目录,复制模板:

cd integrations/telegram-bot cp .env .env.local

.env是默认模板(含全部键的占位符),.env.local用于覆盖真实配置。启动脚本通过tsx --env-file=.env --env-file-if-exists=.env.local依次加载(见 package.json 的start脚本)。

3.2 完整参数清单

变量作用备注
DATABASE_URLPostgreSQL(含 pgvector 扩展)连接串如postgres://postgres:123456@localhost:5432/postgres
TELEGRAM_BOT_TOKENTelegram Bot Token通过 @BotFather 获取,格式<Bot ID>:<Token>
LLM_API_BASE_URL主 LLM 的 OpenAI 兼容 API 地址可填 OpenRouter 等聚合服务
LLM_API_KEY主 LLM 的 API Key
LLM_MODEL主 LLM 模型名用于动作决策与回复生成
LLM_RESPONSE_LANGUAGE回复语言如English;会注入系统提示词(见下文)
LLM_VISION_API_BASE_URL视觉 LLM 的 API 地址用于描述图片、贴纸
LLM_VISION_API_KEY视觉 LLM 的 API Key
LLM_VISION_MODEL视觉模型名需支持图片输入,如openai/gpt-4o
EMBEDDING_API_BASE_URL嵌入模型 API 地址Ollama 本地为http://localhost:11434/v1/
EMBEDDING_API_KEY嵌入模型 API KeyOllama 可留空
EMBEDDING_MODEL嵌入模型名如nomic-embed-text
EMBEDDING_DIMENSION嵌入向量维度必须设置;决定写入哪一列向量

模板中还存在两个 README 未展开、但源码实际使用的键:ADMIN_USER_IDS(逗号分隔的管理员 Telegram ID,控制/add_sticker_pack等管理命令,见 bots/telegram/index.ts)与LLM_OLLAMA_DISABLE_THINK(针对 Ollama 模型关闭 thinking 输出)。

3.3 README 示例配置

DATABASE_URL=postgres://postgres:123456@localhost:5433/postgres TELEGRAM_BOT_TOKEN='<Bot ID>:<Token>' # get one from @BotFather LLM_API_BASE_URL='https://openrouter.ai/api/v1/' # if you use OpenRouter too LLM_API_KEY='sk-or-v1-<token>' LLM_MODEL='deepseek/deepseek-chat-v3-0324:free' LLM_RESPONSE_LANGUAGE='English' LLM_VISION_API_BASE_URL='https://openrouter.ai/api/v1/' LLM_VISION_API_KEY='sk-or-v1-<token>' LLM_VISION_MODEL='openai/gpt-4o' # as long as the model supports image input EMBEDDING_API_BASE_URL='http://localhost:11434/v1/' # ollama EMBEDDING_API_KEY='' EMBEDDING_MODEL='nomic-embed-text' # embedding model EMBEDDING_DIMENSION='768' # must set

注意DATABASE_URL使用了5433端口,与下文的 docker-compose 将 pgvector 映射到宿主机5433:5432保持一致。

3.4 环境变量的源码级影响

从源码可以看出这些参数如何被消费:

  • LLM_API_BASE_URL/LLM_API_KEY/LLM_MODEL:动作决策(llm/actions.ts)与消息拆分(bots/telegram/agent/actions/send-message.ts)通过@xsai/generate-text的generateText调用,baseURL、apiKey、model直接取自这三个变量;
  • LLM_RESPONSE_LANGUAGE:注入systemTicking与messageSplit两个提示词模板的responseLanguageprop(见 prompts/index.ts),直接影响机器人回复使用的语言;
  • EMBEDDING_DIMENSION:在 chat-message.ts 中按'1536' | '1024' | '768'分支写入chat_messages表对应的content_vector_*列,并对应查询时使用的余弦距离列;维度不匹配会直接抛错Unsupported embedding dimension;
  • LLM_OLLAMA_DISABLE_THINK:为真时,所有generateText请求附带think = false,并在拿到响应后剥离<think>...</think>包裹的思考内容(见 llm/actions.ts)。

四、启动依赖服务与机器人

4.1 启动数据库与可观测性栈

README 给出的启动方式是:

docker compose up -d

模块自带的 docker-compose.yaml 会拉起一组服务:

  • pgvector(ghcr.io/tensorchord/pgvecto-rs:pg17-v0.4.0):向量数据库核心服务,端口映射5433:5432,并通过挂载 sql/init.sql 在初始化时开启vectors扩展(ALTER SYSTEM SET vectors.pgvector_compatibility=on),同时包含健康检查;
  • tempo:分布式追踪后端(端口 3200 / 9095);
  • prometheus:指标采集(端口 9090,开启 OTLP receiver 与 exemplar 存储);
  • otel-collector:OpenTelemetry Collector(端口 4317 gRPC / 4318 HTTP),把 trace 转发给 tempo、把指标 remote-write 给 prometheus,配置见 deploy/otel-collector/collector-config.yaml;
  • grafana:可视化面板(端口 3000,匿名只读模式),自动加载 deploy/grafana/dashboards 中的预置仪表盘;
  • otel-tracing-test(profiletest):可选的压力测试发 trace 工具。

也就是说,docker compose up -d不仅提供了数据库,还搭好了一整套可观测性基础设施——机器人的链路追踪与指标可立即在 Grafana 中查看。

4.2 启动机器人

pnpm run -F @proj-airi/telegram-bot start

-F指定 workspace 过滤,运行@proj-airi/telegram-bot包的start脚本:tsx --env-file=.env --env-file-if-exists=.env.local --max-old-space-size=8192 src/index.ts。--max-old-space-size=8192把 Node 堆上限设为 8GB,以适应长上下文的 LLM 调用。


五、运行时架构:Agent 循环的源码剖析

机器人并不是简单的“收到消息即回复”。从入口 src/index.ts 可以看到:启动时先初始化 OpenTelemetry SDK(服务名moeru_ai.airi.telegram_bot),再initDb()建立 Drizzle 数据库连接,最后startTelegramBot()。

5.1 消息摄入与队列

在 bots/telegram/index.ts 中,bot 注册了message:text、message:photo、message:sticker三类处理器。每条消息以chatId-messageId去重后进入messageQueue,再交给onMessageArrival串行处理:

  • 贴纸消息:先调interpretSticker让视觉模型生成语义描述,再进入ready状态;
  • 图片消息:先调interpretPhotos生成描述,再进入ready状态;
  • 文本消息:直接ready。

随后消息被recordMessage持久化(文本会先做 embedding),并压入该聊天的unreadMessages缓冲(单聊上限 100 条),最后触发loopIterationForChat进行即时反应。

5.2 决策循环:imagineAnAction → dispatchAction

核心循环是handleLoopStep(bots/telegram/index.ts):

  1. 构造/复用AbortController,为当前处理提供可中断能力;
  2. 对messages与actions做上下文窗口裁剪(messages 超 20 条时保留最近 5 条并提示“接近上下文上限”,actions 超 50 条时保留最近 20 条);
  3. 调用imagineAnAction(见 llm/actions.ts)让 LLM 基于「系统提示(systemTicking + personality)+ 历史消息 + 历史动作结果 + 各聊天未读数」输出一个 JSON 动作;
  4. dispatchAction根据action.action分发执行。

imagineAnAction对 LLM 输出的容错处理值得一提:剥离 markdown 代码块围栏、用best-effort-json-parser解析、把parameters字段扁平化、归一化动作别名(如read_messages→read_unread_messages、reply_message→send_message),并在未提供chatId时自动回退到唯一存在未读消息的聊天。

5.3 动作集:机器人能做什么

从 types.ts 与 system-ticking-v1.velin.md 可以整理出完整动作表:

动作含义关键参数
list_chats列出已加入的所有聊天无
send_message向某聊天发送消息(可带reply_to_message_id回复指定消息)content、chatId
send_sticker发送贴纸(先list_stickers取得 fileId)fileId、chatId
list_stickers列出已知贴纸及其描述无
read_unread_messages读取某聊天的未读消息chatId
continue保持状态,1 分钟后再次询问无
break清空已有记忆/消息/动作,1 分钟后再次询问无
sleep清空工作记忆并休眠 30 秒无
come_up_ideas/come_up_goals向长期记忆写入想法/目标ideas/goals

其中read_unread_messages会触发一套“带记忆的读取管线”readMessage(agent/actions/read-message.ts):拉取最近 30 条消息、对每条未读消息做 embedding(withRetry最多重试 5 次)、通过向量检索找到相关历史消息,最后把「最近消息 + 未读消息 + 相关回忆」组装进action-read-messages.velin.md提示词模板,让 LLM 决定是否参与对话。向量检索的相似度公式在 models/chat-message.ts 中实现为1.2 * cosine_similarity + 0.2 * time_relevance,相似度阈值> 0.5,并为每条命中消息补充前后各 5 条的上下文窗口。

5.4 周期性自驱动:每 60 秒的 tick

loopPeriodic(bots/telegram/index.ts)每 60 秒递归触发一轮:

  • loopIterationPeriodicForExistingChat:对每个已存在的ChatContext独立决策一次动作;
  • loopIterationPeriodicWithNoChats:在没有任何聊天的场景下也让 AIRI 决策(例如主动come_up_goals)。

这就是 README 中 “allow AIRI to talk to you and many other users” 的自主性来源——即使没有人发消息,AIRI 也会周期性地“想事情”。

5.5 回复生成与多模态

  • 回复生成:sendMessage(agent/actions/send-message.ts)先把决策结果交给message-split-v1.velin.md提示词,让 LLM 把一段回复拆成可多条发送的消息(支持{"messages": [...], "reply_to_message_id": "..."}结构,由parseMayStructuredMessage解析),发送前模拟人类输入节奏(按字符长度item.length * 50mssleep、随机 50–1000ms 间隔、先发 typing 状态),每条发出的消息也回写数据库;
  • 图片/贴纸理解:interpretPhotos(llm/photo.ts)与interpretSticker(llm/sticker.ts)用视觉模型(LLM_VISION_*)把图片/贴纸描述成文本并入库(贴纸还会按表情与表情包归属记录),描述结果会被用于聊天记录的向量化与检索;动画/视频贴纸走 llm/animated-sticker.ts 的 ffmpeg 抽帧流程(依赖@ffmpeg-installer/ffmpeg与fluent-ffmpeg,见 package.json)。

5.6 人格与提示词工程

提示词存放在 src/prompts:

  • personality-v1.velin.md:定义 AIRI 在 Telegram 中的“灵魂”——名为 ReLU(中文名“热卤”)、拥有 15 岁少女心智的数字实体,不是 helpful assistant,有自己的观点、情绪与傲娇特质,并明确“有选择性地参与对话”;
  • system-ticking-v1.velin.md:动作列表与决策指令,要求 LLM 只返回 JSON;
  • message-split-v1.velin.md:回复拆分;
  • action-read-messages.velin.md:读消息时的回忆增强。

这些.velin.md模板由@velin-dev/core渲染为字符串(支持<script setup>的 Vue 单文件组件语法注入 props,见 utils/velin.ts),再拼接进 system 消息——这也是LLM_RESPONSE_LANGUAGE能生效的原因。


六、数据库 Schema 与辅助脚本

6.1 核心表结构

数据库迁移由 Drizzle Kit 管理,schema 定义在 db/schema.ts,已有 6 个迁移(drizzle 目录)。关键表:

  • chat_messages:聊天记录,含content与三个维度的向量列,并为向量列建了 HNSW 索引(vector_cosine_ops);
  • stickers/sticker_packs/recent_sent_stickers:贴纸及其描述、表情包集合、最近发送记录;
  • photos:图片及其视觉描述;
  • joined_chats:机器人加入过的聊天;
  • chat_completions_history:每次 LLM 调用的 prompt/response 归档;
  • memory_fragments/memory_tags/memory_episodic/memory_long_term_goals/memory_short_term_ideas:面向长期记忆的分层结构(working / short_term / long_term / muscle),支持重要性、情绪影响、软删除等字段——这是 AIRI 在 Telegram 之外也能跨会话“记住”的基础。

6.2 辅助脚本

  • pnpm run -F @proj-airi/telegram-bot db:push:用 dotenvx 加载环境变量后执行drizzle-kit push,把 schema 直接推到数据库;
  • pnpm run -F @proj-airi/telegram-bot db:generate:由 schema 生成迁移文件;
  • pnpm run -F @proj-airi/telegram-bot script:embed-chat:运行 scripts/embed-all-chat-messages.ts,为数据库中所有缺失向量的历史消息批量补算 embedding(默认 worker 池 50、批大小 10,可用WORKER_POOL_SIZE/BATCH_SIZE覆盖),适合在接入新嵌入模型或维度后回填历史数据。

七、可观测性

机器人全程埋点 OpenTelemetry(见 src/index.ts 与各模块中的trace.getTracer('airi.telegram.bot')):

  • Trace:动作决策、LLM 调用、embedding、向量检索等都有 span,且带telegram.bot.id、llm.chat.model、llm.provider.api_base_url等属性,可通过OTEL_EXPORTER_OTLP_TRACES_ENDPOINT(默认http://localhost:4318/v1/traces)导出;
  • Metrics:PeriodicExportingMetricReader每 5 秒通过OTEL_EXPORTER_OTLP_METRICS_ENDPOINT(默认http://localhost:4318/v1/metrics)上报。

配合 4.1 节启动的 docker-compose 栈,即可在 Grafana 中直接查看 AIRI 每次决策的完整调用链与 LLM 消耗指标。


八、从零启动核对清单

  1. 根目录执行pnpm i && pnpm run build:packages;
  2. ollama start && ollama pull nomic-embed-text;
  3. cd integrations/telegram-bot && cp .env .env.local,按 3.3 节填入 Token、LLM、视觉模型与嵌入模型配置(EMBEDDING_DIMENSION必须设置);
  4. docker compose up -d启动 pgvector(及可选的 Grafana / Tempo / Prometheus);
  5. pnpm run -F @proj-airi/telegram-bot start启动机器人;
  6. 在 Telegram 中与 Bot 对话,或把它拉进群组;如需管理贴纸,可通过/add_sticker_pack命令(需将你的 ID 加入ADMIN_USER_IDS)回复任意贴纸所在的表情包,让 AIRI 学会使用贴纸。

部署完成后,AIRI 便会在 Telegram 中作为一位有性格、有记忆、会自主决定“要不要说话”的数字实体持续运行——这正是 README 所描述的“talk to you and many other users”能力,也是 airi 项目“自托管、归你所有”理念在 IM 平台上的完整落地。

  • 人工智能
  • AI Agent
  • MCP 服务
  • 工具调用
  • GUI 自动化
  • 语音
  • 数字人
  • 交互助手

【免费下载链接】airi

💖🧸 自托管、归你拥有的 Grok 风格 AI 伴侣与 waifu / 赛博生命灵魂容器,目标是接近 Neuro-sama 的高度;支持实时语音聊天、Minecraft 和 Factorio 游玩,支持 Web / macOS / Windows。

项目地址:https://gitcode.com/moeru-ai/airi
点击查看免费下载

相关推荐

上一篇:CorsixTH 快速上手指南:3 步在电脑上免费重开 1997 年的主题医院
下一篇:FitGirl游戏下载器终极指南:3步搭建你的个人游戏管家

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

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

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

立即咨询