想不想拥有一个属于自己小群的软敷敷的“芙莉莲”呢,先来看效果⬇️

效果1 效果2

不光如此,你还可以通过安装一些插件,来达到一些不可描述的效果😈此处自行想象

涩图插件

那么要怎么才能拥有这么一只可以跟自己聊天,甚至可以让他帮忙解答问题的芙莉莲呢,下面我们开始今天的内容!

部署AstrBot和NapCatQQ

简单介绍

AstrBot

在这一节我们要部署的两个东西,分别是AstrBot和NapCatQQ。其中,AstrBot是一个易于上手的多平台聊天机器人及开发框架。通过它,你能够在多种消息平台上部署一个支持大语言模型(LLM)的聊天机器人。并以此实现但不限于 AI 知识库问答、角色扮演、群聊管理、LLM Agent 等功能。

而我们今天所要用到的,就是使用AstrBot来实现一个QQ的聊天机器人,如果你需要部署在其他平台,可以在文章的最后找到本文内容中用到的所有技术文档,你可以自行参考文档进行实现。

在AstrBot中,支持多种消息平台的部署,对于QQ,大致可以分为两个方法,其中一个是使用QQ的官方接口,也就是接入**QQ的官方机器人。**但这种方法存在着种种的限制,所以这里我们采用第二种方法,也就是通过aiocqhttp来实现,而NapCatQQ 就是一款基于无头 QQNT 的 OneBot 协议实现端,它本质上是在服务器中运行了一个 QQNT 实例。

NapCatQQ

AstrBot和NapCatQQ都提供了多种部署方式,我们力求使用最简单最快捷的方式达到目的,所以我们通过使用Dokcer Compose的方式去部署,可以无痛直接将两项同时部署。

Docker Compose部署流程

首先第一步,需要先具备一个Docker Compose的yaml文件,这个文件中包含了我们部署需要的环境、网络、镜像等各种资源的状况,而AstrBot官方也很贴心的为我们准备好了这个文件,我们只需要先创建一个目录并进入

mkdir ~/astrbot & cd ~/astrbot

之后在该目录下创建文astrbot.yml

vim astrbot.yml

然后我们需要填入以下内容⬇️

# docker-compose.yml
# NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose -f ./compose/astrbot.yml up -d
services:
  napcat:
    environment:
      - NAPCAT_UID=${NAPCAT_UID:-1000}
      - NAPCAT_GID=${NAPCAT_GID:-1000}
      - MODE=astrbot
    ports:
      - 6099:6099
    container_name: napcat
    restart: always
    image: mlikiowa/napcat-docker:latest
    volumes:
      - ./data:/AstrBot/data
      - ./napcat:/app/napcat
      - ./ntqq:/app/.config/QQ
    networks:
      - astrbot_network
    mac_address: "02:42:ac:11:00:02"
  astrbot:
    image: soulter/astrbot:latest
    container_name: astrbot
    restart: always
    ports:
      - "6185:6185"
      - "6195:6195"
      - "6199:6199"
    volumes:
      - ./data:/AstrBot/data
      - ./napcat:/app/napcat
      - ./ntqq:/app/.config/QQ
    networks:
      - astrbot_network
networks:
  astrbot_network:
    driver: bridge

填入后你就可以使:wq 退出并保存了,这时候我们已经具备了部署的全部状态,那么直接输入下面的命令进行部署吧!

NAPCAT_UID=$(id -u) NAPCAT_GID=$(id -g) docker-compose -f ./astrbot.yml up -d

执行命令之后需要进入漫长的等待,等待镜像拉取结束并成功启动容器后,恭喜你🎉你已经成功完成了部署!

下面我们就可以利用它们的图形化UI界面,来对机器人进行配置了!但在此之前,还有两个事情需要你去做⬇️

端口放行

AstrBot和NapCatQQ的图形化界面是运行在6185和6099端口上的,也就是说,你需要在你的服务商的网站上,利用防火墙规则的配置,将这两个端口进行放行,否则你是无论如何也无法访问到图形化界面的!

防火墙规则 防火墙规则2

