编程笔记

lifelong learning & practice makes perfect

译|NLWeb 协议简介

微软最近开源了一个名为 NLWeb 的协议,旨在为网站添加对话式界面。1 它利用了许多网站已经拥有的 Schema.org 结构化数据,并内置了对 MCP(模型上下文协议)的支持,从而实现人与人之间的对话以及代理之间的通信。

核心思想: NLWeb 创建了一个标准协议,将任何网站转换为对话式界面,人类和 AI 代理都可以自然地查询。

想试试 NLWeb 吗?

在撰写这篇文章的过程中,我实现了用于 MCP 服务器的 NLWeb 搜索。请参阅“Glama NLWeb 服务器”部分以获取示例。

NLWeb 解决了什么问题?

目前,网站拥有结构化数据(Schema.org),但 AI 代理或对话式界面没有标准的访问方式。每个实现都是定制的。传统的搜索界面在处理具有上下文感知能力的多轮查询时会遇到困难。

NLWeb 创建了一个用于对话式访问 Web 内容的标准协议。就像 RSS 为联合内容所做的那样,NLWeb 为 AI 交互做出了贡献——一个实现服务于人类聊天界面和程序化的代理访问。

关键:NLWeb 利用 LLM 对 Schema.org 的现有理解来创建即时对话界面,而不是为每个网站构建定制的 NLP。

真正的力量来自于保留上下文的多轮对话:

  1. “查找晚餐聚会的食谱”
  2. “仅限素食选项”
  3. “可以在一小时内准备好”

每个查询都建立在前一个上下文的基础上——这是传统搜索界面难以处理的。

NLWeb 如何工作

双组件系统

  1. 协议层:REST API(/ask 端点)和 MCP 服务器(/mcp 端点),它们接受自然语言查询并返回 Schema.org JSON 响应
  2. 实现层:参考实现,用于协调多个 LLM 调用以进行查询处理

查询处理流程

用户查询 → 并行预处理 → 向量检索 → LLM 排序 → 响应
├─ 相关性检查
├─ 去语境化
├─ 记忆检测
└─ 快速通道

在这个流程中,单个查询可能会触发 50 多个有针对性的 LLM 调用,用于:

  • 基于对话历史的查询去语境化
  • 针对站点内容的相关性评分
  • 使用每个内容类型的自定义提示进行结果排序
  • 可选的后处理(摘要/生成)

“快速通道”(fast track)优化启动了一个与预处理同时进行的并行检索路径(步骤 3),但结果会被阻止,直到相关性检查完成。2

视频说明

在我写完这篇文章后,我收到了这个视频,其中包含了 R.V. Guha(Schema.org、RSS 和 RDF 的创建者)对 NLWeb 的精彩介绍:

前往

为什么需要 50 多个 LLM 调用?

NLWeb 没有使用一个大型提示来处理所有事情,而是将每个查询分解为几十个小的、具体的问题:

  • “这个查询是关于食谱的吗?”
  • “它是否引用了之前提到的内容?”
  • “用户是否要求记住饮食偏好?”
  • “这个特定结果的相关性有多高?”

这种方法有两个主要优点:

  1. 没有幻觉 - 结果只来自你的实际数据库
  2. 更高的准确性 - 每次 LLM 调用都有一个明确的任务,它可以很好地完成

可以把它想象成拥有一支专家团队,而不是一个通才。

即使你不使用 NLWeb,这种模式——使用许多集中的 LLM 调用而不是一个复杂的提示——也值得借鉴。

快速开始

理解 NLWeb 的最佳方式是亲自尝试一下。

Microsoft 提供了一个快速入门指南,用于设置一个带有 Behind The Tech RSS 订阅的 NLWeb 服务器示例。

1
2
3
4
5
6
7
8
9
10
11
12
# 设置
git clone https://github.com/microsoft/NLWeb
cd NLWeb
python -m venv myenv
source myenv/bin/activate
cd code
pip install -r requirements.txt
# 配置 (复制 .env.template → .env, 更新 API 密钥)
# 加载数据
python -m tools.db_load https://feeds.libsyn.com/121695/rss Behind-the-Tech
# 运行
python app-file.py

打开 localhost:8000,你应该有一个正在运行的 NLWeb 服务器。

我还注意到该存储库包含一个 CLI,用于简化应用程序的配置、测试和执行。但是,我很难让它正常工作。

一旦服务器运行起来,你可以向它提问,例如:

1
2
3
curl -X POST http://localhost:8000/ask \
-H "Content-Type: application/json" \
-d '{ "query": "tell me more about the first one", "prev": "find podcasts about AI,what topics do they cover" }'

这将返回一个 JSON 响应,例如:

1
2
3
4
5
6
7
8
9
10
{
"query_id": "abc123",
"results": [{
"url": "https://...",
"name": "AI Safety with Stuart Russell",
"score": 85,
"description": "Discussion on alignment challenges...",
"schema_object": { "@type": "PodcastEpisode", ... }
}]
}

Glama NLWeb 服务器

在撰写这篇文章的过程中,我使用 Node.js 构建了一个简单的 NLWeb 服务器。你可以使用它来查询我们的 MCP 服务器 目录:

