当前位置: 首页 > article >正文

DeepSearch:WebThinker开启AI搜索研究新纪元!

1,项目简介

WebThinker 是一个深度研究智能体,使 LRMs 能够在推理过程中自主搜索网络、导航网页,并撰写研究报告。这种技术的目标是革命性的:让用户通过简单的查询就能在互联网的海量信息中进行深度搜索、挖掘和整合,从而为知识密集型领域(如金融、科学、工程)的研究人员大幅降低信息收集的时间和成本。

项目地址:https://github.com/RUC-NLPIR/WebThinker

评价:很垃圾,需要接入微软宙斯的东西,Bing搜索。这些都需要替换成国产的,而且质量一般,不兼容图片等等等,远远不如字节的 DeerFlow 强大。

现有的开源深度搜索智能体通常采用检索增强生成(Retrieval-Augmented Generation, RAG)技术,依循预定义的工作流程,这限制了 LRM 探索更深层次网页信息的能力,也阻碍了 LRM 与搜索引擎之间的紧密交互。

  • 传统 RAG:仅进行浅层搜索,缺乏思考深度和连贯性
  • 进阶 RAG:使用预定义工作流,包括查询拆解、多轮 RAG 等,但仍缺乏灵活性
  • WebThinker:在连续深思考过程中自主调用工具,实现端到端任务执行

WebThinker 使 LRM 能够在单次生成中自主执行操作,无需遵循预设的工作流程,从而实现真正的端到端任务执行。

2,替换原LLM

【替换Bing的检索】run_web_thinker.py & run_web_thinker_report.py

async def generate_response(client: AsyncOpenAI,prompt: str,semaphore: asyncio.Semaphore,generate_mode: str = "chat",temperature: float = 0.0,top_p: float = 1.0,max_tokens: int = 32768,repetition_penalty: float = 1.0,top_k: int = 1,min_p: float = 0.0,model_name: str = "QwQ-32B",stop: List[str] = [END_SEARCH_QUERY],retry_limit: int = 3,bad_words: List[str] = [f"{END_SEARCH_RESULT}\n\n{tokenizer.eos_token}"],
) -> Tuple[str, str]:"""Generate a single response with retry logic"""for attempt in range(retry_limit):try:async with semaphore:if generate_mode == "chat":messages = [{"role": "user", "content": prompt}]if 'qwq' in model_name.lower() or 'deepseek' in model_name.lower() or 'r1' in model_name.lower():formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)else:formatted_prompt = aux_tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)if ('deepseek' in model_name.lower() or 'r1' in model_name.lower()) and "<think>\n" not in formatted_prompt:formatted_prompt = formatted_prompt + "<think>\n"else:formatted_prompt = promptresponse = await client.completions.create(model=model_name,prompt=formatted_prompt,temperature=temperature,top_p=top_p,max_tokens=max_tokens,stop=stop,extra_body={'top_k': top_k,'include_stop_str_in_output': True,'repetition_penalty': repetition_penalty,# 'bad_words': bad_words,# 'min_p': min_p},timeout=3600,)return formatted_prompt, response.choices[0].textexcept Exception as e:print(f"Generate Response Error occurred: {e}, Starting retry attempt {attempt + 1}")# print(prompt)if "maximum context length" in str(e).lower():# If length exceeds limit, reduce max_tokens by halfmax_tokens = max_tokens // 2print(f"Reducing max_tokens to {max_tokens}")if attempt == retry_limit - 1:print(f"Failed after {retry_limit} attempts: {e}")return "", ""await asyncio.sleep(1 * (attempt + 1))return "", ""

替换为:

async def generate_response(client: AsyncOpenAI,prompt: str,semaphore: asyncio.Semaphore,generate_mode: str = "chat",temperature: float = 0.0,top_p: float = 1.0,max_tokens: int = 32768,repetition_penalty: float = 1.0,top_k: int = 1,min_p: float = 0.0,model_name: str = "QwQ-32B",stop: List[str] = [END_SEARCH_QUERY],retry_limit: int = 3,bad_words: List[str] = [f"{END_SEARCH_RESULT}\n\n{tokenizer.eos_token}"],
) -> Tuple[str, str]:"""Generate a single response with retry logic"""for attempt in range(retry_limit):try:async with semaphore:if generate_mode == "chat":messages = [{"role": "user", "content": prompt}]if 'qwq' in model_name.lower() or 'deepseek' in model_name.lower() or 'r1' in model_name.lower():formatted_prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)else:formatted_prompt = aux_tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)if ('deepseek' in model_name.lower() or 'r1' in model_name.lower()) and "<think>\n" not in formatted_prompt:formatted_prompt = formatted_prompt + "<think>\n"else:formatted_prompt = promptclient = OpenAI(api_key="sk-*****",base_url="https://api.deepseek.com/beta")response = client.chat.completions.create(model="deepseek-chat",temperature=temperature,messages=[{"role": "system", "content": formatted_prompt},],stream=False)return formatted_prompt, response.choices[0].message.contentexcept Exception as e:print(f"Generate Response Error occurred: {e}, Starting retry attempt {attempt + 1}")# print(prompt)if "maximum context length" in str(e).lower():# If length exceeds limit, reduce max_tokens by halfmax_tokens = max_tokens // 2print(f"Reducing max_tokens to {max_tokens}")if attempt == retry_limit - 1:print(f"Failed after {retry_limit} attempts: {e}")return "", ""await asyncio.sleep(1 * (attempt + 1))return "", ""

