0%

【本文由 DeepSeek 辅助完成】
在日常工作生活中,AI 已经成为我的得力助手。经过长期实践,我总结出一套高效使用 AI 的方法论,现在分享给大家。

开发场景的 AI 应用

对于开发者来说,AI 工具能显著提升工作效率。在遇到技术问题时,我会优先使用 Github Copilot Chat 这类专业工具来咨询问题,比如复杂的 SQL 查询语句或不熟悉的库的使用方法。相比通用聊天助手,这类针对开发场景优化的工具给出的建议更加精准。

代码补全方面,GitHub Copilot 是我的主力工具。我习惯将它的智能补全与 IDE 传统提示相结合,形成”AI+传统”的混合工作流,这样既能获得 AI 的创新建议,又能确保代码规范性。

当需要进行项目级别的修改时,比如实现新需求或重构代码,我会根据情况选择不同的工具。在 IDE 内进行多文件编辑时使用 Github Copilot Edit 功能,如果是在网页端修改 Github 项目,则会考虑是用 Copilot Workspace(示例 PR)。

通用场景的 AI 助手

处理日常信息时,我主要使用腾讯元宝和 Deepseek 这两个工具。腾讯元宝的特色在于可以检索公众号资源,并且支持在混元和 DeepSeek 模型间切换。需要注意的是,国内 AI 助手有时无法直接解析海外链接内容,这时我会先用 Jina AI Reader 将页面转为 Markdown 格式再处理。

内容创作方面,我采取多工具协同策略。通常会让腾讯元宝、ChatGPT 和 DeepSeek 分别生成内容,然后综合各家之长。这种”集思广益”的方式往往能产生更优质的内容。

垂直领域的专业工具

不同专业领域都有对应的 AI 工具利器:

  • 翻译工作首选 DeepL,它在专业术语处理上表现突出
  • 图片生成推荐即梦,支持对单张图片进行迭代编辑
  • 办公场景下腾讯文档 AI 助手的思维导图和 PPT 生成功能很实用
  • 浏览器插件 Monica 可以即时分析网页内容
  • 需要制作手绘风格图表时,Excalidraw AI 是不二之选
  • 将网页转为 Markdown 文档,Jina AI Reader 能完美保留原始排版结构
Read more »

【本文由 Claude 3.7 辅助编写】

Git 仓库

1. MCP 协议简介

Model Context Protocol (MCP) 是一个开放协议,旨在标准化应用程序如何为大型语言模型 (LLMs) 提供上下文。MCP 类似于 AI 应用中的 USB-C 接口,提供了一种标准化的方式,将 AI 模型连接到不同的数据源和工具。

为什么需要 MCP?

MCP 帮助用户在 LLMs 之上构建代理和复杂的工作流。LLMs 经常需要与数据和工具集成,MCP 提供了以下支持:

  • 预建集成:LLM 可以直接插入的预建集成列表。
  • 灵活性:在不同 LLM 提供商和供应商之间切换的灵活性。
  • 最佳实践:在基础设施内保护数据的最佳实践。

核心架构

MCP 采用客户端-服务器架构,主机应用程序可以连接到多个服务器:

  • MCP 主机:如 Claude Desktop、IDE 或 AI 工具,希望通过 MCP 访问数据。
  • MCP 客户端:与服务器保持 1:1 连接的协议客户端。
  • MCP 服务器:通过标准化 Model Context Protocol 暴露特定功能的轻量级程序。
  • 本地数据源:MCP 服务器可以安全访问的计算机文件、数据库和服务。
  • 远程服务:MCP 服务器可以通过互联网连接的外部系统(如 API)。

2. 使用 fastmcp 框架实现 MCP Server

fastmcp 是一个用于快速构建 MCP 工具服务器的框架。让我们看看如何使用它实现一个简单的工具服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { FastMCP } from "fastmcp";
import { z } from "zod";

// 创建MCP服务器实例
const server = new FastMCP({
name: "My Server",
version: "1.0.0",
});