1
2
3
curl -X POST https://glama.ai/nlweb/ask \
-H "Content-Type: application/json" \
-d '{"query": "MCP servers for working with GitHub"}'

据我所知,这是有史以来第一个公开的 NLWeb 端点!

由于 LLM 调用的数量,它需要几秒钟才能响应。

或者,如果你想继续对话:

1
2
3
curl -X POST https://glama.ai/nlweb/ask \
-H "Content-Type: application/json" \
-d '{ "query": "servers that can create PRs", "prev": "MCP servers for working with GitHub" }'

或者,如果你想总结结果:

1
2
3
curl -X POST https://glama.ai/nlweb/ask \
-H "Content-Type: application/json" \
-d '{ "query": "MCP servers for working with GitHub", "mode": "summarize" }'

当你想要一个概述而不是仅仅一个结果列表时,这很有用。

或者,如果你想生成一个响应:

1
2
3
curl -X POST https://glama.ai/nlweb/ask \
-H "Content-Type: application/json" \
-d '{ "query": "MCP servers for working with GitHub", "mode": "generate" }'

此模式尝试使用检索到的结果来回答问题(如传统的 RAG)

使实现变得容易的事情:

  • 我们已经为每个 MCP 服务器和向量存储创建了嵌入
  • 我们已经有一种进行 LLM 调用的方法

在实现过程中,我想到了一些问题:

  • 似乎 NLWeb 没有规定 /ask 端点需要托管在哪里——它必须是 https://glama.ai/ask 还是可以是 https://glama.ai/nlweb/ask
  • 我不清楚哪种 Schema.org 数据最适合描述 MCP 服务器。

毫不奇怪,管道中最慢的部分是 LLM 调用。

REST API

目前,NLWeb 在 /ask/mcp 端点支持两个 API。参数对于两者都是相同的,大部分功能也是如此。/mcp 端点以 MCP 客户端可以使用的格式返回答案。/mcp 端点还支持核心 MCP 方法(list_toolslist_promptscall_toolget_prompt)。

/ask 端点支持以下参数:

参数 类型 描述
query string 自然语言问题
site string 范围限定到特定的数据子集
prev string 逗号分隔的先前查询
decontextualized_query string 如果提供,则跳过去语境化
streaming bool 启用 SSE 流式传输
query_id string 跟踪对话
mode string listsummarizegenerate

与 MCP 集成

由于 NLWeb 默认包含一个 MCP 服务器,你可以配置 Claude for Desktop 与 NLWeb 对话。

如果你的 NLWeb 服务器已经运行,那么只需将以下内容添加到你的 ~/Library/Application Support/Claude/claude_desktop_config.json 配置文件中即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
{ "mcpServers": 
{ "ask_nlw": {
"command": "/Users/yourname/NLWeb/myenv/bin/python",
"args": [
"/Users/yourname/NLWeb/code/chatbot_interface.py",
"--server",
"http://localhost:8000",
"--endpoint", "/mcp"
],
"cwd": "/Users/yourname/NLWeb/code"
}
}
}

Implementation Reality

该文档表明,如果你有现有的 Schema.org 标记或 RSS 订阅,你可以快速运行一个基本原型。

实际上很简单的事情:

  • 加载 RSS 订阅或 Schema.org 数据
  • 使用提供的提示进行基本搜索功能
  • 使用 Qdrant 进行本地开发

需要更多努力的事情:

  • 大规模的生产部署
  • 优化每个查询的 50 多个 LLM 调用(文档中提到)
  • 为你自己的领域进行自定义提示工程
  • 维护向量存储和实时数据之间的数据新鲜度

我已经有了很多这些组件,所以我能够在 1 小时内运行一个基本原型。但是,要使它能够用于生产,我需要花更多的时间考虑 LLM 调用的成本。

你应该关心吗?

如果以下情况,则应关心:

  • 你已经有结构化数据(Schema.org、RSS)
  • 你想要启用超出关键字的对话式搜索
  • 你需要通过 MCP 进行程序化的 AI 代理访问
  • 你可以尝试早期阶段的技术

如果以下情况,则不应关心:

  • 你需要经过实战考验的生产代码
  • 你无法处理大量的 LLM API 成本
  • 你的内容结构不佳
  • 你期望即插即用的简单性

NLWeb

NLWeb 作为一种战略方向比作为当前技术更有趣。NLWeb 由 R.V. Guha(Schema.org、RSS 和 RDF 的创建者)构思和开发,他现在是微软的 CVP 和技术研究员。3 这可是强大的血统。

O’Reilly 原型证明它对于内容丰富的网站是可行的。快速入门表明它对开发人员来说是平易近人的。但是“几天内完成原型”并不意味着“几周内完成生产”。

把它看作是对使你的内容成为原生对话式的投资。技术基础是坚实的——REST API、标准格式、经过验证的向量存储。愿景是引人注目的。代码需要改进。

想尝试一下吗?克隆代码库并尝试上面的快速入门。

原文

欢迎关注我的其它发布渠道

Related Issues not found

Please contact @yiGmMk to initialize the comment