使用ClickHouse UDF与OpenAI模型集成

ClickHouse在AI领域的结合应用 通过其强大的数据处理能力和高效的查询性能,ClickHouse为AI技术的应用提供了强有力的支持,帮助企业提升数据处理效率,优化业务流程,提升竞争力。ClickHouse作为一种高性能的列式数据库,能够提供实时的数据处理和分析能力,与AI技术结合,可以实现更高效的数据处理和分析,从而提高AI系统的性能和准确性。无论是高性能的交互分析、灵活的半结构化数据存储,还是与AI引擎的无缝集成,ClickHouse都为用户提供了强大的工具和平台,助力其在数据驱动的智能时代中取得成功。风险管理是金融行业的核心业务之一。 阅读详情

图片

本文字数:14683;估计阅读时间:37 分钟

作者:Dale McDiarmid

审校:庄晓东(魏庄)

本文在公众号【ClickHouseInc】首发

图片

Meetup活动

ClickHouse Shenzhen User Group第1届 Meetup 火热报名中,详见文末海报!

介绍

在ClickHouse中,用户可以直接在其SQL中调用AI模型。这可以在插入数据时丰富数据的形式,或者在查询时补充特定的结果。虽然许多用户习惯于训练自己的领域特定模型,但对于较小的团队或用例,这通常是不切实际的。在这些情况下,预构建的“即插即用”模型或服务通常就足够,并且可以在付出最小努力的情况下获得良好的结果。

在本文中,我们演示了:

  • 如何使用ClickHouse用户定义的函数(UDF)轻松集成第三方API,这些API提供“AI as a Service”

  • 如何在ClickHouse中,直接调用这些“即插即用”模型完成特定任务,如情感分析,并针对这些结果进行聚合,以计算有关给定主题的正面和负面帖子数量等指标

鉴于OpenAI最近的知名度和备受关注的ChatGPT服务,我们以OpenAI为例。然而,这种方法的简单性意味着可以轻松地适应其他AI服务。

用户定义的函数(UDF)

ClickHouse中的UDF(用户定义的函数)有几种形式。在最近的一篇文章中,我们分享了:如何使用ClickHouse SQL定义的函数查询Hugging Face中托管的外部数据集。虽然诸如此类的SQL定义的函数对于概括常见的SQL任务非常有用,但有时用户需要熟悉的编程语言的全部功能。为此,ClickHouse支持可执行的UDF。这为开发人员提供了调用任何外部可执行程序或脚本来处理数据的灵活性。在我们下面的简单示例中,我们将使用这个功能来调用简单的Bash和Python脚本,这些脚本将查询OpenAI API。我们将展示API响应如何自动丰富由ClickHouse插入或查询的数据。

图片

使用OpenAI

大多数用户通过流行的ChatGPT服务熟悉OpenAI,该服务已经改变了工作行为和日常任务。OpenAI为企业提供了访问ChatGPT模型的REST API,以在现有服务和自动化流程中使用。这些服务提供从聊天和嵌入生成到图像生成和语音转文本的所有方式。我们的示例专注于聊天完成,这可以用于更通用的任务,如实体提取和情感标记。

注意:访问OpenAI服务的所有请求都需要一个令牌 - 在下面的示例中作为环境变量OPENAI_API_KEY传递。用户可以注册试用版,并获得足够的免费积分来执行这里的示例。

除了能够充当聊天机器人外,OpenAI的完成(completion)服务还支持其他任务,如情感分析和结构提取。对于这些任务,开发人员必须通过系统角色提供相关说明,以描述期望的行为。执行情感分析的示例REST API请求可能如下所示。在这里,我们要求服务对论坛帖子进行分类。请注意,我们需要提供明确的说明,以仅返回指定情感的单个令牌:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
  "model": "gpt-3.5-turbo",
  "messages": [
  {
    "role": "system",
    "content": "You are an AI language model trained to analyze and detect the sentiment of forum comments."
  },
  {
    "role": "user",
    "content": "Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."
  }
  ],
  "temperature": 0,
  "max_tokens": 256
}'

{
  "id": "chatcmpl-7vOWWkKWGN7McODMXJzQB6zzDcx0r",
  "object": "chat.completion",
  "created": 1693913320,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
  {
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "NEGATIVE"
    },
    "finish_reason": "stop"
  }
  ],
  "usage": {
  "prompt_tokens": 147,
  "completion_tokens": 2,
  "total_tokens": 149
  }
}

请注意,这里我们使用更具成本效益的gpt-3.5-turbo模型,而不是最新的gpt-4模型。前者对于示例目的已足够。我们将其性能水平的评估留给读者。