def extract_relevant_info(search_results):"""Extract relevant information from Bing search results.Args:search_results (dict): JSON response from the Bing Web Search API.Returns:list: A list of dictionaries containing the extracted information."""useful_info = []if 'webPages' in search_results and 'value' in search_results['webPages']:for id, result in enumerate(search_results['webPages']['value']):info = {'id': id + 1,  # Increment id for easier subsequent operations'title': result.get('name', ''),'url': result.get('url', ''),'site_name': result.get('siteName', ''),'date': result.get('datePublished', '').split('T')[0],'snippet': result.get('snippet', ''),  # Remove HTML tags# Add context content to the information'context': ''  # Reserved field to be filled later}useful_info.append(info)return useful_info

替换为:

def extract_relevant_info(search_results):"""Extract relevant information from search results.Compatible with custom search result JSON (not Bing).Args:search_results (dict): JSON response containing search results.Returns:list: A list of dictionaries containing the extracted information."""useful_info = []if 'results' in search_results and isinstance(search_results['results'], list):for id, result in enumerate(search_results['results']):info = {'id': id + 1,'title': result.get('title', ''),'url': result.get('url', ''),'site_name': '',  # 该结构中无 site_name 字段'date': '',       # 该结构中无 datePublished 字段'snippet': result.get('content', ''),  # 使用 content 字段'context': ''}useful_info.append(info)return useful_info

3,替换Bing搜索

目前Bing关闭的API,原方式无法继续使用。修改 bing_search.py:

async def bing_web_search_async(query, subscription_key, endpoint, market='en-US', language='en', timeout=20):"""Perform an asynchronous search using the Bing Web Search API.Args:query (str): Search query.subscription_key (str): Subscription key for the Bing Search API.endpoint (str): Endpoint for the Bing Search API.market (str): Market, e.g., "en-US" or "zh-CN".language (str): Language of the results, e.g., "en".timeout (int): Request timeout in seconds.Returns:dict: JSON response of the search results. Returns empty dict if all retries fail."""headers = {"Ocp-Apim-Subscription-Key": subscription_key}params = {"q": query,"mkt": market,"setLang": language,"textDecorations": True,"textFormat": "HTML"}max_retries = 5retry_count = 0while retry_count < max_retries:try:response = session.get(endpoint, headers=headers, params=params, timeout=timeout)response.raise_for_status()search_results = response.json()return search_resultsexcept Exception as e:retry_count += 1if retry_count == max_retries:print(f"Bing Web Search Request Error occurred: {e} after {max_retries} retries")return {}print(f"Bing Web Search Request Error occurred, retrying ({retry_count}/{max_retries})...")time.sleep(1)  # Wait 1 second between retries

替换为:

async def bing_web_search_async(query, subscription_key, endpoint, market='en-US', language='en', timeout=20):client = TavilyClient("tvly-dev-*****")response = client.search(query=query)response.raise_for_status()search_results = response.json()print("=========",search_results)return search_results

4,命令行启动

 【问题解决模式】

python scripts/run_web_thinker.py \--single_question "What is OpenAI Deep Research?" \--bing_subscription_key "YOUR_BING_SUBSCRIPTION_KEY" \  # 用于调用 Bing 搜索API实现搜索增强(如 RAG)--api_base_url "YOUR_API_BASE_URL" \                    # 主模型的 API 接口基础地址,如 http://localhost:8000/v1--model_name "QwQ-32B" \                                # 主模型名称,可为本地模型或远程托管模型--tokenizer_path "PATH_TO_YOUR_TOKENIZER" \             # 主模型使用的分词器路径,如 ./tokenizers/qwq32b/--aux_api_base_url "YOUR_AUX_API_BASE_URL" \            # 辅助模型 API 接口地址--aux_model_name "Qwen2.5-32B-Instruct" \               # 辅助模型名称,用于多模型结果对比、增强或检验--aux_tokenizer_path "PATH_TO_YOUR_AUX_TOKENIZER"       # 辅助模型的分词器路径

【报告生成模式】

python scripts/run_web_thinker_report.py \--single_question "What are the models of OpenAI and what are the differences?" \--bing_subscription_key "YOUR_BING_SUBSCRIPTION_KEY" \--api_base_url "YOUR_API_BASE_URL" \--model_name "QwQ-32B" \--aux_api_base_url "YOUR_AUX_API_BASE_URL" \--aux_model_name "Qwen2.5-32B-Instruct" \--tokenizer_path "PATH_TO_YOUR_TOKENIZER" \--aux_tokenizer_path "PATH_TO_YOUR_AUX_TOKENIZER"

5,web 启动

cd demo
streamlit run run_demo.py

【报错】There is no current event loop in thread 'ScriptRunner.scriptThread'.

【解决】修改 bin_search.py 457 行:关闭加锁。

self.lock = asyncio.Lock()
👇
self.lock = None

【报错】Generate Response Error occurred: Connection error

【解决】修改 settings.py _load_client()

   def _load_client(self, api_base_url, aux_api_base_url):self.client = AsyncOpenAI(api_key="empty",base_url=api_base_url,)self.aux_client = AsyncOpenAI(api_key="empty",base_url=aux_api_base_url,)   👇 def _load_client(self, api_base_url, aux_api_base_url):client = OpenAI(api_key="sk-***",base_url="https://api.deepseek.com/beta")self.client = clientself.aux_client = client
# bing_search.py
use_model_name='QwQ-32B',
aux_model_name='Qwen2.5-72B-Instruct',
👇
use_model_name='deepseek-chat',
aux_model_name='deepseek-chat',

【报错】Invalid max_tokens value, the valid range of max_tokens is [1, 8192]

【解决】修改 bing_search.py

response = await client.completions.create(model=env.aux_model_name,max_tokens=4096,prompt=prompt,timeout=3600,)
👇
response = client.chat.completions.create(model=env.aux_model_name,messages=[{"role": "system", "content": prompt},],)

【报错】Generate Response Error occurred: Error code: 400 - {'error': {'message': 'Invalid max_tokens value, the valid range of max_tokens is [1, 8192]', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_request_error'}}, Starting retry attempt 1

【解决】修改 run_login.py generate_response()

async def generate_response(client: AsyncOpenAI,prompt: str,temperature: float = 0.0,top_p: float = 1.0,max_tokens: int = 4096,repetition_penalty: float = 1.0,top_k: int = 1,min_p: float = 0.0,model_name: str = "QwQ-32B",stop: List[str] = ["<|end_search_query|>"],retry_limit: int = 3,
):"""Generate a streaming response with retry logic"""for attempt in range(retry_limit):try:client = OpenAI(api_key="sk-****",base_url="https://api.deepseek.com/beta")response = client.chat.completions.create(model="deepseek-chat",temperature=temperature,messages=[{"role": "system", "content": prompt},],stream=True)async for chunk in response:if chunk.choices[0].message.content:yield chunk.choices[0].message.contentreturn  except Exception as e:print(f"Generate Response Error occurred: {e}, Starting retry attempt {attempt + 1}")if attempt == retry_limit - 1:print(f"Failed after {retry_limit} attempts: {e}")await asyncio.sleep(0.5 * (attempt + 1))yield ""  

【报错】Generate Response Error occurred: 'async for' requires an object with __aiter__ method, got Stream, Starting

【解决】DeepSeek的输出不是标准的迭代格式,修改 run_logit.py generate_response()

async for chunk in response:if chunk.choices[0].message.content:yield chunk.choices[0].message.contentreturn  
👇
yield response.choices[0].message.content

相关文章:

DeepSearch:WebThinker开启AI搜索研究新纪元!

1&#xff0c;项目简介 WebThinker 是一个深度研究智能体&#xff0c;使 LRMs 能够在推理过程中自主搜索网络、导航网页&#xff0c;并撰写研究报告。这种技术的目标是革命性的&#xff1a;让用户通过简单的查询就能在互联网的海量信息中进行深度搜索、挖掘和整合&#xff0c;从…...

springCloud/Alibaba常用中间件之Setinel实现熔断降级

文章目录 SpringCloud Alibaba:依赖版本补充Sentinel:1、下载-运行&#xff1a;Sentinel(1.8.6)下载sentinel&#xff1a;运行&#xff1a;Sentinel <br> 2、流控规则① 公共的测试代码以及需要使用的测试Jmeter①、流控模式1. 直接:2. 并联:3. 链路: ②、流控效果1. 快速…...

从裸机开发到实时操作系统:FreeRTOS详解与实战指南

从裸机开发到实时操作系统&#xff1a;FreeRTOS详解与实战指南 本文将带你从零开始&#xff0c;深入理解嵌入式系统中的裸机开发与实时操作系统&#xff0c;以FreeRTOS为例&#xff0c;全面剖析其核心概念、工作原理及应用场景。无论你是嵌入式新手还是希望提升技能的开发者&am…...

Deeper and Wider Siamese Networks for Real-Time Visual Tracking

现象&#xff1a; the backbone networks used in Siamese trackers are relatively shallow, such as AlexNet , which does not fully take advantage of the capability of modern deep neural networks. direct replacement of backbones with existing powerful archite…...

简单介绍C++中线性代数运算库Eigen

Eigen 是一个高性能的 C 模板库&#xff0c;专注于线性代数、矩阵和向量运算&#xff0c;广泛应用于科学计算、机器学习和计算机视觉等领域。以下是对 Eigen 库的详细介绍&#xff1a; 1. 概述 核心功能&#xff1a;支持矩阵、向量运算&#xff0c;包括基本算术、矩阵分解&…...

Python爬虫实战:研究decrypt()方法解密

1. 引言 1.1 研究背景与意义 在当今数字化时代,网络数据蕴含着巨大的价值。然而,许多网站为了保护其数据安全和商业利益,会采用各种加密手段对传输的数据进行处理。这些加密措施给数据采集工作带来了巨大挑战。网络爬虫逆向解密技术应运而生,它通过分析和破解网站的加密机…...

黑马程序员C++2024版笔记 第0章 C++入门

1.C代码的基础结构 以hello_world代码为例&#xff1a; 预处理指令 #include<iostream> using namespace std; 代码前2行是预处理指令&#xff0c;即代码编译前的准备工作。&#xff08;编译是将源代码转化为可执行程序.exe文件的过程&#xff09; 主函数 主函数是…...

c#定义占用固定字节长度的结构体字段

在c中&#xff0c;经常类似这样定义结构体&#xff1a; struct DEMO_STRUCT {int a;int b;char c[128]; }; 定义这个结构体&#xff0c;占用了136个字节的内存空间&#xff0c;关键的是&#xff0c;它的内存块是连续的&#xff0c;其中c占用了128个字节 然后如果想在c#中定义…...

foxmail - foxmail 启用超大附件提示密码与帐号不匹配

foxmail 启用超大附件提示密码与帐号不匹配 问题描述 在 foxmail 客户端中&#xff0c;启用超大附件功能&#xff0c;输入了正确的账号&#xff08;邮箱&#xff09;与密码&#xff0c;但是提示密码与帐号不匹配 处理策略 找到 foxmail 客户端目录/Global 目录下的 domain.i…...

Crowdfund Insider聚焦:CertiK联创顾荣辉解析Web3.0创新与安全平衡之术

近日&#xff0c;权威金融科技媒体Crowdfund Insider发布报道&#xff0c;聚焦CertiK联合创始人兼CEO顾荣辉教授在Unchained Summit的主题演讲。报道指出&#xff0c;顾教授的观点揭示了Web3.0生态当前面临的挑战&#xff0c;以及合规与技术在推动行业可持续发展中的关键作用。…...

EDR与XDR如何选择适合您的网络安全解决方案

1. 什么是EDR&#xff1f; 端点检测与响应&#xff08;EDR&#xff09; 专注于保护端点设备&#xff08;如电脑、服务器、移动设备&#xff09;。通过在端点安装代理软件&#xff0c;EDR实时监控设备活动&#xff0c;检测威胁并快速响应。 EDR核心功能 实时监控&#xff1a;…...

PowerBI链接EXCEL实现自动化报表

PowerBI链接EXCEL实现自动化报表 曾经我将工作中一天的工作缩短至2个小时&#xff0c;其中最关键的一步就是使用PowerBI链接Excel做成一个自动化报表&#xff0c;PowerBI更新源数据&#xff0c;Excel更新报表并且保留报表格式。 以制作一个超市销售报表为例&#xff0c;简单叙…...

腾讯云MCP数据智能处理:简化数据探索与分析的全流程指南

引言 在当今数据驱动的商业环境中&#xff0c;企业面临着海量数据处理和分析的挑战。腾讯云MCP(Managed Cloud Platform)提供的数据智能处理解决方案&#xff0c;为数据科学家和分析师提供了强大的工具集&#xff0c;能够显著简化数据探索、分析流程&#xff0c;并增强数据科学…...

Android framework 中间件开发(一)

在Android开发中,经常会调用到一些系统服务,这些系统服务简化了上层应用的开发,这便是中间件的作用,中间件是介于系统和应用之间的桥梁,将复杂的底层逻辑进行一层封装,供上层APP直接调用,或者将一些APP没有权限一些操作放到中间件里面来实施. 假设一个需求,通过中间件调节系统亮…...

Lua中使用module时踩过的坑

在lua中设置某个全局对象(假如对象名为LDataUser)为nil时, LDataUser并不会变成nil, 但在有些情况下设置LDataUser nil时却真变成了nil&#xff0c;然后会导致后续再使用LDataUser时会抛nil异常, 后来发现是使用module搞的鬼&#xff0c;下面看看豆包AI给的解释&#xff0c;还…...

MATLAB中的概率分布生成:从理论到实践

MATLAB中的概率分布生成&#xff1a;从理论到实践 引言 MATLAB作为一款强大的科学计算软件&#xff0c;在统计分析、数据模拟和概率建模方面提供了丰富的功能。本文将介绍如何使用MATLAB生成各种常见的概率分布&#xff0c;包括均匀分布、正态分布、泊松分布等&#xff0c;并…...

C# 面向对象 构造函数带参无参细节解析

继承类构造时会先调用基类构造函数&#xff0c;不显式调用基类构造函数时&#xff0c;默认调用基类无参构造函数&#xff0c;但如果基类没有写无参构造函数&#xff0c;会无法调用从而报错&#xff1b;此时&#xff0c;要么显式的调用基类构造函数&#xff0c;并按其格式带上参…...

轨迹误差评估完整流程总结(使用 evo 工具)

roslaunch .launch rosbag play your_dataset.bag -r 2.0 ✅ 第二步&#xff1a;录制估计轨迹 bash 复制编辑 rosbag record -O traj_only.bag /aft_mapped_to_init 运行一段时间后 CtrlC 停止&#xff0c;生成 traj_only.bag 第三步&#xff1a;提取估计轨迹和真值轨迹为…...

Spring Boot 跨域问题全解:原理、解决方案与最佳实践

精心整理了最新的面试资料和简历模板&#xff0c;有需要的可以自行获取 点击前往百度网盘获取 点击前往夸克网盘获取 一、跨域问题的本质 1.1 什么是跨域&#xff1f; 跨域&#xff08;Cross-Origin&#xff09;问题源于浏览器的同源策略&#xff08;Same-Origin Policy&…...

vhca_id 简介,以及同 pf, vf 的关系

vhca_id 指的是 Virtual Host Channel Adapter ID&#xff08;虚拟主机通道适配器编号&#xff09;&#xff0c;它是 NVIDIA&#xff08;Mellanox&#xff09;网络设备虚拟化架构中的一个核心概念。 它与 PF&#xff08;物理功能&#xff09;、VF&#xff08;虚拟功能&#xff…...

LlamaIndex 第九篇 Indexing索引

索引概述 数据加载完成后&#xff0c;您将获得一个文档对象(Document)列表&#xff08;或节点(Node)列表&#xff09;。接下来需要为这些对象构建索引(Index)&#xff0c;以便开始执行查询。 索引&#xff08;Index&#xff09; 是一种数据结构&#xff0c;能够让我们快速检索…...

微信小程序原生swiper高度自适应图片,不同屏幕适配,正方形1:1等比例图片轮播

🤵 作者:coderYYY 🧑 个人简介:前端程序媛,目前主攻web前端,后端辅助,其他技术知识也会偶尔分享🍀欢迎和我一起交流!🚀(评论和私信一般会回!!) 👉 个人专栏推荐:《前端项目教程以及代码》 ✨一、前言分析 一开始只设了图片的mode="widthFix" st…...

在 C# 中将 DataGridView 数据导出为 CSV

在此代码示例中&#xff0c;我们将学习如何使用 C# 代码将 DataGridView 数据导出到 CSV 文件并将其保存在文件夹中。 在这个程序中&#xff0c;首先&#xff0c;我们必须连接到数据库并从中获取数据。然后&#xff0c;我们将在数据网格视图中显示该数据&#xff0c;…...

解锁 CPU 性能天花板:多维优化策略深度剖析

在数字世界的底层战场&#xff0c;CPU 如同指挥千军万马的将军&#xff0c;掌控着程序运行的节奏与效率。无论是大型服务器应用&#xff0c;还是手机端的轻量化程序&#xff0c;CPU 性能的优化都如同解锁隐藏力量的密码&#xff0c;能让程序在执行效率上实现质的飞跃。本文将深…...

Android SwitchButton 使用详解:一个实际项目的完美实践

Android SwitchButton 使用详解&#xff1a;一个实际项目的完美实践 引言 在最近开发的 Android 项目中&#xff0c;我遇到了一个需要自定义样式开关控件的需求。经过多方比较&#xff0c;最终选择了功能强大且高度可定制的 SwitchButton 控件。本文将基于实际项目中的使用案…...

Kafka如何实现高性能

Kafka如何实现高性能 Kafka之所以能成为高性能消息系统的标杆&#xff0c;是通过多层次的架构设计和优化实现的。 一、存储层优化 1. 顺序I/O设计 日志结构存储&#xff1a;所有消息追加写入&#xff0c;避免磁盘随机写分段日志&#xff1a;将日志分为多个Segment文件&…...

MySQL中表的增删改查(CRUD)

一.在表中增加数据&#xff08;Create&#xff09; INSERT [INTO] TB_NAME [(COLUMN1,COLUMN2,...)] VALUES (value_list1),(value_list2),...;into可以省略可仅选择部分列选择插入&#xff0c;column即选择的列&#xff0c; 如图例可以选择仅在valuelist中插入age和id如果不指…...

项目思维vs产品思维

大家好&#xff0c;我是大明同学。 这期内容&#xff0c;我们来聊一下项目思维和产品思维的区别。 项目是实施关键&#xff0c;力求每一步都精准到位&#xff1b;产品则是战略导向&#xff0c;确保所选之路正确无误。若缺乏优异成果&#xff0c;即便按时完成&#xff0c;也只…...

游戏引擎学习第285天:“Traversables 的事务性占用”

回顾并为当天的工作做准备 我们有一个关于玩家移动的概念&#xff0c;玩家可以在点之间移动&#xff0c;而且当这些点移动时&#xff0c;玩家会随之移动。现在这个部分基本上已经在工作了。我们本来想实现的一个功能是&#xff1a;当玩家移动到某个点时&#xff0c;这个点能“…...

基于DWT的音频水印算法

基于离散小波变换&#xff08;DWT&#xff09;的音频水印算法是一种结合信号处理与信息隐藏的技术&#xff0c;旨在将版权信息或标识隐蔽地嵌入音频信号中&#xff0c;同时保证不可感知性和鲁棒性。以下是该算法的核心步骤及关键技术点&#xff1a; ​1. 算法基本原理​ ​DWT…...