返回
RSS ClickHouse Blog AI 逐段翻译 发布 2026-09-11 20:49 收录于 09-12

ClickHouse 发布 SQL 内置 AI Functions(Beta)

DataHot 速览

ClickHouse 推出内置 AI Functions,可在 SQL 引擎中直接调用 LLM 或 embedding 服务,把模型调用变成类似 SUM() 的 SQL 函数。相关功能处于 Beta,按版本逐步加入:26.4 引入 aiGenerate/aiClassify/aiExtract/aiTranslate,26.6 加入 aiEmbed,26.8 加入 aiFilter/aiRedact/aiSimilarity。官方称其目标是“把模型搬到数据旁”,减少将数据抽到外部 RAG、向量库和编排框架的复杂度。ClickHouse Cloud 中无需额外配置,目前 AI Functions 处于 private preview。

为什么值得关注:数据从业者可关注在数仓/OLAP 内直接完成分类、抽取、翻译、embedding 和语义搜索,减少数据搬运与多栈编排;这也体现数据库平台 AI 化趋势。

本文目录 13 节
  1. 在 ClickHouse Cloud 中试用 AI Functions
  2. 我们为什么开发这个
  3. 一个查询中的 AI Functions
  4. Beta 中包含什么
  5. 准备设置(仅 OSS)
  6. 理解你的数据:分类、过滤
  7. 用 SQL 分析,而不是 Python
  8. 重塑你的数据:生成、翻译
  9. 完整的 RAG 循环,在数据库中
  10. 为花费设置上限
  11. 发布前需要了解的事项
  12. 结论
  13. 在 ClickHouse Cloud 中尝试 AI Functions

译文

AI 逐段翻译

ClickHouse 现在有一系列内置的 AI Functions,它们直接从 SQL 引擎调用 LLM 或嵌入提供程序。模型变成了你可以从 SQL 中调用的东西,就像 lower() 或 sum() 一样,并且在你数据已经所在的地方运行。

这些函数目前处于 Beta 阶段,功能正在不断添加和改进。它们在三个版本中陆续推出:aiGenerate()aiClassify()aiExtract()aiTranslate() 在 26.4 中推出,aiEmbed() 在 26.6 中推出,然后 aiFilter()aiRedact()aiSimilarity() 在 26.8 中推出。

在 ClickHouse Cloud 中试用 AI Functions

在 ClickHouse Cloud 中,无需下文提到的任何额外配置——这些函数开箱即用。目前,AI Functions 在 ClickHouse Cloud 中处于私有预览阶段。

加入私有预览

我们为什么开发这个

你的所有数据都已经存放在 ClickHouse 中:日志、产品评论、描述和支持工单。传统的 LLM 工作流(如 RAG)将数据从数据库拉取到单独的栈中运行分类或嵌入任务,然后再将结果推回。这种方法慢、容易出错,并且增加了运维复杂性。

AI Functions 背后的核心思想是将模型移动到数据,而不是将数据移动到模型。由于 ClickHouse 已经存储并可以 搜索向量,完整的 RAG 循环可以在一个系统中运行,而不是在向量数据库、编排框架和单独的 LLM API 之间拼凑起来。

一个简单的例子:

1SELECT aiClassify('I love this product!', ['positive', 'negative', 'neutral']);

响应:

1positive

一个查询中的 AI Functions

简而言之,AI Functions 将复杂的工作流转变为简单的 `SELECT` 查询。

探索 AI Functions

Beta 中包含什么

以下 AI Functions 在 26.8 中可供你使用。文本函数:

  • aiClassify - 使用 LLM 提供程序将给定文本分类为所提供的类别之一。
  • aiExtract - 使用 LLM 提供程序从非结构化文本中提取结构化信息。
  • aiGenerate - 使用 LLM 提供程序根据提示生成自由形式的文本内容。
  • aiTranslate - 使用 LLM 提供程序将给定文本翻译为指定的目标语言。
  • aiFilter - 使用 LLM 提供程序对给定文本评估自然语言条件,并返回适合用于 UInt8 的布尔值(WHEREPREWHEREJOIN ... ON)。
  • aiRedact - 使用 LLM 提供程序检测并脱敏给定文本中的个人身份信息(PII)。