相同的服务也可以用于提取结构。假设我们希望从上述文本中提取所提到的技术,作为字符串值的列表。我们需要稍微修改一下说明:

curl https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
  "model": "gpt-3.5-turbo",
  "messages": [
  {
    "role": "system",
    "content": "You are an AI language model trained to extract entities from forum comments"
  },
  {
    "role": "user",
    "content": "From the following text extract the many technologies mentioned as a comma seperated list: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."
  }
  ],
  "temperature": 0,
  "max_tokens": 20
}'

{
  "id": "chatcmpl-7vOdLnrZWeax3RxjeUNelCTdGvr8q",
  "object": "chat.completion",
  "created": 1693913743,
  "model": "gpt-3.5-turbo-0613",
  "choices": [
  {
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "BigQuery, Databricks, Spark, ClickHouse"
    },
    "finish_reason": "stop"
  }
  ],
  "usage": {
  "prompt_tokens": 122,
  "completion_tokens": 11,
  "total_tokens": 133
  }
}

关于上述请求参数的一些建议:

  • 我们将temperature设置为0,以从响应中删除任何随机性。对于这些用例,我们不需要创造性的文本,只需要确定性的文本分析。

  • 在两种情况下,我们设置max_tokens以确定响应的长度。一个token大约是3/4个词。因此,我们调整了我们的请求。

数据集

对于我们的示例数据集,我们使用了Hacker News的帖子。这个数据集在我们的公共play环境中可用,包含从2006年到2023年8月的流行Hacker News论坛上的所有帖子和评论,约有3700万行。表模式如下所示。

我们对title和text列感兴趣。我们将探索这个数据集的任务留给读者,如果希望将这个数据集的最新版本加载到你自己的ClickHouse实例中,可以按照这里的说明操作。或者,我们提供了一个在S3上的Parquet文件,可以使用如下所示的s3函数加载:

CREATE TABLE hackernews
(
  `id` UInt32,
  `deleted` UInt8,
  `type` Enum8('story' = 1, 'comment' = 2, 'poll' = 3, 'pollopt' = 4, 'job' = 5),
  `by` LowCardinality(String),
  `time` DateTime,
  `text` String,
  `dead` UInt8,
  `parent` UInt32,
  `poll` UInt32,
  `kids` Array(UInt32),
  `url` String,
  `score` Int32,
  `title` String,
  `parts` Array(UInt32),
  `descendants` Int32
)
ENGINE = MergeTree
ORDER BY id

INSERT INTO hackernews SELECT * FROM s3('https://datasets-documentation.s3.eu-west-3.amazonaws.com/hackernews/2023-08-18.parquet')

添加情感分析

对于我们的示例,假设我们希望为存储在ClickHouse中的Hacker News数据添加情感分析。为此,我们需要通过ClickHouse UDF调用之前的OpenAI REST API。这个请求的简单性意味着:即使是一个简单的bash脚本可能也足够,如下所示(下面需要jq)。稍后,我们将演示如何直接在Python中执行此操作。

#!/bin/bash

while read read_data; do
  sentiment=$(curl -s https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <insert>" \
  -d "{
  \"model\": \"gpt-3.5-turbo\",
  \"messages\": [
      {
      \"role\": \"system\",
      \"content\": \"You are an AI language model trained to analyze and detect the sentiment of forum comments.\"
      },
      {
      \"role\": \"user\",
      \"content\": \"Analyze the following Hacker News comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: ${read_data}\"
      }
  ],
  \"temperature\": 0,
  \"max_tokens\": 2,
  \"temperature\": 0
}" | jq -r '.choices[0].message.content')
  printf "$sentiment";
done

这个脚本应该保存在ClickHouse的user_scripts目录中,命名为sentiment.sh,并设置为可执行。还应该在一个文件openai_functions.xml中添加以下条目,并保存到ClickHouse配置目录(通常是/etc/clickhouse-server/)。

<functions>
       <function>
           <name>sentiment</name>
           <type>executable</type>
           <format>TabSeparated</format>
           <return_type>String</return_type>
           <argument>
             <type>String</type>
           </argument>
           <command>sentiment.sh</command>
           <command_read_timeout>10000</command_read_timeout>
           <command_write_timeout>10000</command_write_timeout>
           <max_command_execution_time>10000</max_command_execution_time>
       </function>
</functions>

这个配置使得UDF可用于ClickHouse。除了在这里修改超时以允许OpenAI请求的延迟之外,我们提供了一个函数名sentiment,并指定了输入和返回类型。

有了上述配置,用户可以通过简单的函数调用请求文本片段的情感,例如:

SELECT sentiment('Learn about the key differences between ClickHouse Cloud and Snowflake and how ClickHouse Cloud outperforms Snowflake across the critical dimensions for real-time analytics: query latency and and cost.') AS sentiment

