
Airi 项目 Telegram 机器人部署实战从环境配置到 LLM 驱动的群聊 AI 接入【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airiAiriアイリ是 moeru-ai 旗下的自托管 AI 陪伴项目而integrations/telegram-bot是其官方 Telegram 集成模块让 Airi 能够在 Telegram 中与你和群聊里的其他用户对话。本文基于该模块的 README完整讲解从克隆仓库、安装依赖、配置 LLM / 向量数据库 / Telegram Bot Token到启动服务并接入 PostgreSQL 向量库pgvecto-rs与可观测性组件OpenTelemetry / Prometheus / Tempo / Grafana的整套流程同时结合源码剖析其LLM 生成动作 → 动作分发执行的自主 Agent 运行机制帮助你独立部署并二次开发属于自己的 Telegram AI 伙伴。一、模块概览这个 Telegram Bot 能做什么integrations/telegram-bot是一个基于 grammY 框架对应依赖grammy见 package.json构建的 TypeScript 服务。与普通一问一答的机器人不同它的核心循环是一个由 LLM 驱动的动作选择循环每次收到消息后Bot 将当前聊天历史、已执行动作、未读消息统计等信息打包成提示词交给 LLM 判断接下来应该做什么LLM 返回 JSON 形式的动作指令再由代码分发执行。可执行的动作类型定义在 src/types.ts 中包括动作参数作用continue无承认指令继续循环直到下一轮 tickbreak无清空当前聊天的消息与动作记忆sleep无睡眠 30 秒后继续list_chats无列出所有加入过的聊天send_messagecontent,chatId向指定聊天发送文本消息send_stickerfileId,chatId向指定聊天发送已注册的表情包贴纸search_googlequery预留的 Google 搜索动作read_history_messageschatId,beforeMessageId?,afterMessageId?读取历史消息read_unread_messageschatId读取指定聊天中的未读消息list_stickers无列出当前记忆分区中已注册的贴纸消息处理主循环位于 src/bots/telegram/index.ts文本、图片、贴纸消息进入messageQueue按pending → interpreting → ready状态流转随后触发即时反应循环loopIterationForChat此外每 60 秒会执行一次周期性循环loopPeriodic让 Airi 即使没有新消息也能主动思考。二、环境准备克隆仓库与安装依赖在开始之前你需要一台能运行 Node.js本项目使用tsx直接运行 TypeScript依赖由 pnpm workspace 统一管理的 Linux/macOS 机器并完成以下步骤git clone gitgithub.com:moeru-ai/airi.git pnpm i pnpm run build:packagespnpm run build:packages会构建仓库内被本模块依赖的本地包如xsai/generate-text、xsai/embed、moeru/std、guiiai/logg等见 package.json 中的 catalog 依赖因此必须先执行否则直接启动会因找不到工作区包而失败。三、启动本地 Ollama 提供 Embedding 模型Bot 的记忆检索与贴纸/图片语义描述依赖向量化能力仓库的默认配置使用本地 Ollama 提供 embedding 服务ollama start ollama pull nomic-embed-textnomic-embed-text是默认的 embedding 模型输出 768 维向量。启动后Ollama 会在本机11434端口提供 OpenAI 兼容的/v1/接口对应环境变量中的EMBEDDING_API_BASE_URLhttp://localhost:11434/v1/。embedding 的调用在 src/llm/sticker.ts 等模块中通过xsai/embed完成。四、配置环境变量核心配置项逐一解读4.1 创建 .env.local进入模块目录复制模板并填写配置cd integrations/telegram-bot cp .env .env.local.env模板位于 integrations/telegram-bot/.env包含数据库、Telegram、LLM 三组凭据。启动命令pnpm run -F proj-airi/telegram-bot start实际执行的是tsx --env-file.env --env-file-if-exists.env.local ... src/index.ts见 package.json即.env作为基准配置、.env.local作为覆盖项加载——因此敏感凭据应写入.env.local不要提交到版本库。4.2 必填配置项清单变量含义示例/说明DATABASE_URLPostgreSQL 连接串postgres://postgres:123456localhost:5433/postgres注意 compose 将宿主机 5433 映射到容器 5432TELEGRAM_BOT_TOKENTelegram Bot Token形如Bot ID:Token通过 BotFather 获取格式Bot ID:TokenLLM_API_BASE_URL主对话 LLM 的 OpenAI 兼容接口地址如 OpenRouterhttps://openrouter.ai/api/v1/LLM_API_KEY主对话 LLM 的 API Key如sk-or-v1-tokenLLM_MODEL主对话模型名如deepseek/deepseek-chat-v3-0324:freeLLM_RESPONSE_LANGUAGEAiri 回复使用的语言如English会注入提示词模板见下文LLM_VISION_API_BASE_URL视觉理解 LLM 接口地址可复用主 LLM 的地址LLM_VISION_API_KEY视觉理解 LLM 的 API Key—LLM_VISION_MODEL视觉理解模型名如openai/gpt-4o只要模型支持图片输入即可EMBEDDING_API_BASE_URLEmbedding 服务地址如 Ollamahttp://localhost:11434/v1/EMBEDDING_API_KEYEmbedding API KeyOllama 本地可留空EMBEDDING_MODELEmbedding 模型如nomic-embed-textEMBEDDING_DIMENSION向量维度必须设置与所用 embedding 模型一致如768ADMIN_USER_IDS管理员用户 ID 列表逗号分隔如123456,789012用于校验/add_sticker_pack等管理命令一个可直接参考的完整示例README 原样给出DATABASE_URLpostgres://postgres:123456localhost:5433/postgres TELEGRAM_BOT_TOKENBot ID:Token # get one from BotFather LLM_API_BASE_URLhttps://openrouter.ai/api/v1/ # if you use OpenRouter too LLM_API_KEYsk-or-v1-token LLM_MODELdeepseek/deepseek-chat-v3-0324:free LLM_RESPONSE_LANGUAGEEnglish LLM_VISION_API_BASE_URLhttps://openrouter.ai/api/v1/ LLM_VISION_API_KEYsk-or-v1-token LLM_VISION_MODELopenai/gpt-4o # as long as the model supports image input EMBEDDING_API_BASE_URLhttp://localhost:11434/v1/ # ollama EMBEDDING_API_KEY EMBEDDING_MODELnomic-embed-text # embedding model EMBEDDING_DIMENSION768 # must set4.3 配置项在源码中的实际作用LLM_RESPONSE_LANGUAGE被 src/prompts/index.ts 中的systemTicking()以{ responseLanguage: env.LLM_RESPONSE_LANGUAGE }的形式注入system-ticking-v1.velin.md提示词模板控制 Airi 的人格心智时钟与回复语言。LLM_API_*在 src/llm/actions.ts 中构造generateText请求apiKey/baseURL/model用于想象下一个动作同时这里有一个隐藏开关LLM_OLLAMA_DISABLE_THINK当使用带思考模式的 Ollama 模型时可设为任意非空值请求会附带think: false并在拿到响应后通过正则think[\s\S]*?\/think剥离思考内容actions.ts、sticker.ts 均有此处理。LLM_VISION_API_*在 src/llm/sticker.ts 与 src/llm/photo.ts 中将贴纸/图片转为data:image/png;base64后以多模态消息发送给视觉模型生成为视障人士服务的详细描述。EMBEDDING_*为消息、贴纸、照片、记忆片段生成向量用于相似度检索。向量维度与数据库表结构强相关详见下一节。ADMIN_USER_IDS在 src/bots/telegram/index.ts 的isChatIdBotAdmin中校验只有管理员能执行/add_sticker_pack回复一条贴纸消息即可将整个贴纸包登记并逐一解读入库。五、启动数据库与 Bot5.1 一键启动 PostgreSQL 可观测性全家桶docker compose up -d pnpm run -F proj-airi/telegram-bot startdocker-compose.yaml 默认拉起 5 个服务服务镜像端口作用pgvectorghcr.io/tensorchord/pgvecto-rs:pg17-v0.4.05433→5432PostgreSQL 17 向量扩展数据卷挂载./.postgres/datagrafanagrafana/grafana3000可视化面板预置 dashboards 与 datasourcestempografana/tempo:latest3200/9095分布式追踪后端配置见 tempo.yamlprometheusprom/prometheus9090指标采集启用 OTLP 接收器与 exemplar 存储配置见 prometheus.ymlotel-collectorotel/opentelemetry-collector4317/4318OpenTelemetry Collector汇聚 traces/metrics 后分发到 Tempo 与 Prometheus配置见 collector-config.yaml另有otel-tracing-test服务profiles: [test]用docker compose --profile test up可启用用于注入模拟 trace 压力测试。数据库初始化脚本 sql/init.sql 会在首次启动时执行ALTER SYSTEM SET vectors.pgvector_compatibilityon;并创建vectors扩展保证向量类型与标准 pgvector 语法兼容。5.2 数据库表结构与向量维度表结构由 src/db/schema.ts 通过 Drizzle ORM 定义核心表包括chat_messages聊天消息含content文本与三列向量content_vector_768/1024/1536并为每列建立 HNSW 余弦相似度索引stickers/sticker_packs/recent_sent_stickers贴纸记忆体系贴纸保存image_base64、description由视觉模型生成及对应向量photos图片消息的语义描述与向量joined_chats机器人加入过的聊天记录chat_completions_historyLLM 请求/响应留痕memory_fragments记忆碎片、memory_tags、memory_episodic、memory_long_term_goals、memory_short_term_ideas面向长期记忆的分层记忆系统支持working/short_term/long_term/muscle类型、importance1-10、emotional_impact-10~10等元数据同样为 768/1024/1536 三种维度分别建向量索引。重要约束EMBEDDING_DIMENSION必须与所用 embedding 模型的输出维度一致nomic-embed-text为 768否则写入向量列时会因维度不匹配而报错——这正是 README 强调 must set 的原因。三种维度768/1024/1536并存的设计是为了兼容不同 embedding 模型而预留的扩展空间。数据库 Schema 迁移文件位于 drizzle 目录0000_*.sql~0005_*.sql共 6 个迁移如需推送 Schema 变更可使用pnpm run -F proj-airi/telegram-bot db:push基于 drizzle.config.ts 的DATABASE_URL。5.3 启动时的行为src/index.ts 是进程入口启动顺序为配置guiiai/logg的全局格式与日志级别Pretty / Debug创建 OpenTelemetry NodeSDK以moeru_ai.airi.telegram_bot为服务名注册 OTLP Trace/Metric 导出器默认端点http://localhost:4318可用OTEL_EXPORTER_OTLP_TRACES_ENDPOINT/OTEL_EXPORTER_OTLP_METRICS_ENDPOINT覆盖指标每 5 秒批量导出一次调用initDb()建立 Drizzle 数据库连接调用startTelegramBot()启动 grammY Bot注册message:text/message:photo/message:sticker三个处理器与管理命令/add_sticker_packdrop_pending_updates丢弃启动前的堆积更新随后开启 60 秒周期的自主循环。六、工作原理LLM 驱动的 Agent 循环6.1 想象动作提示词每次循环都会调用imagineAnAction()src/llm/actions.ts其构造的提示词包含System 侧systemTicking()人格心智时钟与personality()人格描述两份 Velin 模板拼装User 侧正在进入的消息、历史动作列表History actions、服务器当前时间并提示时区差异、各聊天的未读消息数量统计最后要求仅以 JSON 返回下一个要执行的动作不要任何解释与标记。6.2 响应的容错解析由于 LLM 输出不稳定代码做了多层归一化剥离去掉json代码块包裹使用best-effort-json-parser容错解析参数扁平化若模型把参数包在parameters对象里则展开到顶层动作别名归一化read_messages、get_unread_messages、check_messages、get_messages_from_chat、Read_unread_messages→read_unread_messagesreply_to_a_message_from_a_chat、reply_message→send_message字段别名归一化recipient_id/group_id/chat_id/user_id/conversation_id/unread_message_id/id统一为chatIdmessage/text/chat_message统一为content兜底推断若未显式给出chatId且只有一个聊天存在未读消息则自动补为该聊天的 ID。6.3 动作分发与上下文裁剪解析出的动作由dispatchActionsrc/bots/telegram/index.ts通过switch分发执行。几个值得注意的设计多数动作会向chatCtx.actions追加动作 结果记录并返回下一个循环步骤形成链式循环loopIterationForChat中的while不断执行返回的函数直到模型决定continue等待下个 tick或break上下文自动裁剪当单聊messages超过 20 条时只保留最近 5 条并注入系统提示说明历史已裁剪actions超过 50 条时保留最近 20 条index.ts消息去重processedIds集合以${chat.id}-${message_id}去重每聊未读消息队列上限 100 条break会清空messages与actions让 Airi 重置短期记忆sleep则让循环暂停 30 秒源码中保留了attention-handler注意力/响应率调控与interruption新消息打断模块目前处于注释状态属于从源码结构推断的规划中能力尚未默认启用。6.4 贴纸与图片的多模态理解收到贴纸时interpretStickersrc/llm/sticker.ts会对动态贴纸is_animated/is_video转交interpretAnimatedSticker基于 fluent-ffmpeg ffmpeg-installer 抽取帧静态贴纸通过bot.api.getFile Telegram 文件接口下载经napi-rs/image转为 PNG Base64将该贴纸属于哪个贴纸包、代表 emoji、由谁发送等上下文与图片一起交给视觉模型要求尽可能详细地描述包括 meme 深层含义与文化梗将描述与file_id、image_base64存入stickers表供后续list_stickers/send_sticker动作检索使用。七、数据库迁移与批量回填除启动外模块还提供两个运维脚本见 package.json# 基于当前 schema 生成迁移文件 pnpm run -F proj-airi/telegram-bot db:generate # 推送 schema 变更到数据库自动加载 .env 与 .env.local忽略缺失的 env 文件 pnpm run -F proj-airi/telegram-bot db:push # 批量对历史聊天消息生成 embedding 向量并回填数据库 pnpm run -F proj-airi/telegram-bot script:embed-chat其中script:embed-chat对应 scripts/embed-all-chat-messages.ts用于在接入向量检索前为chat_messages表的历史数据批量补齐向量列。八、快速自检清单部署完成后可按以下顺序验证系统是否就绪docker compose ps确认 pgvector / otel-collector / prometheus / tempo / grafana 五个容器均为 healthy 状态观察 Bot 日志出现bot initialized且携带bot_username字段index.ts说明 Token 有效且已连上 Telegram在私聊或群聊中 Airi 发送普通文本日志中应出现Generated action记录含 token 用量与未读消息统计向 Bot 发送贴纸等待日志出现Interpreted sticker随后可用/add_sticker_pack需管理员登记整个贴纸包打开 Grafanahttp://localhost:3000已开启匿名登录并禁用登录表单查看 Trace/指标是否持续写入若发现上下文被裁剪提示Approaching to system context limit属正常现象说明长对话保护机制在按预期工作。相关文件索引部署与配置入口integrations/telegram-bot/README.md、integrations/telegram-bot/.env进程入口与可观测性初始化integrations/telegram-bot/src/index.ts机器人主循环与动作分发integrations/telegram-bot/src/bots/telegram/index.tsLLM 动作生成与容错解析integrations/telegram-bot/src/llm/actions.ts多模态理解贴纸/图片/动图src/llm/sticker.ts、src/llm/photo.ts、src/llm/animated-sticker.ts数据库表结构与向量索引integrations/telegram-bot/src/db/schema.tsDocker 编排与观测配置integrations/telegram-bot/docker-compose.yaml 及 deploy 目录提示词模板integrations/telegram-bot/src/promptspersonality-v1 / system-ticking-v1 / action-* 等 Velin 模板【免费下载链接】airi Self hosted, you-owned Grok Companion, a container of souls of waifu, cyber livings to bring them into our worlds, wishing to achieve Neuro-samas altitude. Capable of realtime voice chat, Minecraft, Factorio playing. Web / macOS / Windows supported.项目地址: https://gitcode.com/GitHub_Trending/ai/airi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考