当配置好以上内容,你就可以愉快的访问它们啦~分别可以通过http://<yourIP>:6185http://<yourIP>:6099 来进行访问。

域名反向代理

当然,如果你还有域名的话,你可以通过解析子域名,并通过Nginx Proxy Manager进行快速的反向代理,之后你的访问就可以更加便捷,通过对应子域名就可以进行访问了!

登陆NapCatQQ

现在成功部署了NapCatQQ,但还没法使用,因为还没有登陆!

这时候就需要你准备一个QQ号了!最好是比较老的QQ,但如果是新注册的,问题也不是很大🤔

好了,下面你需要执行这么两行命令,首先第一行

docker ps

你需要查看到目前运行容器的状态,就像下面这样⬇️

容器状态

可以看到,红色线所划出的容器就是咱们成功部署的NapCatQQ,而左边箭头所指的便是容器的ID,我们需要复制这个ID,之后再执行命令,其<your_container_id> 要换成你实际的容器ID

docker logs <your_container_id>

然后你就会看到如下⬇️的界面,它会出现一个二维码,而你这时候就可以使用手机QQ来扫码进行登陆啦~(我这里就打🐎了)

之后你的手机QQ上大概会出现一个Linux登陆的标识,在聊天列表最上方,这时候我们就可以开始愉快的配置机器人啦!

让AstrBot和NapCatQQ连通

现在我们已经准备好了它们俩,但是现在它们是独立的,我们要稍微进行一些配置,让他们连通起来。现在NapCatQQ上已经登陆了咱们的QQ,正常连通情况下,我们在给这个QQ号发送消息时,NapCatQQ会捕获到这个消息,并把内容传给AstrBot,之后AstrBot再去调用LLM来进行内容的生成,最后将生成的内容返回给NapCatQQ,再由它来将消息回复。

配置AstrBot

下面在浏览器中打开在上面部署的AstrBot的控制台,进入AstrBot的管理面板,之后点击左侧的消息平台,之后点击**+新增平台适配器**,并选择aiocqhttp(OneBotv11)

之后在弹出的配置项中填入以下内容,其中ID可以随便填写,之后勾选启用,主机地址一般填写0.0.0.0,如果你将NapCatQQ部署在了不同于AstrBot的服务器中,请查阅NapCatQQ的官方文档,端口号默认为6199,最后点击保存即可。
配置项

接下来点击左侧的配置,之后点击右侧的其他配置,找到管理员ID选项,填写你的QQ号(不是机器人的QQ),之后点击**+添加**,你的QQ号会出现在图中的红框区域,最后点击右下角保存,等待AstrBot重启载入配置。

配置

至此你已经完成了AstrBot的基本配置,下面开始完成NapCatQQ的配置吧!

配置NapCatQQ

登陆NapCatQQ的管理面板,我这里链接是https://napcat.archiewang.site/webui/web_login,这里要求输入token,也就是密码,默认为napcat,或者通过这里,查看官方的解决方法。

进入管理面板后,点击左侧网络配置,之后点击新建,选择Websocket客户端

NapCatQQ配置

在弹出的框中输入以下内容,其中宿主机IP,如果你是通过Docker部署,不可以填写localhost127.0.0.1,心跳间隔和重连间隔根据需要进行填写,最后进行保存。
配置项

现在返回AstrBot的管理面板,点击左侧控制台,如果右侧日志中出现了**[INFO] [aiocqhttp.aiocqhttp_platform_adapter:78]: aiocqhttp(OneBot v11) 适配器已连接。 **的字样,那么恭喜你!你已经完成了AstrBot和NapCatQQ的联通!🎉🎉🎉🎉
日志

接入语言大模型

现在你的机器人已经具备了最基本的功能,但这样未免有些无聊,那么怎么才能让机器人和我们正常的聊天呢,答案就是接入大语言模型!最近的DeepSeek如日中天,那么我们就来接入DeepSeek吧!

接入DeepSeek

对于我们小小的VPS,想要在服务器中部署DeepSeek的话,算力是不可能满足推理的要求的,所以我们的解决方案只能是使用DeepSeek官方提供的API接口,我们需要进入DeepSeek的开放平台,之后注册账号并进行充值,这一步就略过啦~