┌─sentiment─┐
│ POSITIVE  │
└───────────┘

1 row in set. Elapsed: 0.433 sec.

虽然上面的例子可以让我们开始,但可能需要一个更健壮的解决方案,具有错误处理的功能。为此,我们可能希望将上述内容转换为Python。下面的Python脚本添加了基本的错误处理和带有回退的重试。后者是为了特别解决OpenAI速率限制的挑战 - 请参阅处理延迟和速率限制以获取更多详细信息。

请注意,需要openai和tenacity库来处理API请求和速率限制。

#!/usr/bin/python3
import sys
import openai
from tenacity import (
   retry,
   stop_after_attempt,
   wait_random_exponential,
)

openai.api_key = "<INSERT>"
request_timeout = 3

@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(20))
def completion_with_backoff(**kwargs):
   return openai.ChatCompletion.create(**kwargs)

def extract_sentiment(text):
   if text == "":
       return "NEUTRAL"
   messages = [{"role": "system",
                "content": "You are an AI language model trained to analyze and detect the sentiment of hackernews forum comments."},
               {
                   "role": "user",
                   "content": f"Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. "
                              f"Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: {text}"
               }]
   try:
       response = completion_with_backoff(model="gpt-3.5-turbo", messages=messages, max_tokens=30, temperature=0, request_timeout=request_timeout)
       return response.choices[0].message.content
   except:
       return "ERROR"

for size in sys.stdin:
   # collect a batch for performance
   for row in range(0, int(size)):
       print(extract_sentiment(sys.stdin.readline().strip()))
   sys.stdout.flush()

服务的基于聊天的性质使得在单个请求中评估多个文本片段的情感变得具有挑战性。为了使这些示例保持简单,我们每行进行一次请求。一个更优化的解决方案可能会对请求进行批处理,并要求端点评估一组文本。

上述假设:从ClickHouse传递的任何输入,都包括一个行数的前缀。这用于确定后续输入要迭代的次数。这可以使Python脚本内的操作进行批处理以获得更高的性能。

除了定义唯一名称sentiment_p之外,上述函数的配置还有一些额外的设置。我们将type设置为可执行池,以提高吞吐性能。这将启动命令N次(下面是10次),允许多个并发的调用。设置send_chunk_header确保在任何输入之前有一个表示要处理的行数的数字标题。我们增加了超时设置,以防传递大块的行。

<functions>
    <function>
    <name>sentiment_p</name>
      <type>executable_pool</type>
      <pool_size>10</pool_size>
      <send_chunk_header>true</send_chunk_header>
      <format>TabSeparated</format>
      <return_type>String</return_type>
      <argument>
        <type>String</type>
      </argument>
      <command>sentiment.py</command>
      <command_read_timeout>10000000</command_read_timeout>
         <command_write_timeout>10000000</command_write_timeout>
         <max_command_execution_time>1000000</max_command_execution_time>
    </function>
</functions>

我们可以将上述任何一个函数应用于列的一组行。在下面的示例中,我们请求包含单词ClickHouse的10行的标题和文本的情感。

SELECT text, sentiment_p(text) AS sentiment
FROM hackernews WHERE text LIKE '%ClickHouse%' OR title LIKE '%ClickHouse%'
ORDER BY time DESC
LIMIT 2
FORMAT Vertical
Row 1:
──────
text:    Yeah ClickHouse is definitely the way to go here. Its ability to serve queries with low latency and high concurrency is in an entirely different league from Snowflake, Redshift, BigQuery, etc.
sentiment: POSITIVE

Row 2:
──────
text:    There are other databases today that do real time analytics (ClickHouse, Apache Druid, StarRocks along with Apache Pinot).  I&#x27;d look at the ClickHouse Benchmark to see who are the competitors in that space and their relative performance.
sentiment: POSITIVE

2 rows in set. Elapsed: 2.763 sec. Processed 37.17 million rows, 13.30 GB (13.46 million rows/s., 4.82 GB/s.)

只有在最终结果被整理后,UDF才会执行 - 这意味着只需要两个请求。这种方法是理想的,因为对OpenAI的请求的延迟通常比ClickHouse评估查询的时间要长得多。

进一步地,我们可以通过简单的聚合来计算ClickHouse的正面和负面帖子的数量。这会产生更多的开销,因为我们需要对OpenAI API进行1600多次调用。这反映在最终的计时中。

SELECT
  count(),
  sentiment
FROM hackernews
WHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')
GROUP BY sentiment_p(text) AS sentiment
FORMAT PrettyCompactMonoBlock

┌─count()─┬─sentiment─┐
│   192 │ NEGATIVE  │
│   628 │ NEUTRAL   │
│   857 │ POSITIVE  │
└─────────┴───────────┘