// 添加一个数学计算工具
server.addTool({
name: "add",
description: "Add two numbers",
parameters: z.object({
a: z.number(),
b: z.number(),
}),
execute: async (args) => {
return String(args.a + args.b);
},
});

// 添加一个系统状态查询工具
server.addTool({
name: "system-battery",
description: "Get the current system battery status",
parameters: z.object({}),
execute: async () => {
const command = new Deno.Command(
"C:\\Program Files\\PowerShell\\7\\pwsh.exe",
{
args: [
"-c",
"Get-WmiObject -Class Win32_Battery | Select-Object -Property EstimatedChargeRemaining | ConvertTo-Json",
],
}
);
const output = await command.output();
return new TextDecoder().decode(output.stdout);
},
});

// 启动服务器
server.start({
transportType: "stdio",
});

工具定义的关键要素

  1. 名称 (name): 工具的唯一标识符
  2. 描述 (description): 工具功能的简要说明
  3. 参数模式 (parameters): 使用 zod 定义的参数类型验证规则
  4. 执行逻辑 (execute): 实际执行工具功能的异步函数

FastMCP 使工具服务器的开发变得简单直观。通过定义工具名称、描述、参数模式和执行逻辑,开发者可以快速创建功能丰富的工具集合。服务器通过 stdio 传输方式启动,方便与客户端进行交互。

3. MCP Client 与 OpenAI 接口集成

接下来,我们来看看如何创建 MCP 客户端并将其与 OpenAI 接口集成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { createOpenAI } from "@ai-sdk/openai";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { CoreMessage, Tool, generateText } from "ai";
import { z } from "zod";

// 创建与MCP服务器的通信通道
const transport = new StdioClientTransport({
command: "deno",
args: ["run", "-A", "server.ts"],
});

// 初始化MCP客户端
const client = new Client(
{
name: "example-client",
version: "1.0.0",
},
{
capabilities: {
prompts: {},
resources: {},
tools: {},
},
}
);

// 连接到MCP服务器
await client.connect(transport);

// 获取服务器提供的工具描述
const { tools: tool_descs } = await client.listTools();
const tools: Record<string, Tool> = {};

// 将MCP工具转换为OpenAI可用的Tool格式
for (const tool_desc of tool_descs) {
const parameters: Record<string, z.ZodType> = {};
for (const [name, { type }] of Object.entries(
tool_desc.inputSchema.properties
) as [string, { type: string }][]) {
parameters[name] = type === "number" ? z.number() : z.string();
}

tools[tool_desc.name] = {
description: tool_desc.description,
parameters: z.object(parameters),
execute: async (args) => {
const result = await client.callTool({
name: tool_desc.name,
arguments: args,
});
console.log(`Tool ${tool_desc.name} executed with result:`, result);
return result.content[0].text;
},
};
}

// 初始化OpenAI客户端
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY,
baseURL: process.env.OPENAI_BASE_URL,
});

// 处理用户查询
async function main() {
const model = openai(process.env.OPENAI_MODEL!);
const messages: CoreMessage[] = [
{ role: "user", content: "系统还有多少电?" },
];

// 使用模型生成文本,可能触发工具调用
const response = await generateText({
model,
tools,
messages,
});

// 处理工具调用和结果
if (response.toolCalls.length > 0) {
// ... 处理工具调用和结果的代码 ...

// 基于工具结果生成最终响应
const { text } = await generateText({
model,
tools,
messages,
});
console.log(text);
}
}

main();

集成过程的关键步骤

  1. 创建传输通道:通过 StdioClientTransport 连接到 MCP 服务器
  2. 初始化客户端:创建 MCP 客户端并连接
  3. 工具映射:将 MCP 工具转换为 OpenAI 可用的 Tool 格式
  4. 模型调用:使用 OpenAI 模型处理用户查询
  5. 工具调用处理:管理模型生成的工具调用和结果
  6. 响应生成:基于工具执行结果生成最终响应

通过这种集成方式,OpenAI 模型可以无缝调用 MCP 服务器提供的工具,实现强大的功能扩展。

