资讯动态

WeKnora 网络搜索与网页抓取实战指南:13 种搜索引擎接入、Agent 联网检索与 SSRF 安全体系

发布时间:2026/9/13 2:02:45 来源:尧图企业网站定制
WeKnora 网络搜索与网页抓取实战指南13 种搜索引擎接入、Agent 联网检索与 SSRF 安全体系【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnoraWeKnora 是开源的 LLM 知识平台其网络搜索能力用于补充知识库之外的信息智能体通过web_search查找结果再通过web_fetch读取网页正文两者共同构成 Agent 的外部信息通道。本文以 website-docs/03-features/11-web-search.md 为核心骨架结合仓库源码与部署配置系统讲解如何在「设置 → 网络搜索」中接入 DuckDuckGo、Google、Bing、Tavily、SearXNG 等 13 个搜索引擎深入分析web_search/web_fetch两个 Agent 工具的参数语义、续读机制与失败语义并剖析底层 SSRF 防护链路与新增搜索引擎的扩展步骤帮助你在一线部署与二次开发中直接落地。网络搜索在 WeKnora 中的角色WeKnora 的知识问答能力以知识库Knowledge Base为主体但现实中的问题往往需要补充知识库之外的最新或外部信息。此时智能体按以下分工工作web_search负责「发现」根据用户问题检索网页标题、摘要、域名、日期等搜索结果web_fetch负责「读取」按 URL可能是 wN 页面 ID、用户直接给出的网页地址或页面中发现的链接抓取正文供模型分析。两个工具配合形成完整的「搜索 → 精选 → 读页 → 综合作答」闭环。在使用层面管理员在「设置 → 网络搜索」中选择提供商、填写凭据并测试连接然后在智能体的运行配置中选择该搜索配置即可搜索结果数受智能体的最大结果数设置约束上限 20。一个重要设计变化是Agent 搜索不再强制先调用grep_chunks和knowledge_search。是否检索知识库取决于任务相关性与当前可用的工具知识库检索与网络搜索不再有强制的先后顺序——网络搜索的定位是「按需启用的外部信息来源」而非知识库流程的附属环节。支持的搜索引擎与提供商差异所有搜索引擎在 internal/container/container.go 中通过registry.Register注册为「provider 类型 → 工厂函数」的映射。当前仓库注册了 13 个引擎registry.Register(duckduckgo, infra_web_search.NewDuckDuckGoProvider) registry.Register(google, infra_web_search.NewGoogleProvider) registry.Register(bing, infra_web_search.NewBingProvider) registry.Register(tavily, infra_web_search.NewTavilyProvider) registry.Register(ollama, infra_web_search.NewOllamaProvider) registry.Register(baidu, infra_web_search.NewBaiduProvider) registry.Register(searxng, infra_web_search.NewSearxngProvider) registry.Register(keenable, infra_web_search.NewKeenableProvider) registry.Register(zhipu, infra_web_search.NewZhipuProvider) registry.Register(metaso, infra_web_search.NewMetasoProvider) registry.Register(exa, infra_web_search.NewExaProvider) registry.Register(bocha, infra_web_search.NewBochaProvider) registry.Register(brave, infra_web_search.NewBraveProvider)各引擎的源码文件均位于 internal/infrastructure/web_search/其关键差异如下引擎源码文件是否需要 API Key端点备注DuckDuckGoduckduckgo.go否HTML 抓取优先API 兜底免费可配proxy_urlGooglegoogle.go是还需engine_idGoogle Custom Search API官方 SDKcustomsearch/v1Bingbing.go是https://api.bing.microsoft.com/v7.0/search硬编码Tavilytavily.go是https://api.tavily.com/search硬编码Ollama Web Searchollama.go是https://ollama.com/api/web_search硬编码最多 10 条结果百度千帆 AI 搜索baidu.go是https://qianfan.baidubce.com/v2/ai_search/web_search硬编码SearXNGsearxng.go否租户自填base_url自托管实例唯一允许自定义地址的引擎需过 SSRF 校验Keenablekeenable.go可选https://api.keenable.ai硬编码无 Key 走公共限速端点有 Key 解除限制智谱搜索zhipu.go是https://open.bigmodel.cn/api/paas/v4/web_search硬编码默认引擎search_std秘塔 Metasometaso.go是https://metaso.cn/api/v1/searchextra_config.scope 选择资源范围默认 webpageExaexa.go是https://api.exa.ai/search默认 highlights可用 extra_config.include_text 获取正文博查 Bochabocha.go是https://api.bochaai.com/v1/web-searchextra_config.freshness、summaryBrave Searchbrave.go是https://api.search.brave.com/res/v1/web/search支持按次传 country/freshness除了 SearXNG所有引擎端点均硬编码、租户不可配置——源码注释明确写道Not configurable by tenants — prevents SSRF这是防 SSRF 的第一道措施。这也意味着租户只能通过base_url影响 SearXNG 一个引擎的请求目标。提供商附加配置extra_config部分引擎支持通过extra_config传入提供商特定的非密钥参数这些字段在 internal/types/web_search_provider.go 的GetWebSearchProviderTypes中声明为动态表单字段ConfigFields前端据此渲染配置表单提供商附加配置值Metaso scopewebpage默认、document、scholar、podcast、video、imageExa include_text字符串布尔值例如true默认不取正文Bocha freshnessnoLimit默认、oneDay、oneWeek、oneMonth、oneYearBocha summary字符串布尔值决定是否请求摘要Brave 按次过滤country/freshness 是 web_search 工具参数见下文与 Bocha 固定配置的字段取值不同以智谱搜索为例ConfigFields中声明了search_engine可选search_std/search_pro/search_pro_sogou/search_pro_quark对应不同的价格档位与content_sizemedium/high两个选择型字段Metaso 的scope字段则列出六种内容源。这些字段全部通过ExtraConfig以非加密形式随 Provider 实体持久化。搜索引擎配置Provider 实体每个工作空间Workspace可以创建多个搜索引擎配置实例例如 Production Bing、Test Google存储为web_search_providers表的WebSearchProviderEntity定义见 internal/types/web_search_provider.goAgent 按 ID 引用对应配置。实体字段包括UUID 主键、租户 ID、用户友好名称、provider 类型、描述、参数加密 JSON、是否工作空间默认、时间戳。BeforeCreateGORM 钩子会自动为新增记录生成 UUID。WebSearchProviderParameters是核心参数结构各字段语义如下名称类型默认值说明api_keystring空搜索服务密钥AES-GCM 加密落库仅通过/credentials子资源修改响应中从不返回engine_idstring空仅 Google Custom Search 需要base_urlstring空仅 SearXNG自托管实例地址经utils.ValidateURLForSSRF校验内网地址须加入SSRF_WHITELISTproxy_urlstring空可选出站 HTTP/HTTPS 代理仅隧道流量不替换 API 端点同样过 SSRF 校验extra_configmap[string]stringnil提供商特定参数如 Metaso scope、Exa include_text、Bocha freshness/summary凭据安全AES-GCM 加密与独立凭据接口api_key的安全处理在源码中有三层保障落库加密WebSearchProviderParameters.Value()GORM 的driver.Valuer在写入数据库前用utils.EncryptAESGCM(p.APIKey, key)加密读取时Scan()用utils.DecryptStoredSecretLenient解密密钥来自SYSTEM_AES_KEY。响应永不返回明文处理器通过dto.NewWebSearchProviderResponse序列化APIKey在构造响应时被省略。独立凭据子资源凭据变更走专门的/credentials子资源PUT /:id/credentials避免通过普通更新接口泄露或误改密钥。CRUD 路由由RegisterWebSearchProviderRoutes注册见 internal/router/router.go挂在/web-search-providers路径下包含增删改查、POST /test用存量凭证探测外部服务Admin 权限、POST /:id/test、PUT /:id/credentials另有GET /web-search/providers返回可用引擎类型目录供前端动态渲染表单。Agent 搜索与读页web_search 与 web_fetchweb_search负责发现来源web_fetch负责读取选中的页面。用户指定网页时可直接读页用户要求外部或实时信息时可直接搜索。整个流程可表示为web_search 工具调用示例{query:Python release notes,count:5} {query:Rust release notes,country:DE,freshness:pw,content:true}参数语义count指定结果数量范围是 1 到当前 Agent 配置的最大结果数最多 20省略时沿用现有 Agent 默认值。上游引擎侧同样有限制例如 Brave 的SearchWithFilters会将maxResults钳制在 20 以内Ollama 最多返回 10 条。country/freshness通过新增的 Brave 提供商生效。地区接受两字母代码或ALL时效接受pd过去 24 小时/pw过去一周/pm过去一月/py过去一年或YYYY-MM-DDtoYYYY-MM-DD日期区间。省略country时不向 Brave 传该参数Brave 自身默认 US显式ALL表示全球结果。其它提供商暂不支持这些过滤显式传入时返回错误不会静默忽略。接口层面支持按次过滤的提供商实现了可选的FilteredWebSearchProvider接口见 internal/types/interfaces/web_search.go从而与不支持过滤的提供商明确区分。content默认关闭。设为true时并行抓取前 3 条结果的正文整批 15 秒预算每页最多 5,000 字符摘录其余结果保留搜索摘要需用web_fetch继续读页。抓取失败仍保留摘要完整正文地址通过full_output_path返回。搜索和独立web_fetch共用本轮快照短超时不会取消正在进行的共享抓取。Brave 的相对age原样保留避免把2 days ago伪造为精确发布日期——源码中Age字段直接取自 Brave API 的age/page_age字段。结果处理方面去除空查询、无效 URL、重复结果最大结果数来自 Agent 配置上限 20。Agent 搜索不再调用CompressWithRAG不创建临时知识库不依赖嵌入/重排模型或 Redis 临时状态聊天快速回答管线的 RAG 压缩配置仍由原管线处理。模型输出包含标题、域名、可用日期与 wN 页面 ID。摘要与 provider content 标为未经页面验证的搜索证据每段最多 1,500 字符整批证据预算 16,000 字符。web_fetch 工具调用示例{items:[{url:w1},{url:https://example.com/guide,limit:4000}]}输入接受已知的 wN 页面 ID也接受用户提供或页面中发现的 HTTP(S) URL。短 ID 在模型上下文边界还原UI 与持久化结果保留真实 URL。已移除prompt参数工具 schema 仅暴露url、offset、limit——不再调用第二个模型进行摘要主 Agent 直接分析网页正文。HTML 提取先用 Readability 提取正文成功时直接转换完整提取结果失败时才回退到 main/article/body避免二次选择内部.content节点丢失相邻段落。转为 Markdown 后保留标题、段落、链接、表格和代码。相对链接以最终 HTTP URL 解析嵌入资源不会自动下载。提取逻辑实现在 internal/infrastructure/web_fetch/markdown.go本地回归样例覆盖完整文章的相邻段落、结构化内容、链接目录及代码缩进可通过go test ./internal/infrastructure/web_fetch -run TestMarkdownExtractionFixtures验证。非 HTML 内容纯文本、Markdown、JSON/XML 直接读取避免把...当 HTML 丢掉二进制格式明确报告unsupported_content。内容类型判定见 internal/infrastructure/web_fetch/fetcher.go。渲染兜底HTTP 优先现有 Chromium 动态页面兜底保留。Fetcher会先尝试静态抓取当内容为空、仅含 enable javascript/loading... 占位、或页面带有idapp/idroot且含script时判定需要浏览器渲染此时通过 chromedp 以 headless Chromium 渲染——且渲染也复用 DNS pinning 的 SSRF 防护通过host-resolver-rules将目标主机映射到已解析并校验过的 IP。批处理每批最多 8 项相同规范 URL、offset、limit 去重。各项独立返回success/failed/skipped部分失败保留成功正文。分页与续读offset是从 0 开始的 Unicode 字符偏移limit默认及上限均为 8,000。批次按输出预算分配正文空间返回offset、returned_chars、content_length、truncated有剩余内容时返回next_offset。使用同一 URL 与offsetnext_offset续读内存缓存最多 8 个页面快照仅用于本次运行的字符续读。持久化与跨轮读取快照被淘汰后可通过返回的full_output_path继续读取同一份完整正文不必重新抓网页。旧式字符续读在缓存失效时返回可重试的snapshot_expired从 offset 0 重抓或改用read_file避免拼接不同版本页面。抓取后完整 Markdown 保存到会话所属租户的文件存储返回web://...格式的full_output_pathread_file可跨轮读取这些文件无需启用沙箱。正文与生成它的 assistant 消息绑定读取时校验租户、会话所有者、会话、消息和网页专用绑定普通附件不能作为网页读出。删除消息或会话后不可访问。单个保存的 Markdown 上限 8 MiB保存失败不会丢弃已抓正文结果含storage_error此时续读仅限本轮内存缓存。read_file 续读细节read_file的offset是从 1 开始的行号limit最多 2,000 行网页读取最多 50 KiB并继续受 Agent 输出预算约束遇到超长单行时返回next_offset和next_line_offset用offset加line_offset续读原行——这样无沙箱 Agent 也不需要执行 shell。大小与超时限制Agent 单页下载上限 2 MiBmaxAgentBodySize超限报告body_too_large不会把静默截断的 HTML 冒充完整页面请求超时 60 秒fetchTimeoutAgent 抓取接受 HTTP 2xx 响应。失败语义失败返回稳定错误码与可重试标记ErrorCode枚举覆盖invalid_url、dns_failed、connection_timeout、tls_failed、http_403、http_429、http_5xx、ssrf_rejected、redirect_rejected、body_too_large、snapshot_expired等见 fetcher.go。临时失败可合理重试永久失败可选择其他相关来源证据不足时说明缺口。一次整批失败不会强制终止研究也不能视为验证成功。开关语义关闭联网时无论旧allowed_tools是否列出这两个工具运行时均不注册失败网页不再作为成功网页引用展示。共享抓取器的快速回答路径继续使用NewPipelineFetcher15 秒超时、100 KiB 下载上限、HTTP-only 与原纯文本抽取见 fetcher.go。行为调整与回归验证相比调整前的 Agent 行为当前实现的差异可总结为行为调整前 WeKnora Agent调整后搜索前置强制两个 KB 工具即使未注册根据任务与可用来源选择搜索附带处理可自动入临时 KB 做 RAG直接返回搜索证据按需读页读页参数强制 url prompturl按需 offset/limit正文分析每页再调用模型摘要主 Agent 直接读 Markdown截断每页/整批限额后续页面可能空白无续读每页保留份额、完整正文存储、跨轮按行续读失败整批失败强制停止搜索保留已有证据合理重试或换源调整后仍保留多搜索引擎、wN 引用、批量调用、租户开关与 SSRF 防护通过 Brave 适配器支持 country/freshness不支持过滤的提供商返回明确错误显式contenttrue与独立web_fetch都可读页。自托管 SearXNG免 API Key 的默认可选搜索后端SearXNG 是自托管的元搜索引擎聚合上游多个引擎WeKnora 把它作为免 API Key 的默认可选搜索后端打包在 docker-compose.yml 的searxng/fullprofile 中。关键定制项docker/searxng/settings.yml 包含如下定制search.formats开启jsonWeKnora 后端走/search?formatjsonserver.limiter: false关闭 IP 限流否则后端会被节流若公开部署需重新开启并配置放行名单secret_key: ultrasecretkey由入口脚本以SEARXNG_SECRET环境变量替换其它image_proxy: true、http_protocol_version: 1.0、method: GET、outgoing.request_timeout: 6.0、outgoing.max_request_timeout: 10.0、safe_search: 0等。部署编排细节searxng-init辅助容器先把模板复制进独立 volume避免 SearXNG 入口脚本原地 sed 修改把解析后的密钥写回仓库工作区docker-compose 中通过cp /template/settings.yml /etc/searxng/settings.yml完成。应用容器默认把searxng主机名并入 SSRF 白名单SSRF_WHITELIST_EXTRA${SSRF_WHITELIST_EXTRA:-searxng,qdrant,milvus,weaviate,doris-fe,doris-be,minio}因此租户配置base_url: http://searxng:8080开箱即用无需额外修改白名单。客户端超时 12sdefaultSearxngTimeout见 searxng.go略高于 SearXNG 的outgoing.max_request_timeout: 10.0让上游慢引擎表现为 SearXNG 侧错误而非客户端取消。ValidateSearxngBaseURL在保存与使用两处共享服务层参数校验与 provider 构造函数都调用它保证配置校验一致——它要求非空、绝对 http(s) URL、无 query/fragment并通过utils.ValidateURLForSSRF。SearXNG 请求构造时以languageall显式表示不过滤语言auto是 UI 侧默认值不是合法的/search参数且有意不设置safesearch以尊重实例 settings.yml 中的配置空结果时会透出unresponsive_engines便于诊断上游引擎连通性。出站请求的 SSRF 防护体系SSRF 防护贯穿搜索与抓取两条链路是网络搜索功能的底层安全基石。搜索链路的统一安全客户端internal/infrastructure/web_search/proxy.go 的NewSearchHTTPClient为所有引擎构造统一的安全 HTTP 客户端DialContext使用utils.SSRFSafeDialContext拨号时校验目标 IP防 DNS rebinding重定向逐跳经ssrfSafeRedirect复验ValidateURLForSSRF超过最大跳数直接失败显式proxy_url需通过 SSRF 校验ValidateProxyURL委托给utils.ValidateURLForSSRF只允许 http/https未配置时回落ProxyFromEnvironment。Brave 还额外禁用了重定向跟随CheckRedirect返回http.ErrUseLastResponse避免订阅令牌被转发到任何重定向目标。抓取链路的 DNS pinninginternal/infrastructure/web_fetch/fetcher.go 的pinnedDialContext实现 DNS pinning拨号前先解析主机 IP逐一校验为公网地址或命中 SSRF 白名单随后直接连接到已校验的 IP 而非重新解析主机名彻底阻断 TOCTOU 型 DNS rebindingChromium 渲染路径同样通过host-resolver-rules把目标主机映射到已校验的 IP。网段与内网地址管理内网/回环地址默认被拒绝租户如需让 SearXNG 等自托管服务接受配置必须把对应主机名加入SSRF_WHITELIST或SSRF_WHITELIST_EXTRA。这一规则同样适用于web_fetch抓取内网服务、以及搜索请求的base_url/proxy_url配置。接口抽象与新增搜索引擎两层接口搜索能力由两层接口定义internal/types/interfaces/web_search.go// WebSearchProvider defines the interface for web search providers type WebSearchProvider interface { Name() string Search(ctx context.Context, query string, maxResults int, includeDate bool) ([]*types.WebSearchResult, error) } // WebSearchService defines the interface for web search services type WebSearchService interface { Search(ctx context.Context, providerID string, config *types.WebSearchConfig, query string) ([]*types.WebSearchResult, error) CompressWithRAG(ctx context.Context, sessionID string, tempKBID string, questions []string, ...) (...) }Provider 层负责具体引擎的协议适配Service 层负责按 providerID 路由、参数装配与租户隔离。可选的FilteredWebSearchProvider接口让 Brave 等引擎按次支持 country/freshness。注册表模式internal/infrastructure/web_search/registry.go 维护provider 类型 → 工厂函数的注册表实例按租户参数在调用时创建type ProviderFactory func(params types.WebSearchProviderParameters) (interfaces.WebSearchProvider, error) func (r *Registry) Register(id string, factory ProviderFactory) func (r *Registry) CreateProvider(providerType string, params types.WebSearchProviderParameters) (interfaces.WebSearchProvider, error)如何新增一个搜索引擎按照现有引擎如 brave.go、searxng.go的实现模式接入新引擎共五步在 internal/infrastructure/web_search/ 新建engine.go实现interfaces.WebSearchProviderName()Search()并提供工厂函数func NewEngineProvider(params types.WebSearchProviderParameters) (interfaces.WebSearchProvider, error)官方端点应硬编码为常量HTTP 客户端用NewSearchHTTPClient(timeout, params.ProxyURL)构造。在 internal/types/web_search_provider.go 增加WebSearchProviderType常量。在 internal/container/container.go 的注册处追加registry.Register(engine, infra_web_search.NewEngineProvider)。如需密钥/额外参数校验在 web search provider service 的参数校验分支中补充参考ValidateSearxngBaseURL的共享校验模式并为前端GET /web-search/providers目录补充展示信息即GetWebSearchProviderTypes中新增对应的WebSearchProviderTypeInfo可声明RequiresAPIKey、RequiresEngineID、RequiresBaseURL、SupportsOptionalAPIKey、SupportsProxy与ConfigFields动态表单字段。参考searxng_test.go/zhipu_test.go位于 internal/infrastructure/web_search/用httptest模拟上游编写单测。小结WeKnora 的网络搜索能力由「多引擎 Provider 注册表 加密凭据的配置实体 web_search/web_fetch 双工具 统一 SSRF 防护 可选 SearXNG 自托管后端」五层构成。部署侧只需在设置中配置提供商并选择到智能体即可启用二次开发侧则通过实现WebSearchProvider接口并注册工厂函数即可在半小时内接入新搜索引擎。需要特别注意的三条底线是除 SearXNG 外的端点一律硬编码、base_url与proxy_url一律过 SSRF 校验、api_key一律加密落库且永不回显。理解了这三条就理解了 WeKnora 网络搜索模块的安全设计哲学与扩展边界。【免费下载链接】WeKnoraOpen-source LLM knowledge platform: turn raw documents into a queryable RAG, an autonomous reasoning agent, and a self-maintaining Wiki.项目地址: https://gitcode.com/GitHub_Trending/we/WeKnora创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价