3 rows in set. Elapsed: 203.695 sec. Processed 37.17 million rows, 13.28 GB (182.48 thousand rows/s., 65.21 MB/s.)

处理延迟和速率限制

OpenAI API的实用性受到两个因素的限制:延迟和它施加的速率限制。请注意,这些变量将取决于所选择的“即插即用”模型。在我们的示例中,我们使用OpenAI。还有许多其他选择,每个选择都有其自己的权衡。

延迟将影响查询的最小响应时间。虽然OpenAI允许多个并发查询以确保这不会影响吞吐量,但速率限制将更具限制性。因此,我们建议用户仅将这些API用于自发分析,其中函数仅在结果的小子集上使用(例如我们之前的2行示例),或者在插入时丰富数据。在展示后者的示例之前,让我们探讨一下延迟和速率限制的限制。

我们可以通过修改我们的情感curl请求来使用一个简单的格式文件来评估响应的延迟:

curl -w "@curl-format.txt" -o /dev/null -s  https://api.openai.com/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
  "model": "gpt-3.5-turbo",
  "messages": [
      {
      "role": "system",
      "content": "You are an AI language model trained to analyze and detect the sentiment of forum comments."
      },
      {
      "role": "user",
      "content": "Analyze the following hackernews comment and determine if the sentiment is: positive, negative or neutral. Return only a single word, either POSITIVE, NEGATIVE or NEUTRAL: I can say for BigQuery and Databricks from personal experience.<p>BigQuery is much slower and is much more expensive for both storage and query.<p>Databricks (Spark) is even slower than that (both io and compute), although you can write custom code&#x2F;use libs.<p>You seem to underestimate how heavily ClickHouse is optimized (e.g. compressed storage)."
      }
  ],
  "temperature": 0,
  "max_tokens": 256,
  "temperature": 0
}'

time_namelookup:  0.081196s
time_connect:  0.084907s
time_appconnect:  0.095853s
time_pretransfer:  0.095937s
time_redirect:  0.000000s
time_starttransfer:  0.095942s
----------
time_total:  0.650401s

这里的总延迟为0.65秒,限制了我们的查询响应时间,但由于我们有一个命令池(上面是10),ClickHouse的并行执行管道可以利用它。然而,这种并行化又受到OpenAPI速率限制的限制。

OpenAI受到每分钟请求数和每分钟令牌数的限制。对于我们的gpt-3.5-turbo模型,这是每分钟90,000个令牌(TPM)和每分钟3,500个请求(RPM)。速率限制因模型和帐户类型而异 - 进一步的细节请参阅此处。

为了解决这个问题,我们在我们的UDF中添加了基本的速率限制。API返回头中包含速率限制信息(即下一分钟剩余的令牌数和请求数)。虽然我们可以开发一个使用这些信息的速率限制函数,但OpenAI建议使用几个专为通过指数回退解决此问题而设计的库。这样做的好处是我们不需要跟踪跨多个线程的请求和令牌使用情况。

我们对聚合查询的上述计时(203.695秒)表明,我们可能没有充分利用我们的10个UDF命令池,或者正在受到速率限制的限制。假设平均延迟为0.65 *,完全并行化,我们预计我们的总执行时间在这里更接近100秒(1600/10 * 0.65 = 104秒)。

*我们假设Open AI API可以保持这种延迟,而不受变量内容长度等因素的影响(一些评论可能比其他评论更长)。

这种性能(100秒)之所以没有实现,是因为查询受到OpenAI API的速率限制的限制 - 具体来说是令牌限制。每个Hacker News评论平均约为330个单词,如下所示,或约80个令牌(每个令牌约4个字符)。但这并不包括我们的提示和系统文本,其中还增加了额外的60个令牌。我们的与ClickHouse相关的子集的平均令牌长度也较高,为136。

SELECT
  round(avg(length(text))) AS num_chars,
  round(num_chars * 0.25) AS num_tokens
FROM hackernews

┌─num_chars─┬─num_tokens─┐
│     333 │       83 │
└───────────┴────────────┘

1 row in set. Elapsed: 1.656 sec. Processed 37.17 million rows, 12.72 GB (22.44 million rows/s., 7.68 GB/s.)

SELECT
  round(avg(length(text))) AS num_chars,
  round(num_chars * 0.25) AS num_tokens
FROM hackernews
WHERE (title LIKE '%ClickHouse%') OR (text LIKE '%ClickHouse%')

┌─num_chars─┬─num_tokens─┐
│     546 │      136 │
└───────────┴────────────┘