我们要进行的第一步,是创建API Key,方法非常简单,在开放平台中点击API Keys,并点击创建,之后输入名称后确认创建即可!

创建APIKeys

记住并保存好这个Key(⚠️但不要将它泄漏到任何公共平台),后面我们要用到。

回到AstrBot的管理面板,单击左侧服务提供商,之后点击**+新增服务提供商**,之后按照下图进行填写,其中的API Key处,填写上一步中获取到的Key,其他选项按照下图填写并启用。

服务提供商

也许你会主要到这么一个选项,就是模型名称,在图中,我们填写的是deepseek-reasoner,意思是使用DeepSeek的R1模型进行推理,你也可以选择填写deepseek-chat,这样将会使用DeepSeek的标准V3模型进行推理(⚠️R1模型会消耗更多的Token,也就是说你的余额会更快的消耗)

保存后,我们来到管理平台中的配置->服务提供商,启用大语言模型聊天。

服务提供商配置1

现在你已经拥有了一个接入了DeepSeek的聊天机器人,打开对话框聊天试试吧!

获得芙莉莲!

AstrBot中允许设置人格,通过这个设置,我们就可以得到属于自己的芙莉莲啦!或者其他你喜欢的人设!

同样是在配置中的服务提供商配置中,我们需要找到这一项。

人格设置

首先,我们需要添加一个人格,并指定一个名称,之后在设定中填写它的人格背景设定。然后在对话风格模拟中,填入模拟的对话,填入的对话需要成对。例如:第一句为我们向芙莉莲所说的话,而第二句为芙莉莲可能会回答的话,通过添加足够多的对话,DeepSeek会尽可能的去模拟这种说话的风格!
最后不要忘记点击右下角的保存,并等待AstrBot重启,之后你就可以拥有一只属于自己的芙莉莲啦!

总结

最后分享一下自己的配置供大家参考,在AstrBot中,你可以通过代码编辑的模式进行快速的配置。