4. MCP 协议的未来展望

随着 AI 技术的快速发展,MCP 协议在未来有着广阔的应用前景:

工具生态系统扩展

未来可能会出现专门的 MCP 工具市场,开发者可以分享和使用各种预构建的工具,加速 AI 应用开发。从代码分析工具、数据处理工具到专业领域工具(如金融分析、医疗诊断等),将形成丰富的工具生态系统。

多模态工具支持

MCP 协议可以扩展到支持多模态工具,使模型能够处理和生成图像、音频和视频内容。例如,通过 MCP 协议连接图像生成工具、视频编辑工具等。

安全性增强

未来 MCP 协议可以引入更强大的安全机制,如权限控制、资源限制和调用审计,确保 AI 系统使用工具时的安全性和可控性。

高效工具调用优化

优化工具调用路径和参数传递方式,减少不必要的往返通信,提高工具调用效率。可能会出现智能工具路由和缓存机制,进一步提升性能。

统一标准化

随着更多组织和项目采用 MCP 协议,可能会形成统一的工具描述标准,使不同平台和模型之间的工具更容易共享和互操作。这将大大减少重复开发工作,推动整个行业向前发展。

AI 代理协作系统

未来 MCP 可能成为 AI 代理之间协作的基础设施,使多个 AI 系统能够共享工具和能力,协同解决复杂问题。

结论

MCP 协议为 AI 模型与工具集成提供了一种灵活、标准化的方式。通过 fastmcp 框架,开发者可以轻松构建功能强大的工具服务器;通过 MCP 客户端与 OpenAI 接口集成,可以实现模型与工具的无缝交互。随着 AI 技术的不断发展,MCP 协议有望在工具生态系统、多模态支持、安全性和效率方面取得更多突破,为 AI 应用开发提供更加强大的支持。

通过实际实践 MCP 协议,开发者可以构建更加智能、灵活的 AI 应用,满足各种复杂场景的需求。

Deno 2.2 版本引入了原生的 OpenTelemetry 支持,使得在 Deno 应用中集成分布式追踪变得异常简单。本文将介绍如何使用 Deno 2.2 和 Hono 框架构建一个简单的微服务系统,并通过 OpenTelemetry 实现服务的可观测性。

项目概述

我们构建了一个包含两个服务的简单系统:

  1. API 网关服务 (gateway.ts):负责接收客户端请求,并将其路由到相应的服务。
  2. 天气服务 (weather.ts):提供天气信息查询功能。

此外,我们还实现了一个中间件 (TraceRoute.ts) 和一个模拟的第三方 API 调用 (thirdApi.ts),用于演示如何在服务中进行追踪。

代码实现

API 网关服务 (gateway.ts)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import { Hono } from "@hono/hono";
import { TraceRoute } from "./TraceRoute.ts";

const app = new Hono().basePath("/api");

app.use(TraceRoute());

app
.get("/", (c) => {
return c.text("Hello from the Trees!");
})
.get("/weather/batch-get", async (c) => {
const cities = c.req.queries("city") as string[];
const result = (
await Promise.all(
cities.map(async (city: string) => {
const resp = await fetch(`http://localhost:8001/weather/${city}`);
return await resp.text();
})
)
).join("\n");
return c.text(result);
})
.get("/weather/:city", (c) => {
return fetch(`http://localhost:8001/weather/${c.req.param("city")}`);
});

Deno.serve(app.fetch);

天气服务 (weather.ts)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Hono } from "@hono/hono";
import { TraceRoute } from "./TraceRoute.ts";
import { getWeather } from "./thirdApi.ts";

const app = new Hono();

app.use(TraceRoute());

app.get("/weather/:city", (c) => {
const city = c.req.param("city");
return c.text(getWeather(city));
});

Deno.serve({ port: 8001 }, app.fetch);
Read more »

原文

(由 DeepSeek 辅助翻译)


(警告,这是一篇长文。我有点写嗨了。)

经过一年时间,在许多客户项目中尝试使用 uv,这个由 Astral 推出的新 Python 项目管理工具,我看到了它的优点和不足。