1 row in set. Elapsed: 1.933 sec. Processed 37.17 million rows, 13.28 GB (19.23 million rows/s., 6.87 GB/s.)
Peak memory usage: 73.49 MiB.

虽然每个评论都需要一个请求,导致总共1600个请求(低于每分钟3500的限制),但我们总共有900k个字符或229k个令牌。考虑到我们的提示文本,这增加到了329k个令牌(每个请求额外增加60个)。这远远超过了每分钟90k的限制。尽管如此,如果这项工作被完美地安排,我们预计这个请求将在我们经历的200秒内完成(329/90〜3.65分钟〜200秒)。

尽管更好的速率限制实现(例如基于通用单元速率算法的实现)可能会更有效地利用Open AI API资源,但请求的延迟最终将受到令牌限制的约束。我们只能使用前N个令牌,其中N的选择基于一个限制,该限制将确保完全利用每分钟3500次的完整请求限制,即90000/3500〜25个令牌。然而,在我们的示例中,这不太可能足以确定情感上述技术。 

在插入时进行提取

鉴于速率限制和延迟,使用API进行查询的更可取的方法是在数据插入时分配情感列。借助其命令池,Python函数更适合进行此类型的批处理处理。下面,在通过INSERT INTO加载行时提取情感。在这个例子中,我们将所有与ClickHouse相关的行插入一个专用表中,为每个计算一个情感列。这种处理方式非常理想,因为新行插入时,Hacker News数据集每分钟接收约8-10行新数据。一旦分配了列,我们就可以在情感列上享受ClickHouse查询速度,而无需进行API请求。

INSERT INTO hackernews_v2 SELECT
  *,
  sentiment_p(text) AS sentiment
FROM hackernews
WHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')

0 rows in set. Elapsed: 185.452 sec. Processed 37.17 million rows, 13.54 GB (200.44 thousand rows/s., 73.00 MB/s.)

SELECT count(), sentiment
FROM hackernews_v2
GROUP BY sentiment

┌─count()─┬─sentiment─┐
│   193 │ NEGATIVE  │
│   850 │ POSITIVE  │
│   634 │ NEUTRAL   │
└─────────┴───────────┘

3 rows in set. Elapsed: 0.003 sec. Processed 1.68 thousand rows, 1.68 KB (531.10 thousand rows/s., 531.10 KB/s.)
Peak memory usage: 72.90 KiB.

提取结构

为了完整起见,让我们也将之前的OpenAI请求转换为提取我们的帖子中的技术。以下是bash Python脚本:

#!/usr/bin/python3
import sys
import openai
from tenacity import (
   retry,
   stop_after_attempt,
   wait_random_exponential,
)

openai.api_key = "<INSERT>"
request_timeout = 3

@retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(20))
def completion_with_backoff(**kwargs):
   return openai.ChatCompletion.create(**kwargs)

def extract_topics(text):
   if text == "":
       return ""
   messages = [{
                   "role": "system",
                   "content": "You are an AI language model trained to extract entities from Hacker News forum comments."},
               {
                   "role": "user",
                   "content": f"From the following text extract the technologies mentioned as a comma separated list with no spaces. Return an empty string if there are no technologies: {text}"
               }]
   try:
       response = completion_with_backoff(model="gpt-3.5-turbo", messages=messages, max_tokens=30, temperature=0,
                                          request_timeout=request_timeout)
       return response.choices[0].message.content.strip()
   except Exception as e:
       return f"ERROR - {e}"

for size in sys.stdin:
   # collect a batch for performance
   for row in range(0, int(size)):
       print(",".join([tech.strip() for tech in extract_topics(sys.stdin.readline().strip()).split(",")]))
   sys.stdout.flush()

配置此函数时,使用与情感UDF相同的参数,只是将名称更改为extract_techs,我们可以在Hacker News上使用ClickHouse识别提到的顶级技术。

WITH results AS (
      SELECT extract_techs(text) as techs
      FROM hackernews
      WHERE (text LIKE '%ClickHouse%') OR (title LIKE '%ClickHouse%')
)
SELECT
    arrayJoin(splitByChar(',', techs)) AS tech,
    count() AS c
FROM results
GROUP BY tech
HAVING tech NOT ILIKE '%ClickHouse%' AND tech != ''
ORDER BY c DESC
LIMIT 5

┌─tech────────┬───c─┐
│ Postgres  │  78 │
│ PostgreSQL  │  65 │
│ SQL       │  63 │
│ TimescaleDB │  54 │
│ MySQL     │  51 │
└─────────────┴─────┘

5 rows in set. Elapsed: 211.358 sec. Processed 37.17 million rows, 13.28 GB (175.87 thousand rows/s., 62.85 MB/s.)
Peak memory usage: 931.95 MiB.

结论

