0%

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 »

Mixtral AI 推出的 AI 聊天助手Le Chat具备 Canvas 功能,支持交互式代码编辑。我利用此功能开发了一款网页绘画应用,代码已托管于 GitHub 并部署在 Vercel 平台。

paint app

通过实践,我总结了以下经验与技巧:

  1. 明确需求: 清晰具体地描述需求,以确保 AI 准确响应。

  2. 分步实施: 将项目拆分为小任务,逐步引导 AI 完成,保障项目流畅进行。

  3. 及时反馈: 在项目进程中持续向 AI 提供反馈,促进其不断优化解决方案。

  4. 善用搜索: 结合在线资源,对比 AI 答案,整合解决方案以获得更佳效果。

GitHub 仓库
应用演示
对话历史

(本文由腾讯混元模型和ChatGPT辅助编写)

在本篇博客中,我们将探讨如何在Docker环境中部署一个基于PyTorch和Transformers库的AI模型,用于图像描述生成。我们将使用一个简单的Flask应用作为后端服务,并通过Docker容器化该应用,以便于部署和管理。

项目概述

本项目实现了一个图像描述生成功能,用户可以通过POST请求上传图片,服务器将返回对应的图像描述。项目代码仓库为duyixian1234/itt

关键技术栈

  • Python: 主要编程语言
  • Flask: 轻量级Web框架
  • PyTorch & Transformers: 深度学习框架和预训练模型库
  • Docker: 容器化技术,用于部署和管理应用

推理代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from flask import Flask, request
from PIL import Image
from transformers import BlipForConditionalGeneration, BlipProcessor

processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base")
model = BlipForConditionalGeneration.from_pretrained(
"Salesforce/blip-image-captioning-base"
)
print("Model loaded")

app = Flask(__name__)


@app.post("/recognize")
def recognize():
file = request.files["file"]
raw_image = Image.open(file.stream).convert("RGB")
inputs = processor(raw_image, return_tensors="pt")
out = model.generate(**inputs, max_new_tokens=256)
return processor.decode(out[0], skip_special_tokens=True)
Read more »