我的结论是:如果你的情况允许,总是先尝试 uv。如果不行,再退回到其他工具。

它是帕累托解决方案,因为比起费劲去弄清楚该用什么工具,uv 更容易上手,而且你很少会后悔。实际上,迁移到 uv 和从 uv 迁移回来的成本都很低,但它带来的价值却相当高。

虽然这篇文章会深入探讨为什么如此,但我们也会专门讨论什么时候你不想使用 uv

不过,这篇文章并不是关于如何使用 uv 的教程。后续会有一篇专门的文章。

尽管我对 uv 充满热情,但我坚持认为,在没有看到它在各种工作场景中的表现之前,我不能轻易推荐它。

这是因为 Python 社区庞大且多样化。有学生、数据科学家、AI 开发者、Web 开发者、系统管理员、生物学家、地理学家、插件作者……他们可能在大学、政府机构、初创公司、军队、实验室或大公司工作。

他们的技能水平、经验、环境和约束各不相同,而工具的普适性越强,我就越能推荐它。

这与 PHP、JS、Java 或 Ruby 的情况非常不同。相对来说,很少有人用 Java 开发 X-plane 插件,用 Ruby 编写 GIS 脚本,用 JS 编写银行定价引擎,或用 PHP 作为最新 LLM 模型的主包装。这些语言虽然也能做到,但我看到 Python 的应用范围更广。

因为我是一名自由职业开发者,同时也是一名培训师,我经常在这些领域游走,而且我见过其他工具在这些场景中惨败的情况。pyenv、poetry、pipenv、pdm、pyflow、pipx、anaconda……

事实上,我的博客之所以开始受欢迎,是因为一篇文章:为什么不告诉人们“简单”地使用 pyenv、poetry、pipx 或 anaconda

所以我不想给人们虚假的希望,推荐一些只在我的小圈子里有效的东西,不幸的是,大多数极客都会这么做

现在,我已经看到了 uv 的使用方式和它可能遇到的问题,我不仅可以告诉你应该使用它,还可以告诉你为什么。

当然,我也会告诉你什么时候不要使用它。

我反复强调过,Python 的引导过程是所有问题的根源。所谓引导,指的是安装 Python 本身,以及配置一个新项目,以便后续安装依赖或构建包。你之后遇到的许多问题(例如打包问题)实际上都源于此。

这是因为:

  • Python 有很多不同的安装方式,每种方式都有不同的默认设置和陷阱。而且这些还因操作系统而异。
  • 光是安装 Python,就需要了解很多前置知识,而 Python 是一门特别适合初学者的语言,而初学者,顾名思义,并不具备这些知识。
  • Python 的应用场景非常广泛,因此很难创建“一个教程适用所有情况”。在公司锁定的 Windows 机器上提供的 Python 体验,与在 Debian 爱好者笔记本电脑上的体验完全不同。
  • 很少有人能给出关于这方面的好建议,但每个人和他们的猫都会以权威的语气谈论它。网上关于这方面的废话实在太多了。
  • 有很多工具试图解决这个问题,因此我们现在面临着选择悖论。
  • PATHPYTHONPATH、糟糕的命名约定、在同一台机器上安装多个 Python 版本、Linux 上的可选包,以及 Python 作为系统依赖项,这些都为你提供了无数种搬起石头砸自己脚的方式。
  • -mpy 在它们的使命中失败了。大多数人甚至不知道它们的存在。
  • 编译扩展的流行给这一切增加了不少乐趣。
  • 人们会遇到直接与这些问题相关的问题,但完全不知道原因,因此他们会直接说“Python 打包太烂了”,因为他们会把问题归咎于他们正在使用的工具,而不是他们根本不知道的根源问题。