本文展示了如何使用UDF将ClickHouse直接集成到模型提供商,以丰富和添加结构到现有数据中。虽然我们在示例中使用了OpenAI,但类似的“即插即用”模型服务应该同样容易集成。

Meetup 活动报名通知

好消息:ClickHouse Shenzhen User Group第1届 Meetup 已经开放报名了,将于2024年1月6日在深圳南山区海天二路33号腾讯滨海大厦举行,扫码免费报名

图片

​​联系我们

手机号:13910395701

邮箱:Tracy.Wang@clickhouse.com

满足您所有的在线分析列式数据库管理需求

大模型API成本控制实战:从token优化到智能路由 大模型API调用成本高,本质是token消耗失控与链路管理粗放所致。其原理在于计费模型严格按输入输出token总和计量,而提示词冗余、未启用流式响应、错误重试无熔断、缓存缺失语义理解等环节,直接推高单位请求成本。技术价值体现在将API从黑盒调用升级为可监控、可降级、可预算的基础设施,支撑高并发、低延迟、低成本的AI服务规模化落地。典型应用场景包括智能客服、文档摘要、营销文案生成等对响应时效与成本敏感的业务线。本文聚焦prompt压缩、stream启用、分级缓存、成本感知路由四大核心控制点,深度融合token 阅读详情

相关推荐

数据库AI Agent选型实战:PolarDB、ArkClaw与DatabaseClaw深度对比

数据库AI Agent是将自然语言查询转化为可执行SQL的智能中间层,其核心原理在于NL→SQL的语义解析与执行计划协同优化。技术价值体现在降低SQL使用门槛、提升查询准确率、缩短业务决策链路。典型应用场景包括金融实时风控、政务智能填报、电商库存调优等对语义理解与数据库深度集成要求极高的领域。选型关键不在于模型参数或开源属性,而取决于是否支持现有数据库连接池热加载、能否零代码适配业务术语映射,以及Skill可扩展性与内核级rewrite能力——这正是PolarDB Agent Express、ArkClaw

weixin_34337381的博客 324

ClickHouse自定义函数实例教程

通过函数封装复杂代码,可以在多个应用场景中复用通过给定输入参数,可以简化测试修改函数定义自动反应至所有函数调用,避免重复维护UDF可以消除重复工作,虽然强大,也不要过度滥用。

neweastsun的专栏 5378

【信息科学与工程学】计算机科学与自动化-——第十五篇云计算 12 公有云里的“多Region + 多AZ“ 02 运营算法01

算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)算法逐步思考推理思考(含数学方程式、对象、资源、任务、进程/协程/线程及对应的代数、约束、目标函数/传递函数/依赖函数、参数及参数的数值范围及边界条件、逐步推理的数学方程式列表、上下文切换、并发/串行/随机/乱序/顺序)云厂商提高闲置资源利用率。算法复杂度为O(N),N为实例数量。

weixin_49199313的博客 280

ClickHouse UDF编写示例

Clickhouse 22版本的UDF编写示例

hongguo880的博客 2884

单卡调试OpenGait:从分布式到本地的轻量级改造指南

本文为个人开发者和研究者提供了一份详细的OpenGait框架单卡调试指南。针对该框架默认依赖多GPU分布式训练的问题,文章通过分析核心痛点,逐步讲解了如何从环境搭建、绕过分布式初始化陷阱、处理通信后端报错到最终配置与调试,实现从分布式到本地的轻量级改造,帮助读者在单张GPU上高效进行步态识别模型的验证与学习。

weixin_28223453的博客 138

SARScape实战:集成GACOS数据优化InSAR大气校正全流程

本文详细介绍了如何在SARScape软件中集成GACOS数据,以优化InSAR大气校正的全流程。通过实战步骤,从GACOS数据申请、下载、导入,到在单景干涉图和SBAS-InSAR流程中应用,有效剥离大气相位延迟,显著提升形变监测结果的精度与可靠性,实现从“雾里看花”到“拨云见日”的转变。

weixin_28419039的博客 397

Clickhouse自定义UDF函数

加载function,查询是否成功,这里查询的xx要跟xml文件保持一致。需要安装python3环境。

等闲之辈莫等闲的博客 2169

FreeRTOS:卡在configASSERT( ( pxQueue ) )问题的解决

FreeRTOS卡在configASSERT( ( pxQueue ) )问题的解决

qq_42007164的博客 9564

机器学习与AI:ClickHouse中的机器学习与AI应用