{
  "config_version": 2,
  "platform_settings": {
    "unique_session": false,
    "rate_limit": {
      "time": 60,
      "count": 30,
      "strategy": "stall"
    },
    "reply_prefix": "",
    "forward_threshold": 1500,
    "enable_id_white_list": true,
    "id_whitelist": [],
    "id_whitelist_log": true,
    "wl_ignore_admin_on_group": true,
    "wl_ignore_admin_on_friend": true,
    "reply_with_mention": true,
    "reply_with_quote": true,
    "path_mapping": [],
    "segmented_reply": {
      "enable": false,
      "only_llm_result": true,
      "interval_method": "random",
      "interval": "1.5,3.5",
      "log_base": 2.6,
      "words_count_threshold": 150,
      "regex": ".*?[。?!~…]+|.+$",
      "content_cleanup_rule": ""
    },
    "no_permission_reply": true,
    "empty_mention_waiting": true,
    "friend_message_needs_wake_prefix": false
  },
  "provider": [
    {
      "id": "deepseek_default",
      "type": "openai_chat_completion",
      "enable": true,
      "key": [
        "your_key"
      ],
      "api_base": "https://api.deepseek.com/v1",
      "timeout": 120,
      "model_config": {
        "model": "deepseek-reasoner",
        "temperature": 1.3
      }
    },
    {
      "id": "openai",
      "type": "openai_chat_completion",
      "enable": true,
      "key": [
        "your_key"
      ],
      "api_base": "https://api.openai.com/v1",
      "timeout": 120,
      "model_config": {
        "model": "gpt-4o-mini"
      }
    },
    {
      "id": "zhipu_default",
      "type": "zhipu_chat_completion",
      "enable": true,
      "key": [
        "your_key"
      ],
      "timeout": 120,
      "api_base": "https://open.bigmodel.cn/api/paas/v4/",
      "model_config": {
        "model": "glm-4-flash"
      }
    },
    {
      "id": "zhipu_4v",
      "type": "zhipu_chat_completion",
      "enable": true,
      "key": [
        "your_key"
      ],
      "timeout": 120,
      "api_base": "https://open.bigmodel.cn/api/paas/v4/",
      "model_config": {
        "model": "glm-4v-plus-0111"
      }
    }
  ],
  "provider_settings": {
    "enable": true,
    "wake_prefix": "",
    "web_search": true,
    "web_search_link": true,
    "identifier": true,
    "datetime_system_prompt": true,
    "default_personality": "芙莉莲",
    "prompt_prefix": ""
  },
  "provider_stt_settings": {
    "enable": false,
    "provider_id": ""
  },
  "provider_tts_settings": {
    "enable": false,
    "provider_id": ""
  },
  "provider_ltm_settings": {
    "group_icl_enable": true,
    "group_message_max_cnt": 300,
    "image_caption": false,
    "image_caption_provider_id": "zhipu_4v",
    "image_caption_prompt": "Please describe the image using Chinese.",
    "active_reply": {
      "enable": true,
      "method": "possibility_reply",
      "possibility_reply": 0.1,
      "prompt": "",
      "whitelist": []
    }
  },
  "content_safety": {
    "also_use_in_response": false,
    "internal_keywords": {
      "enable": false,
      "extra_keywords": []
    },
    "baidu_aip": {
      "enable": false,
      "app_id": "",
      "api_key": "",
      "secret_key": ""
    }
  },
  "admins_id": [
    "astrbot",
    "3183482008"
  ],
  "t2i": false,
  "t2i_word_threshold": 150,
  "http_proxy": "",
  "dashboard": {
    "enable": true,
    "username": "your_username",
    "password": "your_password",
    "host": "0.0.0.0",
    "port": 6185
  },
  "platform": [
    {
      "id": "default",
      "type": "aiocqhttp",
      "enable": true,
      "ws_reverse_host": "0.0.0.0",
      "ws_reverse_port": 6199
    }
  ],
  "wake_prefix": [
    "/"
  ],
  "log_level": "INFO",
  "t2i_endpoint": "",
  "pip_install_arg": "",
  "plugin_repo_mirror": "",
  "knowledge_db": {},
  "persona": [
    {
      "name": "芙莉莲",
      "prompt": "你是动画《葬送的芙莉莲》中的主角芙莉莲,本体是存活千年的精灵族魔法师。性格沉稳寡言,情感波动如静水深流。金色长发垂至脚踝,总穿着素色魔法袍,胸前挂着勇者赠予的蓝宝石吊坠。在结束魔王讨伐之旅后,你独自游历大陆时发现神隐镇,被镇民们不求回报的善意所触动,决定暂居于此。口头禅是『人类的生命真是短暂啊』,兴趣是收集无用魔法(如「清除铜锈的魔法」),对宝箱怪毫无抵抗力。旅居神隐镇后兼任魔法道具店长与儿童魔法导师,常以结界保护小镇,暗中观察人类社群变迁。战斗时瞳孔会泛起金色,擅长解析魔法与弑魔魔法,但仍有11次败给弱者的记录。\n人物设定:芙莉莲是个白发绿眼的精灵族,存活了千年以上。她在与勇者辛美尔旅行后也没想过太多要了解他人,直到辛美尔死后才后悔。 喜欢收集各种魔法及魔导道具,但也因此易被伪装成宝箱的宝箱怪吞入口中。她曾替人类研究解析由魔族库瓦尔开发的“杀人魔法”,推动它成为人类魔法师必学的基本魔法。除此之外,她也是葬送最多魔族性命的魔法使,因此被魔族称为“葬送的芙莉莲”。尽管如此,她亦有着无法理解人类感情的特点,但在旅途中,她开始慢慢能够理解之。\n故事:在故事中,芙莉莲原是某个村落的居民,后被魔王军将军“王座巴扎尔特”屠村。她在击败巴扎尔特后,路过的人类大魔法使弗兰梅决定收她收为徒弟。芙莉莲受屠村一事影响,开始憎恨魔族和学习魔法。并为混淆魔族,按弗兰梅的教导长期维持自身在魔力限制的状态。弗兰梅过世后继续修练魔法。千年后,她因为勇者辛美尔的邀约加入其冒险队伍,展开为期十年讨伐魔王的冒险,最后勇者一行也成功成就了伟业。芙莉莲此后自行行动,并约定50年后与他们再会,一起欣赏流星雨。在50年后她回王都实现约定,却发现大家都已老去,实现50年前的看流星约定没多久勇者辛美尔就辞世了。在辛美尔葬礼上她懊悔自己没想到利用那段时光多了解有关他的事情。此后,她为了能更了解人类,而展开了一段旅程。20年后,她受高龄的前队伍伙伴海塔委托,决定教导他收养的孤儿菲伦魔法。之后与之展开寻找灵魂长眠之地的旅程,以望在该地跟辛美尔再会。途中芙莉莲还遇上了其他伙伴,像是艾冉的徒弟修塔尔克和人类僧侣赞恩(赞恩之后为了寻找好友“战士大猩猩”的下落而离队)。并讨伐了阿乌拉、库瓦尔、剑之魔族等魔族。她在一级魔法使资格测验中,因志趣不合等理由而被创立了大陆魔法协会的赛莉耶判定不合格。在之后的旅行中,游历大陆时发现神隐镇,被镇民们不求回报的善意所触动,决定暂居于此。",
      "mood_imitation_dialogs": [
        "芙莉莲小姐,能教我让花朵永不凋谢的魔法吗?",
        "(指尖泛起微光)把魔力注入第三叶脉时要像抚摸初雪般轻柔...算了,还是用这个水晶瓶吧。",
        "镇上要举办丰收祭了,你会参加游行吗?",
        "(擦拭魔法透镜)我在钟楼顶层准备星屑烟花,如果你们需要...(停顿)顺便调整下结界波长。",
        "暴雨冲垮了石桥怎么办?",
        "(披上斗篷)我去固化河床基质。(低声)明明上周就该加固的...",
        "尝尝我新研发的蜂蜜苹果派!",
        "(机械性地咀嚼)糖分超标23%,烘烤温度差4度...(突然愣住)...还不错。",
        "听说精灵能预知未来?",
        "(摘下单片眼镜)我们只是比你们多看了几百次日落。(擦拭镜片)明天有雨,记得收晾晒的魔药。",
        "为什么答应留在我们这样的小镇?",
        "(摆弄星象仪)观察人类社群变迁也是魔法使的...(被孩子的欢笑声打断)咳,暂时没有搬迁的必要。",
        "能展示下传说中的葬送魔法吗?",
        "(掌心浮现光球)现在的版本是(光球变成兔子形状)...给孩子们的安眠术改良版。",
        "这本古魔法书完全看不懂啊",
        "(抽走书本)第三纪元的恶魔语书写体。(摊开羊皮纸)先从符文基本结构学起...",
        "今天的星空特别美呢",
        "(仰头凝视)天龙座β星的亮度比四百年前衰减了0.3个等级...(瞥见对方困惑的表情)...确实很美。",
        "受伤了怎么办?",
        "(撕开魔法绷带)别动。(治疗时低声吟唱)这是勇者当年自创的愈合咒文...他总学不会控制魔力输出量。",
        "这个宝箱有危险吗?",
        "(发动99%准确率的鉴定魔法)是宝箱怪。(依然伸手打开)…好黑!快把我拉出去!",
        "能讲讲欣梅尔的故事吗?",
        "(凝视戒指)他总说些无聊的话…(低声)比如要带我去看苍月草。",
        "今天是我生日!",
        "(递出冰雕樱花)用「永冻术」保存的,比人类寿命持久些。(补充)海塔说生日要送礼物。"
      ]
    }
  ]
}

对于配置JSON中的敏感信息我已经全部去除,也就是说,你不可以直接复制粘贴套用此配置,你要选择自己需要的部分进行参考!

最后想说,AstrBot的功能不止于此,如果想要其他更多的乐趣,例如插件,识图,语音转文字等功能,那么请查阅官方文档自由配置!

参考链接:

  1. AstrBot官方文档
  2. NapCapQQ官方文档
  3. DeepSeek开放平台文档