因此,一个好的 Python 项目管理工具应该具备以下特性:

  • 独立于 Python 的引导过程,因此不会出现鸡生蛋蛋生鸡的问题,同时也能绕过 PATHPYTHONPATH 问题。
  • 能够在所有平台和情况下以统一的方式安装和运行 Python。
  • 在基础工具(pipvenv)与自身之间提供桥梁。
  • 拥有非常强大的依赖解析器。
  • 让简单的事情变得简单(安装东西),让复杂的事情变得可能(在不同于开发环境的操作系统上安装锁定依赖)。
  • 所有这些都要易于安装和使用,当然,还要足够可靠,让你放心地将它用于你技术栈中最重要的部分之一。
Read more »

(由DeepSeek R1辅助编写)

问题背景

挑战分析

在实现基于 OpenAI 流式 API 的对话系统时,面临两个核心挑战:

  1. 长时操作风险:openai接口生成长文本需要 10-30 秒,客户端网络波动可能导致连接中断
  2. 数据一致性要求:用户发送的消息与 AI 的完整响应必须保证原子性持久化

传统同步处理模式存在致命缺陷,在客户端连接中断时会导致消息丢失:

1
2
3
4
5
6
7
8
9
10
sequenceDiagram
participant Client
participant Server
participant OpenAI

Client->>Server: POST /chat
Server->>OpenAI: 流式请求
OpenAI-->>Server: 数据流
Server-->>Client: 流式响应
Note over Client,Server: 若此时客户端断开连接<br/>未持久化的数据将丢失

架构设计

使用异步 Worker 执行实际请求并通过消息队列通信

方案描述

该方案通过异步任务和消息队列实现了 OpenAI API 流式响应的持久化和可靠传输。具体步骤如下:

  1. 客户端请求:客户端发送 POST 请求到 Web 服务器,创建对话任务。
  2. 异步任务:Web 服务器将任务委派给 异步 Worker,立即返回任务 ID 给客户端。
  3. 流式处理:Worker 向 OpenAI 发起流式请求,实时处理响应数据。
  4. 数据持久化:每个响应片段同时写入数据库和 Redis 消息队列,确保数据安全。
  5. 消息推送:Web 服务器通过 SSE 将消息队列中的数据推送给客户端,实现流式响应。
  6. 断连恢复:客户端可根据任务 ID 重新连接,获取未接收的历史消息。

该方案解决了长时操作风险和数据一致性问题,确保在客户端断连情况下数据不丢失,并支持断线重连和消息恢复。

Read more »

(由 DeepSeek 辅助翻译)

你是否曾觉得你的 Python 代码可以更优雅或更高效?装饰器可能是你正在寻找的改变游戏规则的工具。装饰器可以看作是一种特殊的修饰符,它们包裹在你的函数周围,以最小的努力添加功能。

这些强大的工具可以改变你的函数和类的行为,而无需修改其核心代码。Python 自带了一些内置的装饰器,可以提高你的代码质量、可读性和性能。

在本文中,我们将介绍一些 Python 中最实用的内置装饰器,你可以在日常开发中使用它们——用于优化性能、创建更简洁的 API、减少样板代码等等。这些装饰器大多属于 Python 内置的 functools 模块。

▶️ 你可以在 GitHub 上找到所有代码。

1. @property - 干净的属性访问

@property 装饰器将方法转换为属性,允许你在保持干净接口的同时添加验证逻辑。

在这里,我们创建了一个 Temperature 类,其中包含 celsiusfahrenheit 属性,它们会自动处理单位之间的转换。当你设置温度时,它会执行验证以防止物理上不可能的值(低于绝对零度)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Temperature:
def __init__(self, celsius=0):
self._celsius = celsius

@property
def celsius(self):
return self._celsius

@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("Temperature below absolute zero!")
self._celsius = value

@property
def fahrenheit(self):
return self._celsius * 9/5 + 32

@fahrenheit.setter
def fahrenheit(self, value):
self.celsius = (value - 32) * 5/9

getter 和 setter 工作得非常顺畅,因此访问 temp.celsius 实际上会调用一个方法,但接口感觉就像一个常规属性。

输出:

1
2
3
temp = Temperature()
temp.celsius = 25 # 带有验证的干净属性式访问
print(f"{temp.celsius}°C = {temp.fahrenheit}°F")
Read more »