1.背景介绍 1. 背景介绍 ClickHouse 是一个高性能的列式数据库,它具有强大的查询速度和实时性能。在大数据场景下,ClickHouse 成为了许多公司的首选数据库。然而,ClickHouse 并不仅仅是一个数据库,它还具有强大的机器学习和AI功能。 在本文中,我们将深入探讨 ClickHouse 中的机器学习和AI应用,揭示其背后的原理和算法,并提供实际的最佳实践和代码示例。我们...

AI天才研究院 1370

LSF调度实战:如何用bsub命令实现多队列资源抢占与公平调度

本文深入探讨了LSF作业调度系统的高级实战技巧,重点解析如何通过配置`lsb.queues`文件与灵活运用`bsub -R`命令,构建一套兼顾效率与公平的多队列资源抢占与调度体系。文章详细介绍了队列优先级设计、公平共享机制、资源感知调度以及抢占策略的实施,帮助集群管理员解决高优先级任务等待、资源分配不均等常见问题,实现计算资源的精细化管理和高效利用。

vvv99的博客 218

【Frida Android】实战篇4:SSL Pinning 证书绑定绕过 Hook 教程(一)

在前两章中,我们学习了中间人抓包与 Hook 抓包的基础方法,这些方法在理想环境下能够有效获取网络请求数据。但在实际的企业级应用中,出于安全防护需求,很多 APP 会启用证书绑定(SSL Pinning)机制。这种机制会让客户端对服务器证书的校验更为严格,导致常规的抓包方法(即使将 BurpSuite/Charles 证书安装到系统信任区)也无法生效。因此,从本章开始,我们将系统学习 SSL Pinning 机制的绕过技术。SSL Pinning(证书绑定)是客户端校验服务器身份的进阶安全机制。

水滴石穿 1610

BAML boundary-udf 深度解析:用 YAML 配置驱动的用户自定义函数计算 LLM 调用成本

boundary-udf 是 BAML 引擎中的一个独立 Rust 库,它提供了一种"配置驱动"的方式来对任意 JSON 输入(例如 OpenAI、Anthropic、Gemini 等 LLM 服务商的 API 响应)做模式匹配并执行自定义公式计算。读完本文,你将掌握其 YAML 配置格式(`match`/`constants`/`returns`/`overrides` 四要素)、基于 Jinj

gitblog_00481的博客 84

把 ABAP SQL 窗口函数讲透:从 OVER 到 LEAD、RANK 与累计分析

ABAP SQL窗口函数在不丢失明细记录的前提下,为每行数据提供组内统计和排名功能。它通过OVER子句定义计算窗口,支持三类函数:聚合型(AVG/SUM等)、排名型(ROW_NUMBER/RANK等)和取值型(LEAD/LAG)。相比GROUP BY会合并多行数据,窗口函数保留原始记录同时附加计算结果,特别适合需要保留明细又要展示统计信息的业务场景,如销售排名、客户分层分析等。语法核心是OVER子句,通过PARTITION BY分组,ORDER BY排序,可灵活定义计算范围。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1273

GPT-5 SQL工程鲁棒性评测:真实生产环境下的安全生成与风险防控

SQL大模型不是万能翻译器,而是需经工程化验证的生产级工具。其核心价值在于语义保真、执行安全与运维可维护性——这决定了生成的SQL能否在Hive/Trino/ClickHouse等非标准引擎中稳定运行,能否正确处理NULL边界、窗口函数精度、LEFT JOIN语义退化等高频故障点。从金融风控到电商宽表,真实故障案例揭示:模型对业务逻辑的敬畏远比语法生成能力更重要。本文聚焦GPT-5家族在企业级SQL工作流中的落地实践,覆盖提示词工程、方言适配、CI/CD审计集成等关键环节,为数据工程师提供可即用的风险防控体

359

第29章:PCL PrincipalCurvatures 曲率估计

PrincipalCurvatures(主曲率估计)是一种用于计算点云表面曲率的算法。曲率描述了曲面局部的弯曲程度,是表面几何特征的重要指标。在点云处理中,估计表面的曲率对于形状分析、物体识别、表面重建等任务非常重要。主曲率是曲面上某一点的最大和最小曲率方向。通过计算点云的主曲率,我们可以获得点云中每个点的局部形状特征。通常情况下,主曲率包括两个主要参数:最大主曲率(最大曲率方向上的曲率)和最小主曲率(最小曲率方向上的曲率)。优点缺点提供了对点云表面局部形状的深入分析。

yumeiguo的博客 213

yolov5-6.0的稀疏化训练、结构化剪枝、微调

YOLOv5的BN剪枝、微调

qq_41920323的博客 4394

GPT-5.5是假消息?厘清GPT-4 Turbo与GPT-4o真实能力边界