嵌入函数:

  • aiEmbed - 使用配置的 AI 提供程序为给定文本生成嵌入向量。
  • aiSimilarity - 使用配置的嵌入提供程序计算两个文本的语义相似度。

AI Functions 的工作原理是对每个输入(或嵌入函数的一批输入)向配置的提供程序 API 发起远程 HTTP 调用,并将解析后的响应作为原生 ClickHouse 值返回。

准备设置(仅 OSS)

要开始使用 AI Functions,你必须配置两个 命名集合(分别用于文本和嵌入),以存储你的提供程序凭据和配置。

我们建议配置设置 ai_function_text_default_credentialsai_function_embedding_default_credentials,值为命名集合的名称。然后,所有 AI Functions 将自动选取正确的端点。也可以在执行期间覆盖这些设置。

创建带 OpenAI 提供程序凭据的命名集合的示例语句:你需要一个来自 OpenAI 的 API 密钥,一个用于 chat 端点,另一个用于 embedding 端点:

1CREATE NAMED COLLECTION ai_text_credentials AS2    provider ='openai',3    endpoint ='https://api.openai.com/v1/chat/completions',4    model ='gpt-5.6-terra',5    api_key ='sk-...';67-- The embedding functions (`aiEmbed`, `aiSimilarity`) do not read `model` from the named collection.8CREATE NAMED COLLECTION ai_embedding_credentials AS9    provider ='openai',10    endpoint ='https://api.openai.com/v1/embeddings',11    api_key ='sk-...';
注意:任何 OpenAI 兼容的 API(例如 Ollama、LiteLLM)都可以通过设置 provider = 'openai' 并将端点指向你的服务来使用。因此,这也可以与本地模型一起使用。

接下来,配置默认凭据设置:

1SET ai_function_text_default_credentials ='ai_text_credentials';2SET ai_function_embedding_default_credentials ='ai_embedding_credentials';

现在你已准备好运行这些函数。让我们回顾一些示例。

理解你的数据:分类、过滤

以下示例使用 Hacker News 数据集,包含 2800 万行故事和评论,按照该指南中的 Parquet 模式加载。我们关注的列是 titlecommentauthorscoretypetimestamp。确保你遵循上述设置步骤。

aiClassify 接受一个字符串和一个常量标签列表,并准确返回其中一个标签。模型被要求选择一个类别,因此在这里它的创造力有限。

首页标题是一个很好的起点,因为它们很短,可以保持 token 使用量低:

1SELECT2    title,3    aiClassify(title, ['space', 'security', 'databases', 'startups', 'programming', 'other']) AS topic4FROM hackernews5WHERE (type ='story') AND (score <3000) AND (title !='')6ORDERBY score DESC7LIMIT 3 FORMAT Vertical;

响应:

1Row1:2──────3title: SpaceX’s Falcon Heavy successfully launches4topic: space56Row2:7──────8title: Twitter Will Allow Employees to Work at Home Forever9topic: other1011Row3:12──────13title: No Cookie for You14topic: security

由于输出是 String,它可以无缝地与标准 SQL 集成。你可以在子查询中使用 aiClassify,然后对结果进行聚合。对于任何你计划查询多次的内容,将其分类到列中,而不是重新计算。

用 SQL 分析,而不是 Python

这是对高分 Hacker News 故事的主题分解,没有使用一行 Python 计算得出。在旧工作流中,这需要导出、分类任务,然后再加载回 ClickHouse。

探索数据集

