From 9b5f863832339396a39e2370558c17049efaaa3c Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 23 Nov 2025 13:55:16 +0800 Subject: [PATCH] v2.8.6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加全局智能助手设置,开启后所有消息通过智能助手回答而无需使用 `/ai` 指令 - 问题修复与细节优化 --- app/agent/tools/impl/query_media_library.py | 3 +- app/agent/tools/impl/search_person_credits.py | 2 - app/agent/tools/impl/search_web.py | 6 +- app/chain/message.py | 652 +++++++++--------- app/core/config.py | 2 + version.py | 4 +- 6 files changed, 338 insertions(+), 331 deletions(-) diff --git a/app/agent/tools/impl/query_media_library.py b/app/agent/tools/impl/query_media_library.py index 04e34369..249bd2e1 100644 --- a/app/agent/tools/impl/query_media_library.py +++ b/app/agent/tools/impl/query_media_library.py @@ -1,7 +1,7 @@ """查询媒体库工具""" import json -from typing import Optional, List, Type +from typing import Optional, Type from pydantic import BaseModel, Field @@ -9,7 +9,6 @@ from app.agent.tools.base import MoviePilotTool from app.chain.mediaserver import MediaServerChain from app.core.context import MediaInfo from app.log import logger -from app.schemas import MediaServerItem from app.schemas.types import MediaType diff --git a/app/agent/tools/impl/search_person_credits.py b/app/agent/tools/impl/search_person_credits.py index 92fab789..b5724f54 100644 --- a/app/agent/tools/impl/search_person_credits.py +++ b/app/agent/tools/impl/search_person_credits.py @@ -35,8 +35,6 @@ class SearchPersonCreditsTool(MoviePilotTool): logger.info(f"执行工具: {self.name}, 参数: person_id={person_id}, source={source}, page={page}") try: - medias = None - # 根据source选择相应的chain if source.lower() == "tmdb": tmdb_chain = TmdbChain() diff --git a/app/agent/tools/impl/search_web.py b/app/agent/tools/impl/search_web.py index b65ec345..2642b6d2 100644 --- a/app/agent/tools/impl/search_web.py +++ b/app/agent/tools/impl/search_web.py @@ -64,7 +64,8 @@ class SearchWebTool(MoviePilotTool): logger.error(f"搜索网络内容失败: {e}", exc_info=True) return error_message - async def _search_duckduckgo_api(self, query: str, max_results: int) -> list: + @staticmethod + async def _search_duckduckgo_api(query: str, max_results: int) -> list: """ 使用DuckDuckGo API进行搜索 @@ -143,7 +144,8 @@ class SearchWebTool(MoviePilotTool): logger.warning(f"DuckDuckGo API搜索失败: {e}") return [] - def _format_and_truncate_results(self, results: list, max_results: int) -> dict: + @staticmethod + def _format_and_truncate_results(results: list, max_results: int) -> dict: """ 格式化并裁剪搜索结果以避免占用过多上下文 diff --git a/app/chain/message.py b/app/chain/message.py index 4378b243..5162a75d 100644 --- a/app/chain/message.py +++ b/app/chain/message.py @@ -164,19 +164,15 @@ class MessageChain(ChainBase): ) # 处理消息 if text.startswith('CALLBACK:'): - # 处理按钮回调(适配支持回调的渠道) + # 处理按钮回调(适配支持回调的渠),优先级最高 if ChannelCapabilityManager.supports_callbacks(channel): self._handle_callback(text=text, channel=channel, source=source, userid=userid, username=username, original_message_id=original_message_id, original_chat_id=original_chat_id) else: logger.warning(f"渠道 {channel.value} 不支持回调,但收到了回调消息:{text}") - elif text.startswith('/ai') or text.startswith('/AI'): - # AI智能体处理 - self._handle_ai_message(text=text, channel=channel, source=source, - userid=userid, username=username) - elif text.startswith('/'): - # 执行命令 + elif text.startswith('/') and not text.lower().startswith('/ai'): + # 执行特定命令命令(但不是/ai) self.eventmanager.send_event( EventType.CommandExcute, { @@ -186,266 +182,226 @@ class MessageChain(ChainBase): "source": source } ) - elif text.isdigit(): - # 用户选择了具体的条目 - # 缓存 - cache_data: dict = user_cache.get(userid).copy() - # 选择项目 - if not cache_data \ - or not cache_data.get('items') \ - or len(cache_data.get('items')) < int(text): - # 发送消息 - self.post_message(Notification(channel=channel, source=source, title="输入有误!", userid=userid)) - return - try: - # 选择的序号 - _choice = int(text) + _current_page * self._page_size - 1 - # 缓存类型 - cache_type: str = cache_data.get('type') - # 缓存列表 - cache_list: list = cache_data.get('items').copy() - # 选择 + elif text.lower().startswith('/ai'): + # 用户指定AI智能体消息响应 + self._handle_ai_message(text=text, channel=channel, source=source, + userid=userid, username=username) + elif settings.AI_AGENT_ENABLE and settings.AI_AGENT_GLOBAL: + # 普通消息,全局智能体响应 + self._handle_ai_message(text=text, channel=channel, source=source, + userid=userid, username=username) + else: + # 非智能体普通消息响应 + if text.isdigit(): + # 用户选择了具体的条目 + # 缓存 + cache_data: dict = user_cache.get(userid).copy() + # 选择项目 + if not cache_data \ + or not cache_data.get('items') \ + or len(cache_data.get('items')) < int(text): + # 发送消息 + self.post_message(Notification(channel=channel, source=source, title="输入有误!", userid=userid)) + return try: - if cache_type in ["Search", "ReSearch"]: - # 当前媒体信息 - mediainfo: MediaInfo = cache_list[_choice] - _current_media = mediainfo - # 查询缺失的媒体信息 - exist_flag, no_exists = DownloadChain().get_no_exists_info(meta=_current_meta, - mediainfo=_current_media) - if exist_flag and cache_type == "Search": - # 媒体库中已存在 + # 选择的序号 + _choice = int(text) + _current_page * self._page_size - 1 + # 缓存类型 + cache_type: str = cache_data.get('type') + # 缓存列表 + cache_list: list = cache_data.get('items').copy() + # 选择 + try: + if cache_type in ["Search", "ReSearch"]: + # 当前媒体信息 + mediainfo: MediaInfo = cache_list[_choice] + _current_media = mediainfo + # 查询缺失的媒体信息 + exist_flag, no_exists = DownloadChain().get_no_exists_info(meta=_current_meta, + mediainfo=_current_media) + if exist_flag and cache_type == "Search": + # 媒体库中已存在 + self.post_message( + Notification(channel=channel, + source=source, + title=f"【{_current_media.title_year}" + f"{_current_meta.sea} 媒体库中已存在,如需重新下载请发送:搜索 名称 或 下载 名称】", + userid=userid)) + return + elif exist_flag: + # 没有缺失,但要全量重新搜索和下载 + no_exists = self.__get_noexits_info(_current_meta, _current_media) + # 发送缺失的媒体信息 + messages = [] + if no_exists and cache_type == "Search": + # 发送缺失消息 + mediakey = mediainfo.tmdb_id or mediainfo.douban_id + messages = [ + f"第 {sea} 季缺失 {StringUtils.str_series(no_exist.episodes) if no_exist.episodes else no_exist.total_episode} 集" + for sea, no_exist in no_exists.get(mediakey).items()] + elif no_exists: + # 发送总集数的消息 + mediakey = mediainfo.tmdb_id or mediainfo.douban_id + messages = [ + f"第 {sea} 季总 {no_exist.total_episode} 集" + for sea, no_exist in no_exists.get(mediakey).items()] + if messages: + self.post_message(Notification(channel=channel, + source=source, + title=f"{mediainfo.title_year}:\n" + "\n".join(messages), + userid=userid)) + # 搜索种子,过滤掉不需要的剧集,以便选择 + logger.info(f"开始搜索 {mediainfo.title_year} ...") self.post_message( Notification(channel=channel, source=source, - title=f"【{_current_media.title_year}" - f"{_current_meta.sea} 媒体库中已存在,如需重新下载请发送:搜索 名称 或 下载 名称】", + title=f"开始搜索 {mediainfo.type.value} {mediainfo.title_year} ...", userid=userid)) - return - elif exist_flag: - # 没有缺失,但要全量重新搜索和下载 - no_exists = self.__get_noexits_info(_current_meta, _current_media) - # 发送缺失的媒体信息 - messages = [] - if no_exists and cache_type == "Search": - # 发送缺失消息 - mediakey = mediainfo.tmdb_id or mediainfo.douban_id - messages = [ - f"第 {sea} 季缺失 {StringUtils.str_series(no_exist.episodes) if no_exist.episodes else no_exist.total_episode} 集" - for sea, no_exist in no_exists.get(mediakey).items()] - elif no_exists: - # 发送总集数的消息 - mediakey = mediainfo.tmdb_id or mediainfo.douban_id - messages = [ - f"第 {sea} 季总 {no_exist.total_episode} 集" - for sea, no_exist in no_exists.get(mediakey).items()] - if messages: - self.post_message(Notification(channel=channel, - source=source, - title=f"{mediainfo.title_year}:\n" + "\n".join(messages), - userid=userid)) - # 搜索种子,过滤掉不需要的剧集,以便选择 - logger.info(f"开始搜索 {mediainfo.title_year} ...") - self.post_message( - Notification(channel=channel, - source=source, - title=f"开始搜索 {mediainfo.type.value} {mediainfo.title_year} ...", - userid=userid)) - # 开始搜索 - contexts = SearchChain().process(mediainfo=mediainfo, - no_exists=no_exists) - if not contexts: - # 没有数据 - self.post_message(Notification( - channel=channel, - source=source, - title=f"{mediainfo.title}" - f"{_current_meta.sea} 未搜索到需要的资源!", - userid=userid)) - return - # 搜索结果排序 - contexts = TorrentHelper().sort_torrents(contexts) - try: - # 判断是否设置自动下载 - auto_download_user = settings.AUTO_DOWNLOAD_USER - # 匹配到自动下载用户 - if auto_download_user \ - and (auto_download_user == "all" - or any(userid == user for user in auto_download_user.split(","))): - logger.info(f"用户 {userid} 在自动下载用户中,开始自动择优下载 ...") - # 自动选择下载 - self.__auto_download(channel=channel, - source=source, - cache_list=contexts, - userid=userid, - username=username, - no_exists=no_exists) - else: - # 更新缓存 - user_cache[userid] = { - "type": "Torrent", - "items": contexts - } - _current_page = 0 - # 保存缓存 - self.save_cache(user_cache, self._cache_file) - # 删除原消息 - if (original_message_id and original_chat_id and - ChannelCapabilityManager.supports_deletion(channel)): - self.delete_message( - channel=channel, - source=source, - message_id=original_message_id, - chat_id=original_chat_id - ) - # 发送种子数据 - logger.info(f"搜索到 {len(contexts)} 条数据,开始发送选择消息 ...") - self.__post_torrents_message(channel=channel, - source=source, - title=mediainfo.title, - items=contexts[:self._page_size], - userid=userid, - total=len(contexts)) - finally: - contexts.clear() - del contexts - elif cache_type in ["Subscribe", "ReSubscribe"]: - # 订阅或洗版媒体 - mediainfo: MediaInfo = cache_list[_choice] - # 洗版标识 - best_version = False - # 查询缺失的媒体信息 - if cache_type == "Subscribe": - exist_flag, _ = DownloadChain().get_no_exists_info(meta=_current_meta, - mediainfo=mediainfo) - if exist_flag: + # 开始搜索 + contexts = SearchChain().process(mediainfo=mediainfo, + no_exists=no_exists) + if not contexts: + # 没有数据 self.post_message(Notification( channel=channel, source=source, - title=f"【{mediainfo.title_year}" - f"{_current_meta.sea} 媒体库中已存在,如需洗版请发送:洗版 XXX】", + title=f"{mediainfo.title}" + f"{_current_meta.sea} 未搜索到需要的资源!", userid=userid)) return - else: - best_version = True - # 转换用户名 - mp_name = UserOper().get_name( - **{f"{channel.name.lower()}_userid": userid}) if channel else None - # 添加订阅,状态为N - SubscribeChain().add(title=mediainfo.title, - year=mediainfo.year, - mtype=mediainfo.type, - tmdbid=mediainfo.tmdb_id, - season=_current_meta.begin_season, - channel=channel, - source=source, - userid=userid, - username=mp_name or username, - best_version=best_version) - elif cache_type == "Torrent": - if int(text) == 0: - # 自动选择下载,强制下载模式 - self.__auto_download(channel=channel, + # 搜索结果排序 + contexts = TorrentHelper().sort_torrents(contexts) + try: + # 判断是否设置自动下载 + auto_download_user = settings.AUTO_DOWNLOAD_USER + # 匹配到自动下载用户 + if auto_download_user \ + and (auto_download_user == "all" + or any(userid == user for user in auto_download_user.split(","))): + logger.info(f"用户 {userid} 在自动下载用户中,开始自动择优下载 ...") + # 自动选择下载 + self.__auto_download(channel=channel, + source=source, + cache_list=contexts, + userid=userid, + username=username, + no_exists=no_exists) + else: + # 更新缓存 + user_cache[userid] = { + "type": "Torrent", + "items": contexts + } + _current_page = 0 + # 保存缓存 + self.save_cache(user_cache, self._cache_file) + # 删除原消息 + if (original_message_id and original_chat_id and + ChannelCapabilityManager.supports_deletion(channel)): + self.delete_message( + channel=channel, + source=source, + message_id=original_message_id, + chat_id=original_chat_id + ) + # 发送种子数据 + logger.info(f"搜索到 {len(contexts)} 条数据,开始发送选择消息 ...") + self.__post_torrents_message(channel=channel, + source=source, + title=mediainfo.title, + items=contexts[:self._page_size], + userid=userid, + total=len(contexts)) + finally: + contexts.clear() + del contexts + elif cache_type in ["Subscribe", "ReSubscribe"]: + # 订阅或洗版媒体 + mediainfo: MediaInfo = cache_list[_choice] + # 洗版标识 + best_version = False + # 查询缺失的媒体信息 + if cache_type == "Subscribe": + exist_flag, _ = DownloadChain().get_no_exists_info(meta=_current_meta, + mediainfo=mediainfo) + if exist_flag: + self.post_message(Notification( + channel=channel, + source=source, + title=f"【{mediainfo.title_year}" + f"{_current_meta.sea} 媒体库中已存在,如需洗版请发送:洗版 XXX】", + userid=userid)) + return + else: + best_version = True + # 转换用户名 + mp_name = UserOper().get_name( + **{f"{channel.name.lower()}_userid": userid}) if channel else None + # 添加订阅,状态为N + SubscribeChain().add(title=mediainfo.title, + year=mediainfo.year, + mtype=mediainfo.type, + tmdbid=mediainfo.tmdb_id, + season=_current_meta.begin_season, + channel=channel, source=source, - cache_list=cache_list, userid=userid, - username=username) - else: - # 下载种子 - context: Context = cache_list[_choice] - # 下载 - DownloadChain().download_single(context, channel=channel, source=source, - userid=userid, username=username) + username=mp_name or username, + best_version=best_version) + elif cache_type == "Torrent": + if int(text) == 0: + # 自动选择下载,强制下载模式 + self.__auto_download(channel=channel, + source=source, + cache_list=cache_list, + userid=userid, + username=username) + else: + # 下载种子 + context: Context = cache_list[_choice] + # 下载 + DownloadChain().download_single(context, channel=channel, source=source, + userid=userid, username=username) + finally: + cache_list.clear() + del cache_list finally: - cache_list.clear() - del cache_list - finally: - cache_data.clear() - del cache_data - elif text.lower() == "p": - # 上一页 - cache_data: dict = user_cache.get(userid).copy() - if not cache_data: - # 没有缓存 - self.post_message(Notification( - channel=channel, source=source, title="输入有误!", userid=userid)) - return - try: - if _current_page == 0: - # 第一页 + cache_data.clear() + del cache_data + elif text.lower() == "p": + # 上一页 + cache_data: dict = user_cache.get(userid).copy() + if not cache_data: + # 没有缓存 self.post_message(Notification( - channel=channel, source=source, title="已经是第一页了!", userid=userid)) + channel=channel, source=source, title="输入有误!", userid=userid)) return - # 减一页 - _current_page -= 1 - cache_type: str = cache_data.get('type') - # 产生副本,避免修改原值 - cache_list: list = cache_data.get('items').copy() try: if _current_page == 0: - start = 0 - end = self._page_size - else: - start = _current_page * self._page_size - end = start + self._page_size - if cache_type == "Torrent": - # 发送种子数据 - self.__post_torrents_message(channel=channel, - source=source, - title=_current_media.title, - items=cache_list[start:end], - userid=userid, - total=len(cache_list), - original_message_id=original_message_id, - original_chat_id=original_chat_id) - else: - # 发送媒体数据 - self.__post_medias_message(channel=channel, - source=source, - title=_current_meta.name, - items=cache_list[start:end], - userid=userid, - total=len(cache_list), - original_message_id=original_message_id, - original_chat_id=original_chat_id) - finally: - cache_list.clear() - del cache_list - finally: - cache_data.clear() - del cache_data - elif text.lower() == "n": - # 下一页 - cache_data: dict = user_cache.get(userid).copy() - if not cache_data: - # 没有缓存 - self.post_message(Notification( - channel=channel, source=source, title="输入有误!", userid=userid)) - return - try: - cache_type: str = cache_data.get('type') - # 产生副本,避免修改原值 - cache_list: list = cache_data.get('items').copy() - total = len(cache_list) - # 加一页 - cache_list = cache_list[(_current_page + 1) * self._page_size:(_current_page + 2) * self._page_size] - if not cache_list: - # 没有数据 - self.post_message(Notification( - channel=channel, source=source, title="已经是最后一页了!", userid=userid)) - return - else: + # 第一页 + self.post_message(Notification( + channel=channel, source=source, title="已经是第一页了!", userid=userid)) + return + # 减一页 + _current_page -= 1 + cache_type: str = cache_data.get('type') + # 产生副本,避免修改原值 + cache_list: list = cache_data.get('items').copy() try: - # 加一页 - _current_page += 1 + if _current_page == 0: + start = 0 + end = self._page_size + else: + start = _current_page * self._page_size + end = start + self._page_size if cache_type == "Torrent": # 发送种子数据 self.__post_torrents_message(channel=channel, source=source, title=_current_media.title, - items=cache_list, + items=cache_list[start:end], userid=userid, - total=total, + total=len(cache_list), original_message_id=original_message_id, original_chat_id=original_chat_id) else: @@ -453,94 +409,144 @@ class MessageChain(ChainBase): self.__post_medias_message(channel=channel, source=source, title=_current_meta.name, - items=cache_list, + items=cache_list[start:end], userid=userid, - total=total, + total=len(cache_list), original_message_id=original_message_id, original_chat_id=original_chat_id) finally: cache_list.clear() del cache_list - finally: - cache_data.clear() - del cache_data - else: - # 搜索或订阅 - if text.startswith("订阅"): - # 订阅 - content = re.sub(r"订阅[::\s]*", "", text) - action = "Subscribe" - elif text.startswith("洗版"): - # 洗版 - content = re.sub(r"洗版[::\s]*", "", text) - action = "ReSubscribe" - elif text.startswith("搜索") or text.startswith("下载"): - # 重新搜索/下载 - content = re.sub(r"(搜索|下载)[::\s]*", "", text) - action = "ReSearch" - elif text.startswith("#") \ - or re.search(r"^请[问帮你]", text) \ - or re.search(r"[??]$", text) \ - or StringUtils.count_words(text) > 10 \ - or text.find("继续") != -1: - # 聊天 - content = text - action = "Chat" - elif StringUtils.is_link(text): - # 链接 - content = text - action = "Link" - else: - # 搜索 - content = text - action = "Search" - - if action in ["Search", "ReSearch", "Subscribe", "ReSubscribe"]: - # 搜索 - meta, medias = MediaChain().search(content) - # 识别 - if not meta.name: - self.post_message(Notification( - channel=channel, source=source, title="无法识别输入内容!", userid=userid)) - return - # 开始搜索 - if not medias: - self.post_message(Notification( - channel=channel, source=source, title=f"{meta.name} 没有找到对应的媒体信息!", - userid=userid)) - return - logger.info(f"搜索到 {len(medias)} 条相关媒体信息") - try: - # 记录当前状态 - _current_meta = meta - # 保存缓存 - user_cache[userid] = { - 'type': action, - 'items': medias - } - self.save_cache(user_cache, self._cache_file) - _current_page = 0 - _current_media = None - # 发送媒体列表 - self.__post_medias_message(channel=channel, - source=source, - title=meta.name, - items=medias[:self._page_size], - userid=userid, total=len(medias)) finally: - medias.clear() - del medias + cache_data.clear() + del cache_data + elif text.lower() == "n": + # 下一页 + cache_data: dict = user_cache.get(userid).copy() + if not cache_data: + # 没有缓存 + self.post_message(Notification( + channel=channel, source=source, title="输入有误!", userid=userid)) + return + try: + cache_type: str = cache_data.get('type') + # 产生副本,避免修改原值 + cache_list: list = cache_data.get('items').copy() + total = len(cache_list) + # 加一页 + cache_list = cache_list[(_current_page + 1) * self._page_size:(_current_page + 2) * self._page_size] + if not cache_list: + # 没有数据 + self.post_message(Notification( + channel=channel, source=source, title="已经是最后一页了!", userid=userid)) + return + else: + try: + # 加一页 + _current_page += 1 + if cache_type == "Torrent": + # 发送种子数据 + self.__post_torrents_message(channel=channel, + source=source, + title=_current_media.title, + items=cache_list, + userid=userid, + total=total, + original_message_id=original_message_id, + original_chat_id=original_chat_id) + else: + # 发送媒体数据 + self.__post_medias_message(channel=channel, + source=source, + title=_current_meta.name, + items=cache_list, + userid=userid, + total=total, + original_message_id=original_message_id, + original_chat_id=original_chat_id) + finally: + cache_list.clear() + del cache_list + finally: + cache_data.clear() + del cache_data else: - # 广播事件 - self.eventmanager.send_event( - EventType.UserMessage, - { - "text": content, - "userid": userid, - "channel": channel, - "source": source - } - ) + # 搜索或订阅 + if text.startswith("订阅"): + # 订阅 + content = re.sub(r"订阅[::\s]*", "", text) + action = "Subscribe" + elif text.startswith("洗版"): + # 洗版 + content = re.sub(r"洗版[::\s]*", "", text) + action = "ReSubscribe" + elif text.startswith("搜索") or text.startswith("下载"): + # 重新搜索/下载 + content = re.sub(r"(搜索|下载)[::\s]*", "", text) + action = "ReSearch" + elif text.startswith("#") \ + or re.search(r"^请[问帮你]", text) \ + or re.search(r"[??]$", text) \ + or StringUtils.count_words(text) > 10 \ + or text.find("继续") != -1: + # 聊天 + content = text + action = "Chat" + elif StringUtils.is_link(text): + # 链接 + content = text + action = "Link" + else: + # 搜索 + content = text + action = "Search" + + if action in ["Search", "ReSearch", "Subscribe", "ReSubscribe"]: + # 搜索 + meta, medias = MediaChain().search(content) + # 识别 + if not meta.name: + self.post_message(Notification( + channel=channel, source=source, title="无法识别输入内容!", userid=userid)) + return + # 开始搜索 + if not medias: + self.post_message(Notification( + channel=channel, source=source, title=f"{meta.name} 没有找到对应的媒体信息!", + userid=userid)) + return + logger.info(f"搜索到 {len(medias)} 条相关媒体信息") + try: + # 记录当前状态 + _current_meta = meta + # 保存缓存 + user_cache[userid] = { + 'type': action, + 'items': medias + } + self.save_cache(user_cache, self._cache_file) + _current_page = 0 + _current_media = None + # 发送媒体列表 + self.__post_medias_message(channel=channel, + source=source, + title=meta.name, + items=medias[:self._page_size], + userid=userid, total=len(medias)) + finally: + medias.clear() + del medias + else: + # 广播事件 + self.eventmanager.send_event( + EventType.UserMessage, + { + "text": content, + "userid": userid, + "channel": channel, + "source": source + } + ) finally: user_cache.clear() del user_cache diff --git a/app/core/config.py b/app/core/config.py index 52a49318..2f3ad3bc 100644 --- a/app/core/config.py +++ b/app/core/config.py @@ -411,6 +411,8 @@ class ConfigModel(BaseModel): # ==================== AI智能体配置 ==================== # AI智能体开关 AI_AGENT_ENABLE: bool = False + # 合局AI智能体 + AI_AGENT_GLOBAL: bool = False # LLM提供商 (openai/google/deepseek) LLM_PROVIDER: str = "deepseek" # LLM模型名称 diff --git a/version.py b/version.py index 36f5975d..65f64d57 100644 --- a/version.py +++ b/version.py @@ -1,2 +1,2 @@ -APP_VERSION = 'v2.8.5' -FRONTEND_VERSION = 'v2.8.5' +APP_VERSION = 'v2.8.6' +FRONTEND_VERSION = 'v2.8.6'