大语言模型(LLM)的代际演进并非简单数字递增,而是多维能力持续扩展的过程。当前主流商用模型如GPT-4 Turbo和GPT-4o,虽同属GPT-4系列,但在上下文处理、多模态支持、推理延迟与成本效率等维度存在显著差异。GPT-4 Turbo强化长文本理解与逻辑一致性,适用于法律、金融等高精度场景;GPT-4o则以原生多模态与超低延迟为特征,更适合实时语音交互与跨模态应用。所谓‘GPT-5.5’并无官方依据,实为信息误传或认知偏差所致。技术选型应基于业务漏损率、输入数据流特性与SLA要求,而非虚构代号。本文

weixin_33965305的博客 662

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

从 CHANGELOG 看 Pathway 的演进:连接器生态、数据持久化与 LLM RAG 能力全景解析

Pathway 是面向流处理、实时分析与 LLM/RAG 管线的 Python 增量计算框架。仓库根目录的 [CHANGELOG.md](https://link.gitcode.com/i/e7f7a6649cd8ebc6a29fd7d2dc88446f) 完整记录了该项目从 0.2.0(2023-07-20)到 0.32.1(2026-07-29)及 [Unreleased] 区间的全部版本变

gitblog_00424的博客 645

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Pathway 入门指南:用 Python API + Rust 引擎构建实时流式 ETL 与 RAG 管道

本文基于 Pathway 官方开发者文档首页 [welcome.md](https://link.gitcode.com/i/4b396596cfbd7c5f74819c2eb520d6a0) 展开,系统介绍 Pathway Live Data Framework 的定位、安装方式与全部 11 项核心特性,并结合仓库中的 `pyproject.toml`、Python API 入口与 Rust 引

gitblog_00855的博客 283

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

ClickHouse Java多参UDF

ClickHouse调用java语言编写的多参UDF例程

sleetdream的博客 1759

ClickHouse04-ClickHouse基础数据类型与函数

以下通过与 MySQL 和 PostgreSQL 横向对比一下ClickHouse常见的数据结构:整型、浮点型、布尔型、字符型、时间类型、枚举、空间数据。嵌套数据型、聚合数据型、其他特殊的数据结构。时间日期函数、JSON函数、字符串操作类函数、UDF 用户自定义函数

c_zyer的博客 1952

使用 ClickHouse 的 UDF 解决语义版本的需求

应用版本通常采用语义版本控制(Semantic Versioning),版本格式为 <主版本>.<次版本>.<补丁版本>。我们可以利用正则表达式和 extract 函数来提取任何符合语义版本格式的内容,这样可以从字符串开头获取语义版本。我在 Embrace 工作,我们构建了唯一基于 OpenTelemetry 的用户中心移动应用可观测性解决方案,并使用 ClickHouse 为我们的时间序列分析产品提供支持。将语义版本重写为整数数组后,排序将符合预期,且不同长度的版本也可以正常排序!

ClickHouseDB的博客 1002

clickhouse源码:函数分析和自定义函数UDF

clickhouse函数介绍 clickhouse官方提供了许多的函数,包括常规的数学函数,聚合函数,时间函数,逻辑函数,比较函数等等,关于官方的函数可以在官方文档中查看: 官方文档 当然随着clickhouse的流行,国内也有不少的博主已经开始介绍函数的使用: clickhouse function clickhouse高阶函数 clickhouse详细函数介绍 clickhous...

iceyung的专栏 1万+

ClickHouse与人工智能应用

1.背景介绍 1. 背景介绍 ClickHouse 是一个高性能的列式数据库管理系统,由 Yandex 开发。它主要应用于实时数据处理和分析,具有高速查询和高吞吐量的优势。随着人工智能(AI)技术的发展,ClickHouse 在 AI 领域的应用也越来越广泛。本文将探讨 ClickHouse 与人工智能应用的联系,并深入分析其在 AI 领域的具体应用场景和最佳实践。 2. 核心概念与联系 ...

AI天才研究院 406

使用 ClickHouse MCP 和 CopilotKit 构建智能 AI 应用

在这篇博客中,我们详细介绍了如何使用 ClickHouse MCP Server 与 CopilotKit 构建一款智能应用。

ClickHouseDB的博客 1655

记录一下 clickhouse的java udf 函数实现

主要参考了以下文章,找到的教程使用的是JSONEachRow格式传入数据,我使用的是 TabSeparated注,我的clickhouse是使用 curl https://clickhouse.com/ | sh 的方式下载,./clickhouse install 的方式安装的,目录是默认目录。

weixin_42180058的博客 1735
上一篇: 激发大规模ClickHouse数据加载(2/3)大规模数据加载的加速调优
下一篇: 激发大规模ClickHouse数据加载(3/3)确保加载大规模数据的可靠性
ClickHouseDB
博客等级 码龄3年 1707粉丝 320原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值