【由腾讯元宝辅助翻译】

文章来源:https://rafiqul.dev/blog/fastapi-deconstructed-anatomy-of-modern-asgi-framework

发布时间:2024-11-19T15:32:14.000Z


最近,我有机会在 PyCon APAC 2024 上深入探讨 FastAPI 的内部机制。演讲的标题是“FastAPI 解密:现代 ASGI 框架的剖析”。随后,我想到为什么不将这次演讲的内容写成文字呢?于是,我决定写一篇博客文章。以下就是这篇文章。

你可以在这里找到演讲的幻灯片:https://github.com/shopnilsazal/fastapi-deconstructed

注意: 为了更好地查看图表,请使用浅色模式阅读本文。


FastAPI 迅速成为 Python 开发者首选的框架之一,尤其是在需要高性能和开发者友好的 API 框架时。凭借对异步编程、依赖注入和自动生成 OpenAPI 文档的支持,FastAPI 以其速度和易用性脱颖而出。本文将分解 FastAPI 的核心组件,详细说明从 ASGI 和 Uvicorn 到 Starlette 和 Pydantic 的各个部分如何协同工作,构建出一个强大且现代的 Web 框架。

Hello World

让我们从 FastAPI 应用程序的基础开始。在 FastAPI 中,一个“Hello World”示例非常简单。

1
2
3
4
5
6
7
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def hello():
return {"message": "Hello, World!"}

通过这样一个简单的设置,FastAPI 可以处理以下任务:

  • 定义异步路由。
  • 解析和验证请求。
  • 序列化 JSON 响应。
  • 自动生成 API 文档。

我们可以通过以下方式运行这个应用程序:

1
uvicorn main:app
1
hypercorn main:app
1
granian --interface asgi main:app

可以看到,有多种方式可以运行我们的应用程序。关键在于,我们需要一个符合 ASGI 协议的服务器来运行应用程序。我们可以使用任何实现 ASGI 协议的服务器。但为了简单起见,在本文中我将使用 uvicorn 作为 ASGI 服务器的示例来解释相关内容。


构建模块

FastAPI 的功能建立在多个强大的组件之上:

  1. ASGI:异步协议层,负责处理服务器与应用程序之间的通信。
  2. Uvicorn:一个高性能的 ASGI 服务器,用于运行 FastAPI 应用程序。
  3. Starlette:一个 ASGI 框架,提供路由、中间件和请求/响应处理功能。
  4. Pydantic:用于数据验证和解析的库,FastAPI 使用它来确保数据的一致性和可靠性。
  5. 依赖注入:内置的依赖注入系统,使得注入数据库连接、服务或配置等依赖变得非常容易。
  6. 自动 API 文档:自动生成 OpenAPI 规范,提供详细的文档和交互功能。
Read more »

(本文由ChatGPT辅助编写)

来源: GitHub Copilot Chat Explained: The Life of a Prompt

GitHub Copilot 在 VS Code 中为开发者提供了强大的 AI 编程助手功能。它通过两种主要功能:内联建议Copilot Chat,帮助开发者更高效地编写代码。在与 Copilot Chat 互动时,GitHub Copilot 会通过一系列复杂的步骤处理你的请求,从本地工作区扫描到与 OpenAI 语言模型的交互。以下是 GitHub Copilot 工作流的详细解析。

GitHub Copilot 工作流

当开发者在 VS Code 中启动 Copilot Chat 并输入带有 @workspace 的问题时,Copilot 会进行以下处理:

  1. 本地上下文收集:Copilot 扩展会检查你的本地工作区,找到与问题相关的代码文件或片段。
  2. 请求发送:通过 HTTPS 协议将请求发送到 Copilot 代理服务器,经过加密处理确保安全。
  3. AI 处理:代理服务器将请求转发至后端的 OpenAI 模型,模型根据上下文生成代码建议或解释。
  4. 响应返回:经过处理的响应返回到 Copilot 扩展,开发者可以在 VS Code 中看到结果。
