diff --git a/docs/newsnow_plugin_config.md b/docs/newsnow_plugin_config.md index 88744423..8be887c2 100644 --- a/docs/newsnow_plugin_config.md +++ b/docs/newsnow_plugin_config.md @@ -13,7 +13,7 @@ 3. 选择要配置的智能体 4. 点击"编辑功能"按钮 5. 在右侧参数配置区域找到"newsnow新闻聚合"插件 -6. 在"新闻源配置"字段中输入JSON格式的新闻源配置 +6. 在"新闻源配置"字段中输入分号分隔的中文名称 ### 2. 配置文件方式 @@ -23,62 +23,83 @@ plugins: get_news_from_newsnow: url: "https://newsnow.busiyi.world/api/s?id=" - news_sources: - thepaper: "澎湃新闻" - baidu: "百度热搜" - cls-depth: "财联社" - # 可以添加更多新闻源 - weibo: "微博头条" - douyin: "抖音热搜" - solidot: "奇客Solidot" + news_sources: "澎湃新闻;百度热搜;财联社;微博;抖音" ``` ## 新闻源配置格式 -新闻源配置使用JSON格式,格式为: +新闻源配置使用分号分隔的中文名称,格式为: -```json -{ - "source_id": "显示名称", - "source_id2": "显示名称2" -} +``` +中文名称1;中文名称2;中文名称3 ``` ### 配置示例 -```json -{ - "thepaper": "澎湃新闻", - "baidu": "百度热搜", - "cls-depth": "财联社", - "weibo": "微博头条", - "douyin": "抖音热搜", - "solidot": "奇客Solidot" -} ``` +澎湃新闻;百度热搜;财联社;微博;抖音;知乎;36氪 +``` + +## 支持的新闻源 + +插件支持以下新闻源的中文名称: + +- 澎湃新闻 +- 百度热搜 +- 财联社 +- 微博 +- 抖音 +- 知乎 +- 36氪 +- 华尔街见闻 +- IT之家 +- 今日头条 +- 虎扑 +- 哔哩哔哩 +- 快手 +- 雪球 +- 格隆汇 +- 法布财经 +- 金十数据 +- 牛客 +- 少数派 +- 稀土掘金 +- 凤凰网 +- 虫部落 +- 联合早报 +- 酷安 +- 远景论坛 +- 参考消息 +- 卫星通讯社 +- 百度贴吧 +- 靠谱新闻 +- 以及更多... ## 默认配置 如果未配置新闻源,插件将使用以下默认配置: -```json -{ - "thepaper": "澎湃新闻", - "baidu": "百度热搜", - "cls-depth": "财联社" -} +``` +澎湃新闻;百度热搜;财联社 ``` ## 使用说明 -1. **配置新闻源**:在Web界面或配置文件中设置新闻源 +1. **配置新闻源**:在Web界面或配置文件中设置新闻源的中文名称,用分号分隔 2. **调用插件**:用户可以说"播报新闻"或"获取新闻" 3. **指定新闻源**:用户可以说"播报澎湃新闻"或"获取百度热搜" 4. **获取详情**:用户可以说"详细介绍这条新闻" +## 工作原理 + +1. 插件接受中文名称作为参数(如"澎湃新闻") +2. 根据配置的新闻源列表,将中文名称转换为对应的英文ID(如"thepaper") +3. 使用英文ID调用API获取新闻数据 +4. 返回新闻内容给用户 + ## 注意事项 -1. 新闻源的 `source_id` 必须与API接口支持的ID一致 +1. 配置的中文名称必须与 CHANNEL_MAP 中定义的名称完全一致 2. 配置更改后需要重启服务或重新加载配置 3. 如果配置的新闻源无效,插件会自动使用默认新闻源 -4. JSON格式必须正确,否则会使用默认配置 \ No newline at end of file +4. 多个新闻源之间使用英文分号(;)分隔,不要使用中文分号(;) \ No newline at end of file diff --git a/main/manager-api/src/main/resources/db/changelog/202506251619.sql b/main/manager-api/src/main/resources/db/changelog/202506251620.sql similarity index 61% rename from main/manager-api/src/main/resources/db/changelog/202506251619.sql rename to main/manager-api/src/main/resources/db/changelog/202506251620.sql index a458daea..9af9acd7 100644 --- a/main/manager-api/src/main/resources/db/changelog/202506251619.sql +++ b/main/manager-api/src/main/resources/db/changelog/202506251620.sql @@ -1,6 +1,3 @@ --- 更新 get_news_from_newsnow 插件配置,添加新闻源配置字段 --- 执行时间:2025-06-25 - -- 更新现有的 get_news_from_newsnow 插件配置 UPDATE ai_model_provider SET fields = JSON_ARRAY( @@ -12,10 +9,10 @@ SET fields = JSON_ARRAY( ), JSON_OBJECT( 'key', 'news_sources', - 'type', 'json', + 'type', 'string', 'label', '新闻源配置', - 'default', '{"thepaper":"澎湃新闻","baidu":"百度热搜","cls-depth":"财联社"}' + 'default', '澎湃新闻;百度热搜;财联社' ) ) WHERE provider_code = 'get_news_from_newsnow' -AND model_type = 'Plugin'; \ No newline at end of file +AND model_type = 'Plugin'; \ No newline at end of file diff --git a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml index 0cb07ea2..32ba9f30 100755 --- a/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/main/manager-api/src/main/resources/db/changelog/db.changelog-master.yaml @@ -227,12 +227,12 @@ databaseChangeLog: encoding: utf8 path: classpath:db/changelog/202506191643.sql - changeSet: - id: 202506251619 + id: 202506251620 author: Tink changes: - sqlFile: encoding: utf8 - path: classpath:db/changelog/202506251619.sql + path: classpath:db/changelog/202506251620.sql - changeSet: id: 202506261637 author: hrz diff --git a/main/xiaozhi-server/config.yaml b/main/xiaozhi-server/config.yaml index 27dc3a39..5a43c995 100644 --- a/main/xiaozhi-server/config.yaml +++ b/main/xiaozhi-server/config.yaml @@ -123,10 +123,7 @@ plugins: finance_rss_url: "https://www.chinanews.com.cn/rss/finance.xml" get_news_from_newsnow: url: "https://newsnow.busiyi.world/api/s?id=" - news_sources: - thepaper: "澎湃新闻" - baidu: "百度热搜" - cls-depth: "财联社" + news_sources: "澎湃新闻;百度热搜;财联社" home_assistant: devices: - 客厅,玩具灯,switch.cuco_cn_460494544_cp1_on_p_2_1 @@ -164,7 +161,7 @@ end_prompt: enable: true # 是否开启结束语 # 结束语 prompt: | - 请你以“时间过得真快”未来头,用富有感情、依依不舍的话来结束这场对话吧! + 请你以"时间过得真快"未来头,用富有感情、依依不舍的话来结束这场对话吧! # 具体处理时选择的模块(The module selected for specific processing) selected_module: @@ -201,7 +198,7 @@ Intent: # 如果你的不想使用selected_module.LLM意图识别,这里最好使用独立的LLM作为意图识别,例如使用免费的ChatGLMLLM llm: ChatGLMLLM # plugins_func/functions下的模块,可以通过配置,选择加载哪个模块,加载后对话支持相应的function调用 - # 系统默认已经记载“handle_exit_intent(退出识别)”、“play_music(音乐播放)”插件,请勿重复加载 + # 系统默认已经记载"handle_exit_intent(退出识别)"、"play_music(音乐播放)"插件,请勿重复加载 # 下面是加载查天气、角色切换、加载查新闻的插件示例 functions: - get_weather @@ -211,7 +208,7 @@ Intent: # 不需要动type type: function_call # plugins_func/functions下的模块,可以通过配置,选择加载哪个模块,加载后对话支持相应的function调用 - # 系统默认已经记载“handle_exit_intent(退出识别)”、“play_music(音乐播放)”插件,请勿重复加载 + # 系统默认已经记载"handle_exit_intent(退出识别)"、"play_music(音乐播放)"插件,请勿重复加载 # 下面是加载查天气、角色切换、加载查新闻的插件示例 functions: - change_role diff --git a/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py b/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py index 6fcb7ba6..54641106 100644 --- a/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py +++ b/main/xiaozhi-server/plugins_func/functions/get_news_from_newsnow.py @@ -8,61 +8,98 @@ from markitdown import MarkItDown TAG = __name__ logger = setup_logging() -# 默认新闻来源字典,当配置中没有指定时使用 -DEFAULT_NEWS_SOURCES = { - "thepaper": "澎湃新闻", - "baidu": "百度热搜", - "cls-depth": "财联社", +CHANNEL_MAP = { + "V2EX": "v2ex-share", + "知乎": "zhihu", + "微博": "weibo", + "联合早报": "zaobao", + "酷安": "coolapk", + "MKTNews": "mktnews-flash", + "华尔街见闻": "wallstreetcn-quick", + "36氪": "36kr-quick", + "抖音": "douyin", + "虎扑": "hupu", + "百度贴吧": "tieba", + "今日头条": "toutiao", + "IT之家": "ithome", + "澎湃新闻": "thepaper", + "卫星通讯社": "sputniknewscn", + "参考消息": "cankaoxiaoxi", + "远景论坛": "pcbeta-windows11", + "财联社": "cls-depth", + "雪球": "xueqiu-hotstock", + "格隆汇": "gelonghui", + "法布财经": "fastbull-express", + "Solidot": "solidot", + "Hacker News": "hackernews", + "Product Hunt": "producthunt", + "Github": "github-trending-today", + "哔哩哔哩": "bilibili-hot-search", + "快手": "kuaishou", + "靠谱新闻": "kaopu", + "金十数据": "jin10", + "百度热搜": "baidu", + "牛客": "nowcoder", + "少数派": "sspai", + "稀土掘金": "juejin", + "凤凰网": "ifeng", + "虫部落": "chongbuluo-latest", } +# 默认新闻来源字典,当配置中没有指定时使用 +DEFAULT_NEWS_SOURCES = "澎湃新闻;百度热搜;财联社" + + def get_news_sources_from_config(conn): - """从配置中获取新闻源字典""" + """从配置中获取新闻源字符串""" try: # 尝试从插件配置中获取新闻源 - if (conn.config.get("plugins") and - conn.config["plugins"].get("get_news_from_newsnow") and - conn.config["plugins"]["get_news_from_newsnow"].get("news_sources")): - - # 如果配置中是字符串,尝试解析JSON - news_sources_config = conn.config["plugins"]["get_news_from_newsnow"]["news_sources"] - if isinstance(news_sources_config, str): - try: - return json.loads(news_sources_config) - except json.JSONDecodeError: - logger.bind(tag=TAG).warning("新闻源配置JSON格式错误,使用默认配置") - return DEFAULT_NEWS_SOURCES - elif isinstance(news_sources_config, dict): + if ( + conn.config.get("plugins") + and conn.config["plugins"].get("get_news_from_newsnow") + and conn.config["plugins"]["get_news_from_newsnow"].get("news_sources") + ): + # 获取配置的新闻源字符串 + news_sources_config = conn.config["plugins"]["get_news_from_newsnow"][ + "news_sources" + ] + + if isinstance(news_sources_config, str) and news_sources_config.strip(): + logger.bind(tag=TAG).debug(f"使用配置的新闻源: {news_sources_config}") return news_sources_config else: - logger.bind(tag=TAG).warning("新闻源配置格式错误,使用默认配置") - return DEFAULT_NEWS_SOURCES + logger.bind(tag=TAG).warning("新闻源配置为空或格式错误,使用默认配置") else: logger.bind(tag=TAG).debug("未找到新闻源配置,使用默认配置") - return DEFAULT_NEWS_SOURCES + + return DEFAULT_NEWS_SOURCES + except Exception as e: logger.bind(tag=TAG).error(f"获取新闻源配置失败: {e},使用默认配置") return DEFAULT_NEWS_SOURCES -# 静态函数描述,使用默认新闻源生成描述 +# 从CHANNEL_MAP获取所有可用的新闻源名称 +available_sources = list(CHANNEL_MAP.keys()) +example_sources_str = "、".join(available_sources) + GET_NEWS_FROM_NEWSNOW_FUNCTION_DESC = { "type": "function", "function": { "name": "get_news_from_newsnow", "description": ( "获取最新新闻,随机选择一条新闻进行播报。" - "用户可以选择不同的新闻源,如澎湃新闻(thepaper)、百度热搜(baidu)、财联社(cls-depth)等。" - "如果没有指定,默认从澎湃新闻获取。" + f"用户可以选择不同的新闻源,标准的名称是:{example_sources_str}" + "例如用户要求百度新闻,其实就是百度热搜。如果没有指定,默认从澎湃新闻获取。" "用户可以要求获取详细内容,此时会获取新闻的详细内容。" - "注意:实际可用的新闻源取决于系统配置。" ), "parameters": { "type": "object", "properties": { "source": { "type": "string", - "description": "新闻源,例如thepaper、baidu、cls-depth等。可选参数,如果不提供则使用默认新闻源", + "description": f"新闻源的标准中文名称,例如{example_sources_str}等。可选参数,如果不提供则使用默认新闻源", }, "detail": { "type": "boolean", @@ -134,13 +171,13 @@ def fetch_news_detail(url): ToolType.SYSTEM_CTL, ) def get_news_from_newsnow( - conn, source: str = "thepaper", detail: bool = False, lang: str = "zh_CN" + conn, source: str = "澎湃新闻", detail: bool = False, lang: str = "zh_CN" ): """获取新闻并随机选择一条进行播报,或获取上一条新闻的详细内容""" try: # 获取当前配置的新闻源 news_sources = get_news_sources_from_config(conn) - + # 如果detail为True,获取上一条新闻的详细内容 detail = str(detail).lower() == "true" if detail: @@ -158,7 +195,7 @@ def get_news_from_newsnow( url = conn.last_newsnow_link.get("url") title = conn.last_newsnow_link.get("title", "未知标题") source_id = conn.last_newsnow_link.get("source_id", "thepaper") - source_name = news_sources.get(source_id, "未知来源") + source_name = CHANNEL_MAP.get(source_id, "未知来源") if not url or url == "#": return ActionResponse( @@ -192,21 +229,32 @@ def get_news_from_newsnow( return ActionResponse(Action.REQLLM, detail_report, None) # 否则,获取新闻列表并随机选择一条 - # 验证新闻源是否有效,如果无效则使用默认源 - if source not in news_sources: - logger.bind(tag=TAG).warning(f"无效的新闻源: {source},使用默认源thepaper") - source = "thepaper" + # 将中文名称转换为英文ID + english_source_id = None - source_name = news_sources.get(source, "澎湃新闻") - logger.bind(tag=TAG).info(f"获取新闻: 新闻源={source}({source_name})") + # 检查输入的中文名称是否在配置的新闻源中 + news_sources_list = [ + name.strip() for name in news_sources.split(";") if name.strip() + ] + if source in news_sources_list: + # 如果输入的中文名称在配置的新闻源中,在 CHANNEL_MAP 中查找对应的英文ID + english_source_id = CHANNEL_MAP.get(source) + + # 如果找不到对应的英文ID,使用默认源 + if not english_source_id: + logger.bind(tag=TAG).warning(f"无效的新闻源: {source},使用默认源澎湃新闻") + english_source_id = "thepaper" + source = "澎湃新闻" + + logger.bind(tag=TAG).info(f"获取新闻: 新闻源={source}({english_source_id})") # 获取新闻列表 - news_items = fetch_news_from_api(conn, source) + news_items = fetch_news_from_api(conn, english_source_id) if not news_items: return ActionResponse( Action.REQLLM, - f"抱歉,未能从{source_name}获取到新闻信息,请稍后再试或尝试其他新闻源。", + f"抱歉,未能从{source}获取到新闻信息,请稍后再试或尝试其他新闻源。", None, ) @@ -219,14 +267,14 @@ def get_news_from_newsnow( conn.last_newsnow_link = { "url": selected_news.get("url", "#"), "title": selected_news.get("title", "未知标题"), - "source_id": source, + "source_id": english_source_id, } # 构建新闻报告 news_report = ( f"根据下列数据,用{lang}回应用户的新闻查询请求:\n\n" f"新闻标题: {selected_news['title']}\n" - # f"新闻来源: {source_name}\n" + # f"新闻来源: {source}\n" f"(请以自然、流畅的方式向用户播报这条新闻标题," f"提示用户可以要求获取详细内容,此时会获取新闻的详细内容。)" )