aiFilter 返回 UInt8,这意味着它可以直接放入 WHERE,并像任何其他布尔条件一样表现。这个函数最清楚地做了 SQL 以前无法做到的事情。Token 搜索查找包含单词 "database" 的行。aiFilter 查找有人抱怨数据库的行:

1SELECT author, substring(comment, 1, 100) AS snippet 2FROM (3SELECT author, comment 4FROM hackernews5WHERE type ='comment'AND ilike(comment, '%database%') 6  LIMIT 5007)8WHERE aiFilter(comment, 'the author is describing a production incident or outage they experienced') LIMIT 3 FORMAT Vertical;

响应:

1Row1:2──────3author:  0x04snippet: Wow, the database connection ip and dbname were taken from http cookies!56Row2:7──────8author:  AccountCreated9snippet: &gt; The primary MCP database is comprised of9 MongoDB shards10enough said.1112Row3:13──────14author:  tomazzi15snippet: The link goes to "Database Error - Error establishing a database connection" which is kind of intere
注意:由于 AI Function 调用处理速度可能较慢,最好先在子查询中应用便宜的谓词,然后在外部查询中调用 LLM 谓词。

重塑你的数据:生成、翻译

前面的分类示例将文本放入桶中;接下来的两个函数生成新文本。我们使用相同的数据集和与上面相同的设置。

aiGenerate 接受一个提示并返回模型写回的任何内容。在 SQL 上下文中,提示通常使用 concat 从列构建。

Hacker News 评论是一个很好的目标,因为其中许多很长,这是摘要的绝佳候选。在此示例中,我们还使用 params 映射,带有 system_prompttemperature 参数,以保持各行输出形状一致:

1SELECT2    author,3    length(comment) AS original_chars,4    aiGenerate(5        concat('Summarize this Hacker News comment in one sentence: ', comment),6        map('system_prompt', 'You are terse. Reply with one sentence and no preamble.',7'temperature', '0.3',8'max_tokens', '2000'9)10    ) AS summary11FROM hackernews12WHERE type ='comment'AND length(comment) >100013LIMIT 3 FORMAT Vertical;

响应:

1Row1:2──────3author:         0-_-04original_chars: 10765summary:        Some VPN providers have been court-verified to keep no logs, and given their financial incentive to protect their reputation plus mandatory data retention laws in many countries, using a reputable VPN is likely more private than relying on your local ISP.67Row2:8──────9author:         0-_-010original_chars: 142811summary:        The comment shares Our World in Data links comparing COVID-19 confirmed cases, deaths, andcase fatality rates across several countries using7-day rolling averages.1213Row3:14──────15author:         0-_-016original_chars: 133717summary:        The commenter is drawing a parallel to Wim Hof, a man famous for extreme cold endurance feats and the ability to consciously control his immune system through a method combining cold exposure, breathing, and meditation.

你还可以使用一些有趣的模式,例如按组生成一次而不是按行生成一次,类似这样:

1SELECT aiGenerate(2    concat(3'Write a three-bullet digest of what Hacker News was discussing. Titles:\n',4        arrayStringConcat(groupArray(title), '\n')5    )6) AS digest;

aiTranslate接收文本和目标语言,目标语言可以是语言名称或 BCP-47 代码。值得了解的参数是 instructions,它向模型传递风格或方言方面的指导:

1SELECT title, aiTranslate(title, 'Spanish', map('instructions', 'Use polite form. Keep technical terms and product names in English.')) AS title_es 2FROM hackernews3WHERE type ='story'AND score <3000AND title !=''4ORDERBY score DESC LIMIT 3 FORMAT Vertical;

响应:

1Row1:2──────3title:    SpaceX’s Falcon Heavy successfully launches4title_es: El Falcon Heavy de SpaceX se lanza con éxito56Row2:7──────8title:    Twitter Will Allow Employees to Work at Home Forever9title_es: Twitter Permitirá a sus Empleados Trabajar desde Casa para Siempre1011Row3:12──────13title:    No Cookie for You14title_es: Sin Cookie para Ti

