鸿蒙平台集成 tavily_dart 进行 AI 语义搜索
在鸿蒙上做智能助理或垂直知识类应用,实时获取互联网的结构化信息是绕不开的环节。传统的关键词搜索往往带回大量噪音,直接喂给 LLM 不仅浪费 Token,更容易引发幻觉。
tavily_dart 是一个专门为 AI 场景设计的搜索客户端,背后对接 Tavily 的 LLM 优化搜索引擎。它能自动完成网页抓取、内容去重和摘要生成,返回干净的结构化数据。配合鸿蒙的异步能力,可以让应用具备'动态联网'的特性,同时又保持界面流畅。
它是怎么工作的
整体流程不算复杂:查询意图经 tavily_dart 格式化后发送给 Tavily 服务,服务端根据语义召回网页并进行清洗、摘要,最后返回结构化的 JSON,同时附带引用来源。
graph TD
A[自然语言查询意图 User Query] --> B[Tavily 客户端解析器]
B --> C{AI 搜索策略引擎}
C -- 高级搜索 Advanced Search --> D[网页全量抓取与语义解析]
C -- 基础检索 Basic Retrieval --> E[标题与摘要提取]
D & E --> F[内容重排序与去噪 Re-ranking]
F --> G[生成符合 LLM 格式的上下文 JSON]
G --> H[注入鸿蒙端 AI 业务逻辑层]
H --> I[鸿蒙 UI 智能回复呈现]
J[多维度引用来源记录 Citations] -.-> G
集成配置
在 pubspec.yaml 中添加依赖:
dependencies:
tavily_dart: ^0.1.0
如果是面向政务、医疗等场景,建议在初始化时开启 include_answer。这样一来,客户端可以先拿到 Tavily 生成的预置回复,在本地模型未完全加载时提供快速响应,对用户体验比较友好。
另外,鸿蒙端访问外部 API 可能受网络代理影响,记得在 ClientInfo 里注入准确的地理位置标识,有助于提高本地化搜索精度。
关键 API
tavily_dart 的核心就是 TavilyClient 和 search() 方法。返回的 SearchResult 包含标题、URL、评分和正文片段。下表列了最常用的几个:
| 类/方法 | 用途 | 说明 |
|---|---|---|
TavilyClient | 客户端封装 | 管理 API Key,所有搜索请求的入口 |
search() | 执行搜索 | 可配置深度(SearchDepth)、结果数量等 |
SearchResult | 搜索结果对象 | 含 title、url、content、score 等字段 |
一个简单的使用示例:
import 'package:tavily_dart/tavily_dart.dart';
final client = TavilyClient(apiKey: 'your_api_key_here');
final response = await client.search(
query: 'OpenHarmony NEXT 最新技术趋势',
searchDepth: SearchDepth.advanced,
maxResults: 5,
);
print('找到 ${response.results.length} 条结果');
for (var r in response.results) {
print('${r.title} (评分: ${r.score})');
}
在需要限定来源的场景(比如仅从政府网站获取),可以用 include_domains 参数过滤,避免无关信息污染。
应用场景
- 法律助手:为本地小模型提供实时判例检索,增强回答的可信度。
- 商贸看板:在展会或会议现场快速获取原材料价格波动,做动态展示。
- 舆情监控:从全网采集突发事件评论,用语义聚合生成舆情地图。
这些场景的共性需求是'快速获取结构化外部知识',用 tavily_dart 比从头写爬虫要省很多开发时间。
实际接入时的坑
一次搜索可能导致 UI 卡死
深度搜索(SearchDepth.advanced)耗时 3-5 秒很正常,如果在主线程直接 await,界面会卡住。解决方法有两种:
- 增量展示:配合
StreamBuilder或类似机制,先拿到部分结果就渲染标题,正文慢慢补全。 - 扔到 isolate:把请求逻辑移到 isolate 里执行,主界面不受影响。但这会引入额外的通信成本,需要权衡。
内容合规问题
从网上直接抓的内容可能包含敏感词或违法链接。最好在结果返回后、渲染前加一层过滤。可以用正则检查,或者维护一个敏感域名黑名单做拦截。这不是最优雅的办法,但在上线前能避免不少麻烦。
封装一个搜索服务
实际开发中通常会封装一个服务类,方便统一管理 API Key 和调用逻辑:
import 'package:tavily_dart/tavily_dart.dart';
class AISearchService {
final TavilyClient _client;
AISearchService(String apiKey) : _client = TavilyClient(apiKey: apiKey);
Future<List<SearchResult>> search(String query) async {
final response = await _client.search(
query: query,
searchDepth: SearchDepth.advanced,
maxResults: 5,
);
return response.results;
}
}
后续在 ChangeNotifier 或状态管理里调用这个服务即可,按照自己的架构挂到界面上就行。
小结
tavily_dart 让鸿蒙应用能够用很少的代码接入结构化的网络搜索,尤其适合需要实时外部知识的 AI 助手场景。不过注意处理好异步和内容过滤,否则线上容易出状况。
如果后续想在搜索策略上做优化,可以关注返回结果里的 score 字段,但别单次分数定生死——搜索质量受查询表达影响很大,配合用户埋点做长期分析才能看出真实效果。