Read more »

(本文由ChatGPT辅助编写)

随着大型语言模型(LLM)的广泛应用,将网页内容转换为干净、结构化的文本格式已成为数据预处理的重要环节。2024 年 4 月,Jina AI 正式发布了 Jina Reader(https://jina.ai/reader),该 API 通过在 URL 前添加特定前缀,即可将任意网页转换为对 LLM 更友好的 Markdown 格式。随后,在同年 9 月,Jina 又推出了两款专门用于 HTML 转 Markdown 的小型语言模型—— reader-lm-0.5breader-lm-1.5b。而在最新版本中,Jina 又正式发布了拥有 15 亿参数的 ReaderLM-v2,它不仅能精确转换 HTML 为格式美观的 Markdown,还可以直接生成 JSON 数据,实现了更高的准确性和长文本处理能力(支持高达 512K tokens 的输入输出组合)。

1. Jina Reader API 与 ReaderLM-v2 简介

1.1 背景与发展历程

  • Jina Reader API:只需在目标 URL 前添加 https://r.jina.ai/ 前缀,即可自动抓取网页并转换为清洁的文本格式。这一方式无需复杂配置或 API 密钥,操作简单、响应迅速。
  • 小型语言模型:初期发布的 reader-lm-0.5breader-lm-1.5b 专注于 HTML 到 Markdown 的转换任务,但在长文本处理和复杂格式转换上存在一定局限。
  • ReaderLM-v2:作为第二代模型,ReaderLM-v2 在准确性、长文本支持以及多语言适配方面都有显著提升。它不仅能输出高质量的 Markdown,还能直接生成结构化 JSON 数据,方便后续数据提取和 LLM 调用[citeturn0search11]。

1.2 技术亮点

  • 高准确性:通过全新的训练策略和对比损失,ReaderLM-v2 能够避免在生成长序列时出现重复或循环问题,确保输出内容的连贯性和准确性。
  • 多语言支持:支持包括中文、英文、日语、韩语、法语等 29 种语言,满足全球化应用需求。
  • 扩展性:除了 Markdown 转换,还能直接生成 JSON 数据,为特定领域的数据提取提供便捷接口。

2. 技术原理与工作流程

Jina Reader API 通过以下几个关键步骤实现 HTML 到 Markdown 的转换:

  1. 网页抓取与解析
    利用代理服务抓取目标网页内容,通过 HTML 解析器构建 DOM 树,提取网页的主要文本、标题、列表、代码块、表格等结构信息,同时自动过滤掉冗余的样式、脚本和广告信息。

  2. 内容清洗与结构化
    在提取原始内容后,利用正则表达式和启发式规则对文本进行清洗,保留语义关键部分,并根据 HTML 结构转换为符合 Markdown 语法的文本格式。ReaderLM-v2 甚至支持通过指令方式定制输出,例如提取特定部分的内容或生成符合预定义 JSON Schema 的结构化数据。

  3. 输出转换
    用户可以通过 API 请求直接获得 Markdown 格式的输出,或通过指定参数生成 JSON 数据,便于后续处理或直接供 LLM 进行调用。

3. 实践示例:转换 Python 3.13 新特性文档

下面以 Python 3.13 的新特性文档为例,演示如何使用 Jina Reader API 将 HTML 转换为 Markdown 文件。假设目标 URL 为 https://docs.python.org/3/whatsnew/3.13.html,只需在前面添加 https://r.jina.ai/ 前缀即可。

3.1 使用 curl 进行转换

1
2
3
curl "https://r.jina.ai/https://docs.python.org/3/whatsnew/3.13.html" \
-H "x-engine: readerlm-v2" \
-H "Accept: text/event-stream"

上述命令中:

  • x-engine 请求头指定使用 ReaderLM-v2 引擎进行转换;
  • Accept: text/event-stream 启用流式传输模式,适用于处理大型或动态网页内容。

执行后,API 将返回一个干净、结构化的 Markdown 文本,其中保留了原文的标题、段落、列表、代码块等结构信息,去除了 HTML 标签、内联样式以及脚本代码。

3.2 在 Google Colab 中测试

为了方便实验,Jina 官方还提供了 Google Colab Notebook 示例。该 Notebook 展示了如何加载目标网页,调用 ReaderLM-v2 模型进行转换,并输出 Markdown 格式的结果。Notebook 已针对 Colab 的 T4 GPU 进行了优化,适合快速体验和验证转换效果。

4. 应用场景与优势

4.1 优化 LLM 调用

  • 减少 Token 数量:通过转换 HTML 为 Markdown,自动剔除冗余标签和无用内容,从而大幅降低后续 LLM 调用时的 Token 数量,提升调用速度和成本效率。
  • 提升模型理解:干净且结构化的文本更容易被 LLM 理解,有助于提高生成质量和问答准确率。

4.2 数据预处理和信息提取

  • 内容聚合:开发者可以利用该接口批量转换各类网页内容,构建新闻摘要、知识库、学术文献分析等应用。
  • 自动化工作流:结合 Zapier、Notion 等工具,可实现自动采集、转换并存储网页数据,构建企业级的知识管理系统[citeturn0search14]。

4.3 多格式输出

除了 Markdown 格式外,ReaderLM-v2 还支持直接生成 JSON 数据,对于需要进一步数据清洗和结构化处理的场景具有显著优势。

5. 总结与展望

Jina Reader API 及其背后的 ReaderLM-v2 模型为网页内容转换提供了高效、精准的解决方案。从简单地在 URL 前添加前缀,到支持定制化指令和多格式输出,这一工具极大地简化了数据预处理流程。对于后续的 LLM 调用、知识库构建以及自动化工作流而言,都能带来显著的效能提升。

展望未来,Jina AI 将继续优化 ReaderLM 系列产品,计划扩展多模态处理能力(例如图片自动标注、视频摘要等),并持续提升转换速度和稳定性。无论是企业级应用还是个人开发者,都可以借助这一开源工具打造更高效的 AI 系统。


以上就是关于如何使用 Jina.ai 接口将 HTML 转换为 Markdown 文件的详细技术分享。希望这篇博客能为大家在数据预处理、知识库构建和 LLM 应用中提供新的思路与灵感。欢迎在评论区分享你的使用体验和改进建议!


参考资料

原文:https://blog.logrocket.com/working-urls-javascript/
使用ChatGPT协助翻译

URL 是任何 Web 应用的重要组成部分。如果您的应用需要向 API 发送请求,那么构造正确的 URL 就尤为重要。现代浏览器都支持的 URL API,为解析和操作 URL 提供了一种方便的方法。它可以轻松访问 URL 的各个部分。

了解 URL 的组成部分

使用 JavaScript 操作 URL

让我们看以下示例 URL:

1
https://example.com/api/search?query=foo&sort=asc#results

这个 URL 包括以下几个部分:

  • 协议 (Protocol): https
  • 主机 (Host): example.com
  • 路径名称 (Path name): /api/search
  • 查询字符串 (Query string): ?query=foo&sort=asc
  • 哈希 (Hash): #results

通过现代 JavaScript,我们可以轻松解析这些不同的部分。


解析 URL

在支持 URL API 之前,开发者经常使用 <a> 元素解析 URL。例如,提取查询字符串可以这样写:

1
2
3
4
5
function getQueryString(url) {
const link = document.createElement("a");
link.href = url;
return link.search;
}

缺点:

  1. 需要 DOM 环境,因此不能在 Node.js 环境中运行。
  2. 缺乏错误处理,例如传入无效的 URL 时不会抛出错误。

使用 URL API,我们可以更安全、更简单地解析 URL。只需将 URL 传递给 URL 构造函数。如果 URL 是有效的,构造函数会返回一个包含该 URL 各部分属性的对象:

1
2
3
4
const url = new URL("https://example.com/api/search?query=foobar");
console.log(url.host); // example.com
console.log(url.pathname); // /api/search
console.log(url.search); // ?query=foobar
Read more »