由于这两个函数都返回 String,它们可以嵌套使用。例如,先总结一条长评论,再翻译该总结:

1aiTranslate(2 aiGenerate( concat('Summarize in one sentence: ', comment),3            map('system_prompt', 'Reply with one sentence, no preamble.') ),4'es-MX' ) AS resumen;

完整的 RAG 循环,在数据库中

由 aiEmbed 和向量搜索驱动的检索增强生成

ClickHouse AI Functions MDSN-142.jpg

现在每个阶段都可以在 SQL 中执行:

  1. 在写入时使用物化视图中的 aiEmbed() 进行嵌入,这样向量会随着数据写入而填充。
  2. 将数据和嵌入向量存储在一起
  3. 使用向量相似度索引建立索引
  4. 使用 cosineDistance 针对嵌入数据进行检索。
  5. 使用 aiGenerate 基于检索到的上下文生成答案

请注意,aiSimilarity() 是用于临时工作的便捷路径:它在一次调用中嵌入两侧并返回余弦相似度,非常适合语义去重或对几千行数据进行排序。

为花费设置上限

与大多数 ClickHouse 函数不同,AI 函数除了 CPU 周期和内存使用之外,每次调用还有 token 和美元成本。在部署此类函数时,限制每次查询的 token 成本和使用量很可能是首要考虑的问题。为帮助避免失控查询和令人咋舌的 AI 使用账单,我们实现了一组配额设置,可用于限制每次查询的 AI 函数使用量。

以下会话设置用于控制这些配额:

以及一个用于控制达到配额限制时错误行为的设置:ai_function_throw_on_quota_exceeded(默认 1 - 抛出错误)。

上述设置可以这样使用:

1SELECT2    title,3    aiClassify(title, ['space', 'security', 'databases', 'startups', 'programming', 'other']) AS topic4FROM hackernews5WHERE type ='story'AND score >100AND title !=''6LIMIT 50007SETTINGS ai_function_max_api_calls_per_query =100;

文本函数每行发出一个请求,因此调用预算实际上就是行预算。此查询想要 5000 行,但只允许 100 个请求,因此它会停止:

1Code: 290. DB::Exception: AI API call limit reached: 100 calls made, maximum: 100.2This is controlled by the 'ai_function_max_api_calls_per_query' setting. (LIMIT_EXCEEDED)

计数是精确的,因为配额在每次请求分发之前都会检查,所以查询永远不会超出其调用预算。将其设置为 0 会禁用该限制。

Token 配额的工作方式相同,但跟踪的是提供商实际报告的内容,这更接近你实际被计费的内容。总结长 Hacker News 评论是成本高昂的情况,因为整条评论都会进入提示词:

1SELECT2    author,3    aiGenerate(4        concat('Summarize this Hacker News comment in one sentence: ', comment),5        map('system_prompt', 'You are terse. Reply with one sentence and no preamble.',6'temperature', '0.3')7    ) AS summary8FROM hackernews9WHERE type ='comment'AND length(comment) >100010LIMIT 200011SETTINGS12    ai_function_max_input_tokens_per_query =500000,13    ai_function_max_output_tokens_per_query =50000;1415Code: 290. DB::Exception: AI input token limit reached or exceeded: 500642 tokens consumed,16maximum: 500000. This is controlled by the 'ai_function_max_input_tokens_per_query' setting.

注意"达到或超过"。一次调用的 token 成本要等到其响应返回后才知道,因此总量在每个线程上最多可能超出一个在途请求的量。请留出余量,而不是将限制设置为你能承受的精确数字。

中止是正确的默认行为,但并不总是你想要的。在 99% 时停止长时间的分类运行并返回空结果,比返回大部分结果更糟糕。ai_function_throw_on_quota_exceeded = 0 将配额转变为软停止:

1SELECT2    topic,3count() AS stories4FROM (5SELECT aiClassify(title, ['space', 'security', 'databases', 'startups', 'programming', 'other']) AS topic6FROM hackernews7WHERE type ='story'AND score >100AND title !=''8    LIMIT 50009)10WHERE topic !=''11GROUPBY topic12ORDERBY stories DESC13SETTINGS14    ai_function_max_api_calls_per_query =1000,15    ai_function_throw_on_quota_exceeded =0;

超出配额的行会接收该列的默认值,对于 String 来说是空字符串,查询成功。使用 WHERE topic != '' 将它们过滤掉,这样你得到的是部分但真实的聚合结果,而不是异常。

要查看查询实际花费了多少,请从 system.query_log 中读取 profile events:

1SELECT2    ProfileEvents['AIAPICalls']      AS api_calls,3    ProfileEvents['AIInputTokens']   AS input_tokens,4    ProfileEvents['AIOutputTokens']  AS output_tokens,5    ProfileEvents['AIRowsProcessed'] AS rows_processed,6    ProfileEvents['AIRowsSkipped']   AS rows_skipped7FROM system.query_log8WHERE query_id ='hn_classify'AND type ='QueryFinish'9ORDERBY event_time DESC10LIMIT 1 FORMAT Vertical;1112Row1:13──────14api_calls:      100015input_tokens:   2431016output_tokens:  312217rows_processed: 100018rows_skipped:   4000

AIRowsSkipped 是每当 ai_function_throw_on_quota_exceeded = 0 时需要关注的指标,因为它统计的是悄然获得默认值的行数,这些行可能来自配额削减或错误。确定配额大小最便宜的方法是先对 LIMIT 100 样本运行此查询,然后乘以相应倍数。

配置配额时需要记住的几点:

  • 在顶层查询中设置它们。 子查询上的 SETTINGS 子句对于配额设置会被忽略。
  • 它们是每服务器、每查询片段的。在一个执行上下文中,上限是精确的,并且由每个 AI 函数、块和线程共享。分布式查询最多可以在每个分片上分发到该限制,在每个分片上,因此请除以你的分片数量。
  • Token 配额需要提供商报告使用量。OpenAI、Anthropic 和 vLLM 会报告。省略 usage 对象的提供商会使 token 计数器保持为 0,因此这些限制永远不会触发,你应该改用 ai_function_max_api_calls_per_query 来限制它们。
  • 嵌入函数从不产生补全 token,因此输出 token 限制不适用于 aiEmbedaiSimilarity
  • 重试会计入调用配额ai_function_max_retries 默认为 1,因此如果提供商返回瞬时错误,1000 的预算覆盖的是 1000 次尝试尝试,而不是 1000 行。

发布前需要了解的事项

在将此功能投入生产时,请牢记这些顾虑和限制:

  • 提示词注入:输入文本会引导模型,因此请将输出视为不可信,绝不要将其输入到生成的 SQL 或 shell 命令中。
  • 非确定性:相同的行输入到 LLM 会得到不同的答案,因此请使用 temperature = 0,并考虑物化结果而不是重新计算它们。
  • 成本: 成本和延迟随行数增长,因此请始终先用 LIMIT 测试,并利用上述配额设置
  • 安全性:将 remote_url_allow_hosts 限制为你的提供商,保持端点在 HTTPS 上,并记住提供商在 TLS 终止后以明文看到你的数据。

结论

AI Functions 将分类、翻译、嵌入和生成放到了 ClickHouse 世界中的 SQL 地图上。完整的 RAG 循环现在可以在数据已经所在的地方运行。期待听到你如何基于此功能构建你的应用。

在 ClickHouse Cloud 中尝试 AI Functions

AI Functions 在 ClickHouse Cloud 中处于私有预览阶段。

加入私有预览

这篇内容对你有用吗?

反馈只用于改善内容筛选,不等同于收藏

分享这条资讯
分享海报
保存图片
iOS 也可以长按图片保存