2024年8月

image

快速上手

在本快速入门指南中,我们将安装 Quickwit,创建一个索引,添加文档,最后执行搜索查询。本指南中使用的所有 Quickwit 命令都在
CLI 参考文档
中进行了记录。

使用 Quickwit 安装程序安装 Quickwit

Quickwit 安装程序会自动为您的环境选择正确的二进制归档文件,然后在您的工作目录中下载并解压它。
此方法仅适用于
某些操作系统/架构
,并且您还需要安装一些
外部依赖项

curl -L https://install.quickwit.io | sh
cd ./quickwit-v*/
./quickwit --version

现在您可以根据您的环境将这个可执行文件目录移动到合适的位置,并可能将其添加到您的
PATH
环境变量中。

使用 Quickwit 的 Docker 镜像

您还可以在隔离的 Docker 容器中拉取和运行 Quickwit 二进制文件。

# Create first the data directory.
mkdir qwdata
docker run --rm quickwit/quickwit --version

如果您使用的是基于 Apple Silicon 的 macOS 系统,您可能需要指定平台。您也可以安全地忽略 jemalloc 的警告。

docker run --rm --platform linux/amd64 quickwit/quickwit --version

Start Quickwit server

CLI

./quickwit run

Docker

docker run --rm -v $(pwd)/qwdata:/quickwit/qwdata -p 127.0.0.1:7280:7280 quickwit/quickwit run

提示:您可以使用环境变量
RUST_LOG
来控制 Quickwit 的详细程度。

通过访问
UI 地址 http://localhost:7280
或使用 cURL 发送简单的 GET 请求来检查其是否正常工作:

curl http://localhost:7280/api/v1/version

创建您的第一个索引

在向 Quickwit 添加文档之前,您需要使用一个 YAML 配置文件创建一个索引。此配置文件特别允许您定义如何将输入文档映射到索引字段以及这些字段是否应该被存储和索引。请参阅
索引配置文档

让我们创建一个配置为接收 Stackoverflow 帖子(问题和答案)的索引。

# First, download the stackoverflow dataset config from Quickwit repository.
curl -o stackoverflow-index-config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/stackoverflow/index-config.yaml

索引配置定义了三个字段:
title

body

creationDate

title

body

索引化和分词
的,并且它们也被用作默认搜索字段,这意味着如果您的查询不针对特定字段,它们将用于搜索。
creationDate
作为每条记录的时间戳。没有更多的显式字段定义,因为我们使用默认的动态
模式
:未声明的字段仍然会被索引,默认情况下启用了快速字段以支持聚合查询,并且使用
raw
分词器处理文本。

以下是完整的配置:

#
# Index config file for stackoverflow dataset.
#
version: 0.7

index_id: stackoverflow

doc_mapping:
  field_mappings:
    - name: title
      type: text
      tokenizer: default
      record: position
      stored: true
    - name: body
      type: text
      tokenizer: default
      record: position
      stored: true
    - name: creationDate
      type: datetime
      fast: true
      input_formats:
        - rfc3339
      fast_precision: seconds
  timestamp_field: creationDate

search_settings:
  default_search_fields: [title, body]

indexing_settings:
  commit_timeout_secs: 30

现在我们可以使用以下命令创建索引:

CLI

./quickwit index create --index-config ./stackoverflow-index-config.yaml

CURL

curl -XPOST http://127.0.0.1:7280/api/v1/indexes --header "content-type: application/yaml" --data-binary @./stackoverflow-index-config.yaml

检查是否已创建目录
./qwdata/indexes/stackoverflow
,Quickwit 将在此处写入索引文件和包含
索引元数据

metastore.json
文件。
现在您已经准备好填充索引了。

让我们添加一些文档

Quickwit 可以从许多
来源
索引数据。我们将使用新行分隔的 JSON
NDJSON
数据集作为我们的数据源。
让我们下载
一批 Stackoverflow 帖子(10,000条)

NDJSON
格式并对其进行索引。

# Download the first 10_000 Stackoverflow posts articles.
curl -O https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json

CLI

# Index our 10k documents.
./quickwit index ingest --index stackoverflow --input-path stackoverflow.posts.transformed-10000.json --force

CURL

# Index our 10k documents.
curl -XPOST "http://127.0.0.1:7280/api/v1/stackoverflow/ingest?commit=force" --data-binary @stackoverflow.posts.transformed-10000.json

一旦
ingest
命令完成,您就可以开始使用以下
search
命令查询数据:

CLI

./quickwit index search --index stackoverflow --query "search AND engine"

CURL

curl "http://127.0.0.1:7280/api/v1/stackoverflow/search?query=search+AND+engine"

它应该返回 10 条结果。现在您已经准备好使用搜索 API 进行操作了。

执行搜索查询

让我们从对字段
title
的查询开始:
title:search AND engine

curl "http://127.0.0.1:7280/api/v1/stackoverflow/search?query=title:search+AND+engine"

相同的请求可以用 JSON 查询表达:

curl -XPOST "http://localhost:7280/api/v1/stackoverflow/search" -H 'Content-Type: application/json' -d '{
    "query": "title:search AND engine"
}'

这种格式更冗长,但它允许您使用更多高级功能,例如聚合。以下查询查找此数据集中问题中最常用的标签:

curl -XPOST "http://localhost:7280/api/v1/stackoverflow/search" -H 'Content-Type: application/json' -d '{
    "query": "type:question",
    "max_hits": 0,
    "aggs": {
        "foo": {
            "terms":{
                "field":"tags",
                "size": 10
            }
        }
    }
}'

在尝试不同的查询时,请查看服务器日志以了解发生了什么。

不要忘记正确编码查询参数以避免出现错误请求(状态码 400)。

清理

让我们通过删除索引来做一些清理工作:

CLI

./quickwit index delete --index stackoverflow

REST

curl -XDELETE http://127.0.0.1:7280/api/v1/indexes/stackoverflow

恭喜!您可以继续以下教程来探索 Quickwit 的所有特性。

TLDR

在 Quickwit 的安装目录中运行以下命令。

curl -o stackoverflow-index-config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/stackoverflow/index-config.yaml
./quickwit index create --index-config ./stackoverflow-index-config.yaml
curl -O https://quickwit-datasets-public.s3.amazonaws.com/stackoverflow.posts.transformed-10000.json
./quickwit index ingest --index stackoverflow --input-path ./stackoverflow.posts.transformed-10000.json --force
./quickwit index search --index stackoverflow --query "search AND engine"
./quickwit index delete --index stackoverflow

下一步教程

安装

Quickwit 编译为一个单一的二进制文件,我们提供了多种安装方法:

先决条件

Quickwit 官方仅支持 Linux。FreeBSD 和 MacOS 虽然不是官方支持的,但应该也能正常工作。

Quickwit 提供了 x86-64 和 aarch64 的二进制文件。不需要特殊指令集,但在 x86-64 上推荐使用 SSE3。
对于 aarch64 的支持目前还是实验性的。

下载

version: 0.8.1 -
Release notes
-
Changelog
License:
AGPL V3
Downloads
.tar.gz
:


GitHub
上详细了解可用的构建版本。

注意外部依赖

Quickwit 正常工作依赖于以下外部库:

  • libssl
    :行业标准加密库。
    这些库可以通过本机包管理器安装在您的系统上。
    您可以使用以下命令安装这些依赖项:

Ubuntu

apt-get -y update && apt-get -y install libssl

AWS Linux

yum -y update && yum -y install openssl

Arch Linux

pacman -S openssl

另外,编译它还需要一些额外的依赖项。这些依赖项在生产系统上不是必需的:

  • clang
    :用于编译某些依赖项。
  • protobuf-compiler
    :用于编译 protobuf 定义。
  • libssl-dev
    :libssl 的头文件。
  • pkg-config
    :用于定位 libssl。
  • cmake
    :用于构建 librdkafka,以支持 kafka。
    这些依赖项也可以通过本机包管理器安装在您的系统上。
    您可以使用以下命令安装这些依赖项:

Ubuntu

apt install -y clang protobuf-compiler libssl-dev pkg-config cmake

AWS Linux

yum -y update && yum -y install clang openssl-devel pkgconfig cmake3
# amazonlinux only has protobuf-compiler 2.5, we need something much more up to date.
wget https://github.com/protocolbuffers/protobuf/releases/download/v21.9/protoc-21.9-linux-x86_64.zip
sudo unzip protoc-21.9-linux-x86_64.zip -d /usr/local
# amazonlinux use cmake2 as cmake, we need cmake3
ln -s /usr/bin/cmake3 /usr/bin/cmake

Arch Linux

pacman -S clang protobuf openssl pkg-config cmake make

安装脚本

要在您的机器上轻松安装 Quickwit,只需从您首选的 shell 运行以下命令。
该脚本会检测架构,然后为机器下载正确的二进制存档。

curl -L https://install.quickwit.io | sh

此脚本所做的只是下载适用于您机器的正确二进制存档,并将其提取到当前工作目录中。这意味着您可以从
GitHub
下载与您的操作系统架构匹配的任何所需的存档,并手动将其提取到任何位置。

安装或解压后,所有 Quickwit 的安装文件都可以在一个名为
quickwit-{version}
的目录中找到,其中
version
是对应的 Quickwit 版本。此目录具有以下布局:

quickwit-{version}
    ├── config
    │   └── quickwit.yaml
    ├── LICENSE_AGPLv3.0.txt
    ├── quickwit
    └── qwdata
  • config/quickwit.yaml
    : 默认配置文件。
  • LICENSE_AGPLv3.0.txt
    : 许可证文件。
  • quickwit
    : Quickwit 可执行二进制文件。
  • qwdata/
    : 默认的数据目录。

使用 Docker 镜像

如果您使用 Docker,这可能是最快捷的启动方式之一。
以下命令将从
Docker Hub
拉取镜像并启动一个容器,准备执行 Quickwit 命令。

docker run --rm quickwit/quickwit --version

# If you are using Apple silicon based macOS system you might need to specify the platform.
# You can also safely ignore jemalloc warnings.
docker run --rm --platform linux/amd64 quickwit/quickwit --version

要全面了解这一点,请参阅
快速入门指南

使用 Grafana 查看 Logs 和 Traces

在本教程中,我们将使用 Docker Compose 设置一个展示 Quickwit 追踪信息的 Grafana 仪表板。

只需几分钟时间即可让 Grafana 与 Quickwit 配合工作并构建有意义的仪表板。

创建 Docker Compose 配方

让我们添加一个启用了 OTLP 服务的
Quickwit 实例

version: '3.0'
services:
  quickwit:
    image: quickwit/quickwit
    environment:
      QW_ENABLE_OPENTELEMETRY_OTLP_EXPORTER: "true"
      OTEL_EXPORTER_OTLP_ENDPOINT: "http://localhost:7281"
    ports:
      - 7280:7280
    command: ["run"]

然后我们创建一个带有
Quickwit 数据源
插件的
Grafana
服务。

  grafana:
    image: grafana/grafana-oss
    container_name: grafana
    ports:
      - "${MAP_HOST_GRAFANA:-127.0.0.1}:3000:3000"
    environment:
      GF_INSTALL_PLUGINS: https://github.com/quickwit-oss/quickwit-datasource/releases/download/v0.3.1/quickwit-quickwit-datasource-0.3.1.zip;quickwit-quickwit-datasource
      GF_AUTH_DISABLE_LOGIN_FORM: "true"
      GF_AUTH_ANONYMOUS_ENABLED: "true"
      GF_AUTH_ANONYMOUS_ORG_ROLE: Admin

保存并运行配方:

$ docker compose up

您应该能够通过
http://localhost:7280/
访问 Quickwit 的用户界面,以及通过
http://localhost:3000/
访问 Grafana 的用户界面。

配置数据源

在 Grafana 中,前往
数据源
。如果插件安装正确,您应该能够在列表中找到 Quickwit。

我们将设置一个新的 Quickwit 数据源,用于查看 Quickwit 自身的 OpenTelemetry 追踪信息,让我们使用以下参数配置数据源:

  • URL:
    http://quickwit:7280/api/v1
    这使用了 Docker 服务名称作为主机
  • 索引 ID:
    otel-traces-v0_7

保存并测试,您应该会收到确认消息,表明数据源已正确设置。

image

您还可以设置一个新的 Quickwit 数据源,用于查看 Quickwit 自身的 OpenTelemetry 日志(或您自己的日志索引),让我们使用以下参数配置数据源:

  • URL:
    http://quickwit:7280/api/v1
    这使用了 Docker 服务名称作为主机
  • 索引 ID:
    otel-logs-v0_7

创建仪表板

然后您可以
创建一个新的仪表板
并添加可视化组件:在这里您应该可以选择追踪信息的 Quickwit 数据源。

Quickwit 会发送自身的追踪信息,因此您应该已经有数据可供显示。让我们配置一些面板!

  • 一个表格,统计
    span_name
    的数量
    • Panel type
      :Table
    • Query

    • Metric
      :Count
    • Group by
      :Terms :
      span_name
      : 按 Count 排序
  • 一个柱状图,展示每小时 tantivy 搜索的数量:
    • Panel type
      :Time Series
    • Query

      span_name:tantivy_search
    • Metric
      :Count
    • Group by
      :Date Histogram :
      span_start_timestamp_nanos
      : 间隔 1 小时
  • 一个柱状图,展示过去 6 小时内每小时 ERROR 日志的数量:
    • Panel type
      :Bar Chart
    • Query

      service_name:quickwit AND events.event_attributes.level:ERROR
    • Metric
      :Count
    • Group by
      :Terms :
      span_start_timestamp_nanos
      : 间隔 1 小时
  • 在同一个柱状图上再添加一个查询,展示 WARN 日志的数量

结果

这是您的第一个仪表板可能的样子:

image

使用 Jaeger 查看 Traces

在这个快速入门指南中,我们将使用 Docker Compose 设置一个 Quickwit 实例,并使用 Jaeger 分析其自身的跟踪记录。

您只需要一分钟就能让 Jaeger 与 Quickwit 存储后端一起工作。

启动 Quickwit 和 Jaeger

让我们使用
docker compose
并采用以下配置:

version: "3"

services:
  quickwit:
    image: quickwit/quickwit:${QW_VERSION:-0.8.1}
    volumes:
      - ./qwdata:/quickwit/qwdata
    ports:
      - 7280:7280
    environment:
      - QW_ENABLE_OPENTELEMETRY_OTLP_EXPORTER=true
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:7281
    command: ["run"]

  jaeger-query:
    image: jaegertracing/jaeger-query:1.52
    ports:
      - 16686:16686
    environment:
      - SPAN_STORAGE_TYPE=grpc-plugin
      - GRPC_STORAGE_SERVER=quickwit:7281
      - GRPC_STORAGE_TLS=false

如您在 docker compose 文件中所见,Quickwit 被配置为将其自身的跟踪记录
OTEL_EXPORTER_OTLP_ENDPOINT
发送到自身
http://localhost:7281

另一方面,Jaeger 被配置为使用 gRPC 存储服务器
quickwit:7281

保存并运行配置:

$ docker compose up

您应该能够在
http://localhost:7280/
访问 Quickwit 的 UI,并在
http://localhost:16686/
访问 Jaeger 的 UI。

在 Jaeger 中搜索和查看跟踪记录

Quickwit 生成了许多跟踪记录,让我们来看看其中的一些:

  • find_traces
    :由 Jaeger “查找跟踪记录” 按钮生成。
  • get_operations
    :由 Jaeger 在获取操作列表时生成。
  • get_services
    :由 Jaeger 在获取服务列表时生成。
  • ingest-spans
    :当 Quickwit 通过 gRPC OTLP API 接收 span 时生成。
  • ...

以下是搜索和跟踪视图的截图:

image

image

使用 Quickwit UI 搜索跟踪记录

您还可以使用位于
http://localhost:7280
的 Quickwit UI 来搜索跟踪记录。

这里有一些查询示例:

  • service_name:quickwit AND events.event_attributes.level:INFO
  • span_duration_millis:>100
  • resource_attributes.service.version:v0.8.1
  • service_name:quickwit

就这样!您可以通过以下教程深入了解所有 Quickwit 功能。

下一步教程

本地索引日志数据集

在本指南中,我们将在本地机器上对大约 2000 万条日志条目(解压缩后 7 GB)进行索引。如果您想在 AWS S3 上启动带有多个搜索节点的服务器,请参阅
分布式搜索教程

这里是一个日志条目的示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  },
  "tenant_id": 58
}

安装

让我们下载并安装 Quickwit。

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

或者在隔离的 Docker 容器中拉取并运行 Quickwit 二进制文件。

docker run quickwit/quickwit --version

启动 Quickwit 服务器

CLI

./quickwit run

Docker

docker run --rm -v $(pwd)/qwdata:/quickwit/qwdata -p 127.0.0.1:7280:7280 quickwit/quickwit run

如果您使用的是基于 Apple silicon 的 macOS 系统,可能需要指定平台,使用
--platform linux/amd64
标志。您也可以安全地忽略 jemalloc 的警告。

创建索引

让我们创建一个配置好的索引来接收这些日志。

# First, download the hdfs logs config from Quickwit repository.
curl -o hdfs_logs_index_config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/hdfs-logs/index-config.yaml

索引配置定义了五个字段:
timestamp

tenant_id

severity_text

body
,以及一个 JSON 字段用于嵌套值
resource.service
。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了
default_search_fields

tag_fields

timestamp_field

timestamp_field

tag_fields
由 Quickwit 用于查询时的
分片剪枝
,以提高搜索速度。
有关更多详细信息,请参阅
索引配置文档

version: 0.7

index_id: hdfs-logs

doc_mapping:
  field_mappings:
    - name: timestamp
      type: datetime
      input_formats:
        - unix_timestamp
      output_format: unix_timestamp_secs
      fast_precision: seconds
      fast: true
    - name: tenant_id
      type: u64
    - name: severity_text
      type: text
      tokenizer: raw
    - name: body
      type: text
      tokenizer: default
      record: position
    - name: resource
      type: json
      tokenizer: raw
  tag_fields: [tenant_id]
  timestamp_field: timestamp

search_settings:
  default_search_fields: [severity_text, body]

现在让我们使用
create
子命令创建索引(假设您位于 Quickwit 安装目录内):

CLI

./quickwit index create --index-config hdfs_logs_index_config.yaml

cURL

curl -XPOST http://localhost:7280/api/v1/indexes -H "content-type: application/yaml" --data-binary @hdfs_logs_index_config.yaml

现在您可以填充索引了。

索引日志

数据集是一个压缩的
NDJSON 文件

我们不是先下载再索引数据,而是使用管道直接将解压缩的流发送给 Quickwit。
这可能需要长达 10 分钟的时间,正好适合休息一下喝杯咖啡。

CLI

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz | gunzip | ./quickwit index ingest --index hdfs-logs

Docker

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz | gunzip | docker run -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs

如果您赶时间,可以使用包含 10,000 条文档的样本数据集,我们将使用这个数据集进行示例查询:

CLI

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | ./quickwit index ingest --index hdfs-logs

Docker

在 macOS 或 Windows 上:

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | docker run -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs --endpoint http://host.docker.internal:7280

在 Linux 上:

curl https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json | docker run --network=host -v $(pwd)/qwdata:/quickwit/qwdata -i quickwit/quickwit index ingest --index hdfs-logs --endpoint http://127.0.0.1:7280

cURL

wget https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants-10000.json
curl -XPOST http://localhost:7280/api/v1/hdfs-logs/ingest -H "content-type: application/json" --data-binary @hdfs-logs-multitenants-10000.json

您可以检查是否正在工作,方法是在
severity_text
字段中搜索
INFO

CLI

./quickwit index search --index hdfs-logs  --query "severity_text:INFO"

Docker

在 macOS 或 Windows 上:

docker run -v $(pwd)/qwdata:/quickwit/qwdata quickwit/quickwit index search --index hdfs-logs  --query "severity_text:INFO" --endpoint http://host.docker.internal:7280

在 Linux 上:

docker run --network=host -v $(pwd)/qwdata:/quickwit/qwdata quickwit/quickwit index search --index hdfs-logs  --query "severity_text:INFO" --endpoint http://127.0.0.1:7280

ingest
子命令会生成包含 500 万条文档的
分片
。每个分片是一个小型索引的表示,其中保存了索引文件和元数据文件。

https://quickwit.io/docs/overview/architecture

查询返回的 JSON 结果:

{
  "num_hits": 10000,
  "hits": [
    {
      "body": "Receiving BP-108841162-10.10.34.11-1440074360971:blk_1073836032_95208 src: /10.10.34.20:60300 dest: /10.10.34.13:50010",
      "resource": {
        "service": "datanode/03"
      },
      "severity_text": "INFO",
      "tenant_id": 58,
      "timestamp": 1440670490
    }
    ...
  ],
  "elapsed_time_micros": 2490
}

索引配置显示我们可以使用时间戳字段参数
start_timestamp

end_timestamp
并从中受益于时间剪枝。
在幕后,Quickwit 只会查询包含在这个时间范围内的日志的
分片

让我们使用这些参数与以下查询:

curl 'http://127.0.0.1:7280/api/v1/hdfs-logs/search?query=severity_text:INFO&start_timestamp=1440670490&end_timestamp=1450670490'

清理

让我们做一些清理工作,删除索引:

CLI

./quickwit index delete --index hdfs-logs

cURL

curl -XDELETE http://127.0.0.1:7280/api/v1/indexes/hdfs-logs

恭喜!您完成了这个教程!

要继续您的 Quickwit 之旅,请参阅
分布式搜索教程
或深入研究
搜索 REST API

查询语言

使用 AWS Lambda 进行搜索

在本教程中,我们将使用 Quickwit Lambda 对位于 AWS S3 上的大约 2000 万条日志条目(解压缩后 7 GB)进行索引和搜索。

具体来说,我们将部署一个包含 Quickwit Lambda 的 AWS CloudFormation 栈,以及两个存储桶:一个暂存存储桶用于存放待索引的 gzip 压缩的新行分隔 JSON 文件,另一个存储桶用于存放索引数据。暂存存储桶是可选的,因为 Quickwit 索引器可以从它有访问权限的任何 S3 文件读取数据。

image

安装

安装 AWS CDK

我们将使用
AWS CDK
来编写基础设施自动化脚本。使用
npm
安装它:

npm install -g aws-cdk

您还需要在 shell 中正确配置 AWS 凭证。一种方法是使用
凭证文件

最后,克隆 Quickwit 仓库:

git clone https://github.com/quickwit-oss/tutorials.git
cd tutorials/simple-lambda-stack

设置 Python 环境

我们使用 Python 3.10 来定义需要部署的 AWS CloudFormation 栈,并使用 Python CLI 调用 Lambda 函数。
让我们安装这些必要的包(boto3, aws-cdk-lib, click, pyyaml)。

# Install pipenv if needed.
pip install --user pipenv
pipenv shell
pipenv install

下载 Quickwit Lambda 函数

mkdir -p cdk.out
wget -P cdk.out https://github.com/quickwit-oss/quickwit/releases/download/aws-lambda-beta-01/quickwit-lambda-indexer-beta-01-x86_64.zip
wget -P cdk.out https://github.com/quickwit-oss/quickwit/releases/download/aws-lambda-beta-01/quickwit-lambda-searcher-beta-01-x86_64.zip

初始化并部署

配置您想要部署栈的 AWS 区域和
账户 ID

export CDK_ACCOUNT=123456789
# us-east-1 is where the Quickwit public dataset bucket is located
export CDK_REGION=us-east-1

如果此区域/账户对尚未通过 CDK 初始化,则运行:

cdk bootstrap aws://$CDK_ACCOUNT/$CDK_REGION

这将初始化一些基本资源以托管 Lambda 包等工件。现在我们可以部署栈:

cdk deploy -a cdk/app.py

索引 HDFS 日志数据集

这里是一个数据集中日志条目的示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  },
  "tenant_id": 58
}

如果您有 5 分钟的时间,您可以索引整个数据集,该数据集可在我们的公共 S3 存储桶上获取。

python cli.py index s3://quickwit-datasets-public/hdfs-logs-multitenants.json.gz

一旦启动索引 Lambda 函数,您就不能手动停止它。键盘中断只会停止客户端而不会停止函数。如果您尝试再次运行它,可能会遇到
TooManyRequestsException
错误。这是因为索引器的并发数被设置为 1,以避免在元存储上出现竞态条件。

如果您不想等待,只需索引包含 10,000 个文档的数据集:

python cli.py index s3://quickwit-datasets-public/hdfs-logs-multitenants-10000.json

执行搜索查询

让我们从对字段
severity_text
的查询开始,查找错误:
severity_text:ERROR

python cli.py search '{"query":"severity_text:ERROR"}'

如果索引了整个数据集,它应在不到 1 秒内响应并返回 345 条中的 10 条结果。如果您索引了前 10,000 个文档,则不会有结果,尝试查询
INFO
级别的日志。

现在我们执行一个更高级的查询:一个日期直方图,同时对
severity_text
字段进行术语聚合:

python cli.py search '{ "query": "*", "max_hits": 0, "aggs": { "events": { "date_histogram": { "field": "timestamp", "fixed_interval": "30d" }, "aggs": { "log_level": { "terms": { "size": 10, "field": "severity_text", "order": { "_count": "desc" } } } } } } }'

它应在不到 2 秒内响应并返回每 30 天的日志级别排名。

清理

首先,您需要删除在 S3 存储桶上创建的文件。
完成后,您可以删除栈。

cdk destroy -a cdk/app.py
rm -rf cdk.out

恭喜!您完成了这个教程!您可以继续深入学习以下教程,了解 Quickwit 的所有功能。

下一步

基于 AWS S3 的分布式搜索

在本指南中,我们将使用 EC2 实例对位于 AWS S3 上的大约 4000 万条日志条目(解压缩后 13 GB)进行索引,并启动一个三节点分布式搜索集群。

日志条目示例:

{
  "timestamp": 1460530013,
  "severity_text": "INFO",
  "body": "PacketResponder: BP-108841162-10.10.34.11-1440074360971:blk_1074072698_331874, type=HAS_DOWNSTREAM_IN_PIPELINE terminating",
  "resource": {
    "service": "datanode/01"
  },
  "attributes": {
    "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
  }
}

在使用 Quickwit 和对象存储之前,请查看我们关于在 AWS S3 上部署的
建议
,以避免月底出现一些不愉快的意外。

https://quickwit.io/docs/operating/aws-costs

首先,让我们创建一个 EC2 实例,安装 Quickwit 二进制文件,并按照
配置指南
配置它,以便 Quickwit 可以访问您的 S3 存储桶。此实例将用于索引我们的数据集(请注意,如果您的本地机器有权在 AWS S3 上读写,您也可以从本地机器索引数据集)。

安装

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

使用 S3 配置 Quickwit

让我们定义想要存储索引的 S3 路径。

export S3_PATH=s3://{path/to/bucket}/indexes

您需要为给定的存储桶包含必要的授权,这可以通过设置
AWS_ACCESS_KEY_ID

AWS_SECRET_ACCESS_KEY
环境变量来完成,或者通过 AWS 凭证文件。通常位于
~/.aws/credentials

更多信息请参阅
我们的 AWS 配置指南

https://quickwit.io/docs/guides/aws-setup

现在我们可以创建一个 Quickwit 配置文件。

# Create Quickwit config file.
echo "version: 0.7
node_id: searcher-1
listen_address: 0.0.0.0
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
" > config.yaml

您也可以直接传递环境变量:

# config.yaml
node_id: searcher-1
listen_address: 0.0.0.0
version: 0.7
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}

现在我们准备好启动 Quickwit 了。

./quickwit run --config config.yaml

创建索引

# First, download the hdfs logs config from Quickwit repository.
curl -o hdfs_logs_index_config.yaml https://raw.githubusercontent.com/quickwit-oss/quickwit/main/config/tutorials/hdfs-logs/index-config.yaml

索引配置定义了五个字段:
timestamp

tenant_id

severity_text

body
,以及一个 JSON 字段用于嵌套值
resource.service
。我们本可以在这里使用对象字段并维护一个固定的模式,但为了方便起见,我们将使用 JSON 字段。
它还设置了
default_search_fields

tag_fields

timestamp_field

timestamp_field

tag_fields
由 Quickwit 用于查询时的
分片剪枝
,以提高搜索速度。
有关更多详细信息,请参阅
索引配置文档

version: 0.7

index_id: hdfs-logs

doc_mapping:
  field_mappings:
    - name: timestamp
      type: datetime
      input_formats:
        - unix_timestamp
      output_format: unix_timestamp_secs
      fast_precision: seconds
      fast: true
    - name: tenant_id
      type: u64
    - name: severity_text
      type: text
      tokenizer: raw
    - name: body
      type: text
      tokenizer: default
      record: position
    - name: resource
      type: json
      tokenizer: raw
  tag_fields: [tenant_id]
  timestamp_field: timestamp

search_settings:
  default_search_fields: [severity_text, body]

我们现在可以使用
create
子命令创建索引。

./quickwit index create --index-config hdfs_logs_index_config.yaml

此步骤也可以在您的本地机器上执行。
create
命令会在本地创建索引,然后将 json 文件
metastore.json
上传到您的存储桶
s3://path-to-your-bucket/hdfs-logs/metastore.json

索引日志

数据集是一个压缩的
NDJSON 文件

我们不是分别下载和索引数据,而是使用管道将解压缩的流直接发送给 Quickwit。

wget https://quickwit-datasets-public.s3.amazonaws.com/hdfs-logs-multitenants.json.gz
gunzip -c hdfs-logs-multitenants.json.gz | ./quickwit index ingest --index hdfs-logs

8GB 的内存足以索引这个数据集;像
t4g.large
这样的实例,具有 8GB 内存和 2 个 vCPU,在不到 10 分钟内就索引了这个数据集(前提是您有一些 CPU 信用)。

此步骤也可以在您的本地机器上完成。
ingest
子命令会本地生成每个包含 1000 万条文档的
分片
,并将它们上传到您的存储桶。具体来说,每个分片是一组索引文件和元数据文件。

您可以使用
search
子命令检查是否正在工作,并在
severity_text
字段中查找
ERROR

./quickwit index search --index hdfs-logs --query "severity_text:ERROR"

这将返回 JSON 结果:

{
  "num_hits": 345,
  "hits": [
    {
      "attributes": {
        "class": "org.apache.hadoop.hdfs.server.datanode.DataNode"
      },
      "body": "RECEIVED SIGNAL 15: SIGTERM",
      "resource": {
        "service": "datanode/16"
      },
      "severity_text": "ERROR",
      "tenant_id": 51,
      "timestamp": 1469687755
    },
    ...
  ],
  "elapsed_time_micros": 522542
}

您可以看到此查询有 345 个命中。在这种情况下,第一次运行时服务器在 523 毫秒内响应。
后续运行使用缓存的元存储,并可以在不到 100 毫秒内解决。

既然我们已经索引了日志并且可以从一个实例进行搜索,现在是时候配置并启动另外两个实例以形成集群了。

启动另外两个实例

Quickwit 需要一个端口
rest.listen_port
用于通过 TCP 提供 HTTP REST API 服务以及通过 UDP 维护集群形成。
此外,它还需要
{rest.listen_port} + 1
用于实例之间的 gRPC 通信。

在 AWS 中,您可以创建一个安全组来分组这些入站规则。请参阅我们 AWS 配置指南的
网络部分

为了简化操作,让我们创建一个安全组,打开 TCP/UDP 端口范围 [7200-7300]。
接下来,使用之前创建的安全组创建三个 EC2 实例。记下每个实例的公共 IP 地址。

现在 ssh 登录到第一个 EC2 实例,安装 Quickwit,并按照
环境配置
让 Quickwit 访问索引 S3 存储桶。

让我们在第二个和第三个 EC2 实例上安装 Quickwit。

curl -L https://install.quickwit.io | sh
cd quickwit-v*/

并配置环境,使实例能够形成集群:

export S3_PATH=s3://{path/to/bucket}/indexes
export IP_NODE_1={first-ec2-instance-public-ip}
# configuration for our second node
echo "version: 0.7
node_id: searcher-2
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
listen_address: 0.0.0.0
peer_seeds:
  - ${IP_NODE_1} # searcher-1
" > config.yaml

# Start a Quickwit searcher.
./quickwit run --service searcher --config config.yaml
# configuration for our third node
echo "version: 0.7
node_id: searcher-3
listen_address: 0.0.0.0
peer_seeds:
  - ${IP_NODE_1} # searcher-1
metastore_uri: ${S3_PATH}
default_index_root_uri: ${S3_PATH}
" > config.yaml

# Start a Quickwit searcher.
./quickwit run --service searcher --config config.yaml

您将在终端看到确认实例已加入现有集群的信息。例如这样的日志:

2023-03-19T16:44:56.918Z  INFO quickwit_cluster::cluster: Joining cluster. cluster_id=quickwit-default-cluster node_id=searcher-2 enabled_services={Searcher} gossip_listen_addr=0.0.0.0:7280 gossip_advertise_addr=172.31.30.168:7280 grpc_advertise_addr=172.31.30.168:7281 peer_seed_addrs=172.31.91.203:7280

现在我们可以直接向其中一个实例发出 http 请求,查询节点的 REST API 端点。

curl -v "http://0.0.0.0:7280/api/v1/hdfs-logs/search?query=severity_text:ERROR"

检查所有实例的日志,您会看到所有节点都在工作。

负载均衡传入请求

现在您有了一个搜索集群,理想情况下,您希望负载均衡外部请求。
这可以通过添加 AWS 负载均衡器来快速实现,使其监听传入的 HTTP 或 HTTPS 流量并转发到目标组。
现在您可以随意操作您的集群,随机终止进程,添加/移除新实例,并保持冷静。

清理

让我们做一些清理工作,删除索引:

./quickwit index delete --index hdfs-logs

同时记得删除安全组以保护您的 EC2 实例。如果您不再需要这些实例,可以直接删除它们。

恭喜!您完成了这个教程!

要继续您的 Quickwit 之旅,请查阅
搜索 REST API 参考

查询语言参考

介绍 Quickwit 的查询语言

Quickwit 允许您使用一种简单的查询语言在已索引的文档上进行搜索。下面是一个快速概述。

子句

这种语言的主要概念是子句,它表示一个可以针对文档进行测试的简单条件。

查询字段

一个子句作用于您的文档的字段上。它的语法如下:

field:condition

例如,当搜索包含
tantivy

app_name
字段的文档时,您可以写出如下子句:

app_name:tantivy

在许多情况下,字段名称可以省略,这时 Quickwit 会使用为索引配置的
default_search_fields

条件子句速查表

Quickwit 支持多种类型的子句来表达不同种类的条件。这里有一个快速概述:

type syntax examples description default_search_field
term field:token app_name:tantivy
process_id:1234
word
term 子句检测字段中的某个值是否存在 yes
term prefix field:prefix* app_name:tant*
quick*
term 子句检测字段中的某个令牌是否以提供的值开头 yes
term set field:IN [token token ..] severity:IN [error warn] term 集合子句检测字段中的令牌集合中是否包含任何一个提供的值 yes
phrase field:"sequence of tokens" full_name:"john doe" phrase 子句检测提供的令牌序列是否存在于字段中 yes
phrase prefix field:"sequence of tokens"* title:"how to m"* phrase 前缀子句检测一个令牌序列是否存在,其中最后一个令牌的匹配方式与前缀子句相同 yes
all * * 匹配所有子句将匹配所有文档 no
exist field:* error:* 存在子句检测字段是否存在任何值,只有当字段存在时才会匹配 no
range field:bounds duration:[0 TO 1000}
last_name:[banner TO miller]
range 子句检测字段中的某个令牌是否在提供的范围内 no

查询

结合查询

可以使用布尔运算符
AND

OR
来组合子句,从而创建更复杂的搜索表达式。
AND
查询仅在运算符两侧的条件都满足时才匹配。

type:rose AND color:red

OR
查询在运算符两侧任一条件或两个条件都满足时匹配。

weekday:6 OR weekday:7

如果没有提供运算符,默认隐含为
AND

type:violet color:blue

组合查询

可以通过使用括号来组合子句构建复杂的表达式。

(type:rose AND color:red) OR (type:violet AND color:blue)

当没有使用括号时,
AND
的优先级高于
OR
,这意味着下面的查询等同于上面的查询。

type:rose AND color:red OR type:violet AND color:blue

否定查询

可以通过使用运算符
NOT
或者在查询前加上破折号
-
来否定一个表达式。

NOT

-
的优先级高于其他运算符,因此
-a AND b
意味着
(-a) AND b
,而不是
-(a AND b)

NOT severity:debug

or

type:proposal -(status:rejected OR status:pending)

更深入了解

如果您想了解更多关于查询语言的内容,请参阅
查询语言参考

更多

1.
Binance 如何使用 Quickwit 构建 100PB 日志服务(Quickwit 博客)

背景

Terraform是一款开源的Cli工具,网上的很多文章都是单机安装一个然后创建个目录就去操作云资源;如果在高可用的前提,如何将Terraform cli变成一个嵌入运维流程的一个组件?不仅仅是人编写tf模板然后去apply?

自动化的驱动Terraform,无非包含这几个步骤:

  • 初始化Terraform
  • 填充资源模板
  • apply资源
  • show资源

初始化Terraform

创建一个云资源目录,如cloudxxx-test001
云资源的目录下需要有Terrafor的Provider信息,以及实例声明信息。
创建好了模板文件,就需要初始化Terraform,以及下载Provider插件,建议提前下载好插件到指定的目录,使用容器可以直接打到镜像里
这样初始化直接指定plugin地址:

/usr/local/bin/terraform init -plugin-dir=/Users/lixiangli/.terraform.d/plugins

注意:确保插件地址内有你声明的插件版本

由于Terraform apply是不支持选择apply哪个资源,因此上面的实现方式可以发现,一个目录是放一个云资源。为了让每次操作的影响范围是可控的。这种方式会带来一个问题,就是state的文件存储也必须是隔离的,否则出现的情况是apply 资源cloudxxx-test001时 cloudxxx-test002会被直接删除。

模板文件生成

通过代码的方式去驱动Terraform, 无法避免的一步就是生成所对应的云资源的模板文件,我们这边使用golang,所以找到需要对接的云的Provider的文档然后定义成如下:

resource "ucloud_disk" "ucloud_disk_{{ .ObjectMeta.UID }}" {
  availability_zone = "{{ .Spec.Zone }}"
  name              = "{{ .Spec.InstanceName }}"
  disk_size         = "{{ .Spec.InstanceSize }}"
  disk_type         = "{{ .Spec.InstanceType }}"
  charge_type       = "{{ .Spec.ChargeType }}"
}

在程序运行时动态填充这些模板即可

选择合适的状态存储

Terraform是个有状态的组件,如果部署多个实例的话,官方默认的state文件的模式必然是无法满足需求的。
所以我们这边选择的是etcdv3
配置如下:

terraform {
  required_providers {
    ucloud = {
      source = "ucloud/ucloud"
      version = "~>1.23.0"
    }
  }
  backend "etcdv3" {
    endpoints = ["http://127.0.0.1:2379/"]
    lock      = true
    prefix    = "/terraform-state/clouddisk/77c2d636-7a59-11eb-9d32-12caef3c0b88"
    cacert_path = ""
    cert_path = ""
    key_path = ""
  }
}
provider "ucloud" {
    public_key  = "xxxxxxx"
    private_key = "xxxxxx"
    region      = "cn-bj2"
    project_id  = ""
}

backend的prefix资源加了uuid,实际上是为了解决上面一个目录是放一个云资源锁带来的问题,也就是说那个uuid实际上是对应的单独资源id,每个资源都有单独的state文件

如何支持多云

支持多云是Terraform的强项,支持多云依然需要在上次软件做好一定的屏蔽工作。
Terraform需要做的就是准备好多套云的tf模板去填充
如腾讯云:

resource "tencentcloud_cbs_storage" "tencentcloud_disk_{{ .ObjectMeta.UID }}" {
  storage_type      = "{{ .Spec.InstanceType }}"
  storage_name      = "{{ .Spec.InstanceName }}"
  storage_size      = "{{ .Spec.InstanceSize }}"
  availability_zone = "{{ .Spec.Zone }}"
  project_id        = "{{ .Spec.ProjectID }}"
}

如优刻得:

resource "ucloud_disk" "ucloud_disk_{{ .ObjectMeta.UID }}" {
  availability_zone = "{{ .Spec.Zone }}"
  name              = "{{ .Spec.InstanceName }}"
  disk_size         = "{{ .Spec.InstanceSize }}"
  disk_type         = "{{ .Spec.InstanceType }}"
  charge_type       = "{{ .Spec.ChargeType }}"
}

上层的数据结构可以声明成一样的,所有的差异由tf模板来屏蔽

前言

Gradio.NET 是 Gradio 在 .NET 平台上的移植版本。Gradio 是一个开源的 Python 包,用于快速构建机器学习模型、API 或任意 Python 函数的演示或 Web 应用程序。

Gradio.NET 继承了 Gradio 的核心理念,以.NET 开发习惯和熟悉的方式进行Web应用开发,其主要特点包括:

  • 易用性
    :只需几行 .NET 代码即可创建功能完善的用户界面。

  • 灵活性
    :支持多种类型的输入和输出,包括文本、图像、音频等。

  • 一键分享
    :轻松生成访问链接,方便进行测试和使用。

  • 集成支持
    :能够无缝集成到主流的 .NET 框架和库中,如 ASP.NET Core 和 Entity Framework,加速开发和部署流程。

总而言之,Gradio.NET 是一个强大的工具,极大地简化了创建和分享界面的过程,使我们能够专注于业务逻辑而无需担心复杂的前端开发工作。

Gradio.NET

Gradio.NET 是一个基于 Gradio 的 .NET 实现,我们无需掌握任何前端技术(如 JavaScript、CSS 或 HTML),仅用几行 .NET 代码就能快速构建机器学习模型、API 或任意函数的演示或 Web 应用程序。

通过 Gradio.NET,可以轻松创建美观的交互式 Web 界面,无需前端开发经验。

Gradio.NET 使用

1、创建项目

创建一个新的 .NET 8 WebAPI 标准项目,选择启用 OpenAPI 支持和使用控制器;

dotnet new webapi -n ManageCore.Api
cd ManageCore.Api

2、安装 Gradio.Net

安装 NuGet 包
Gradio.Net.AspNetCore
这个包。

3、示例代码

在 Program.cs 中输入以下示例代码:

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
gr.Markdown(
"开始在下面键入,然后点击**运行** 查看输出结果.");
Textbox input, output;
using(gr.Row())
{
input
= gr.Textbox(placeholder: "你叫什么名字?");
output
=gr.Textbox();
}
var btn = gr.Button("运行");await btn.Click(fn: async (input) => gr.Output($"欢迎使用 Gradio.Net, {input.Data[0]}!"), inputs: new[] { input }, outputs: new[] { output });
returnblocks;
}
}

运行结果如下图所示:

如果想在现有项目中使用 Gradio.NET

可以使用
AddGradio

UseGradio
扩展方法:

var builder =WebApplication.CreateBuilder(args);
builder.Services.AddGradio();
var app =builder.Build();

app.UseGradio(
awaitCreateBlocks());

app.Run();

Gradio.NET 示例

1、Layout

Gradio.NET 常用的布局方式都包括:Row/Column、Tab、Group、Accordion等。

示例代码

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
gr.Markdown(
"# Layout Demo");

gr.Markdown(
"## Row/Column");using(gr.Row())
{
using (gr.Column(scale: 1))
{
var text1 =gr.Textbox();var text2 =gr.Textbox();
}
using (gr.Column(scale: 4))
{
var btn1 = gr.Button("Button 1");var btn2 = gr.Button("Button 2");
}
}

gr.Markdown(
"## Tab");using (gr.Tab("Lion"))
{
gr.Textbox(
"lion");
gr.Button(
"New Lion");
}
using (gr.Tab("Tiger"))
{
gr.Textbox(
"tiger");
gr.Button(
"New Tiger");
}

gr.Markdown(
"## Group");using(gr.Group())
{
gr.Textbox(label:
"First");
gr.Textbox(label:
"Last");
}

gr.Markdown(
"## Accordion");using (gr.Accordion("See Details"))
{
gr.Markdown(
"lorem ipsum");
}
returnblocks;
}
}

示例效果

2、Form

表单示例代码,具体如下:

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
using(gr.Column())
{
var text1 =gr.Textbox();var dropdown1 = gr.Dropdown(choices: new[] { "First Choice", "Second Choice", "Third Choice"});var checkbox1 =gr.Checkbox();var checkboxGroup1 = gr.CheckboxGroup(choices: new[] { "First Choice", "Second Choice", "Third Choice"});var multimodalTextbox1 = gr.MultimodalTextbox(interactive:true);var number1 =gr.Number();var radio1 = gr.Radio(choices: ["First Choice", "Second Choice", "Third Choice"]);var slider1 =gr.Slider();
var text_Result = gr.Textbox(label:"Form Value", interactive:false);var btn = gr.Button("Run");await btn.Click(fn: async (input) => gr.Output($@"Textbox: {Textbox.Payload(input.Data[0])}
Dropdown: {string.Join(
", ",Dropdown.Payload(input.Data[1]))} Checkbox: {Checkbox.Payload(input.Data[2])}
CheckboxGroup: {
string.Join(",", CheckboxGroup.Payload(input.Data[3]))}
MultimodalTextbox: {MultimodalTextbox.Payload(input.Data[
4]).Files.FirstOrDefault()?.OrigName}
Number: {Number.Payload(input.Data[
5])}
Radio: {
string.Join(",", Radio.Payload(input.Data[6]))}
Slider: {Slider.Payload(input.Data[
7])}"), inputs: new Component[] { text1, dropdown1, checkbox1, checkboxGroup1, multimodalTextbox1, number1, radio1, slider1 }, outputs: new[] { text_Result }); }
returnblocks;
}
}

示例效果

3、Media

多媒体控件,具体参考代码

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
gr.Markdown(
"**Image Demo** upload a image and click button");
Gradio.Net.Image input, output;
using(gr.Row())
{
input
=gr.Image();

output
=gr.Image();
}
var btn = gr.Button("Submit");await btn.Click(fn: async (input) => gr.Output(DrawWaterMarkOnImage(Gradio.Net.Image.Payload(input.Data[0]))), inputs: new[] { input }, outputs: new[] { output });
returnblocks;
}
}

static string DrawWaterMarkOnImage(stringinputImageFilePath)
{
using (var img =SixLabors.ImageSharp.Image.Load(inputImageFilePath))
{
var outputFilePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".png");
Font font
= SystemFonts.CreateFont("Arial", 10); //for scaling water mark size is largely ignored. using (var img2 = img.Clone(ctx => ApplyScalingWaterMarkSimple(ctx, font, "Gradio.Net", Color.HotPink, 5)))
{
img2.Save(outputFilePath);
}
returnoutputFilePath;
}

}
staticIImageProcessingContext ApplyScalingWaterMarkSimple(IImageProcessingContext processingContext,
Font font,
stringtext,
Color color,
floatpadding)
{
Size imgSize
=processingContext.GetCurrentSize();
float targetWidth = imgSize.Width - (padding * 2);float targetHeight = imgSize.Height - (padding * 2);
//Measure the text size FontRectangle size = TextMeasurer.MeasureSize(text, newTextOptions(font));
//Find out how much we need to scale the text to fill the space (up or down) float scalingFactor = Math.Min(targetWidth / size.Width, targetHeight /size.Height);
//Create a new font Font scaledFont = new Font(font, scalingFactor *font.Size);
var center = new PointF(imgSize.Width / 2, imgSize.Height / 2);var textOptions = newRichTextOptions(scaledFont)
{
Origin
=center,
HorizontalAlignment
=HorizontalAlignment.Center,
VerticalAlignment
=VerticalAlignment.Center
};
returnprocessingContext.DrawText(textOptions, text, color);
}

示例效果

4、Chatbot

示例代码

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
gr.Markdown(
"# Chatbot Demo");
var chatbot =gr.Chatbot();var msg = gr.Textbox(placeholder:"Enter to Submit");
await msg.Submit(streamingFn: (input) => Respond(Textbox.Payload(input.Data[0]), Chatbot.Payload(input.Data[1])),
inputs:
new Component[] { msg, chatbot }, outputs: newComponent[] { msg, chatbot });returnblocks;
}
}
static async IAsyncEnumerable<Output> Respond(string message, IList<ChatbotMessagePair>chatHistory)
{
chatHistory.Add(
new ChatbotMessagePair(message, "You typed:"));
for (int i = 0; i < message.Length; i++)
{
await Task.Delay(500);
chatHistory.Last().AiMessage.TextMessage
+=message[i];
yield return gr.Output("", chatHistory);
}
}

示例效果

5、Progress

根据自己的需求,调整进度条代码,参考代码如下:

App.Launch(awaitCreateBlocks());
async Task<Blocks>CreateBlocks()
{
using (var blocks =gr.Blocks())
{
gr.Markdown(
"# Progress Demo");
var load = gr.Button("Load");var label = gr.Label(label: "Loader");
load.Click(LoadSet, outputs:
new[] { label });
returnblocks;
}
}
static async Task<Output>LoadSet(Input input)
{
const int count = 24;
input.Progress
=gr.Progress(count);for (int i = 0; i < count; i++)
{
input.Progress.Report(i, desc:
"Loading...");await Task.Delay(100);
}
return gr.Output("Loaded");
}

示例效果

还有更多示例代码,可以查看官方文档进行学习。

Gradio.NET 应用

对于 AI 的爱好者来说,Gradio.NET 提供了一个绝佳的机会,通过访问
https://qwen.starworks.cc:88/
,让他们能够与通义千问开源模型进行互动。

使用 Gradio.NET 打造你的 通义千问 AI 聊天机器人,具体如下图所示:

这个 Web 应用不仅用户体验流畅,还能够记住会话历史,轻松识别语义,这一切都得益于其背后的先进技术。

该项目已开源,源代码地址:
https://github.com/sdcb/Sdcb.DashScope

具体代码讲解,可以查看源码。

项目地址

Github:
https://github.com/feiyun0112/Gradio.Net

Demo:
https://github.com/feiyun0112/Gradio.Net/blob/main/readme_files

AI聊天:
https://github.com/sdcb/Sdcb.DashScope

总结

Gradio.NET 致力于成为 .NET 开发者 构建Web 应用的首选框架。它的设计理念是简化开发过程,让每个人都能轻松参与到 Web 应用的开发中来。

如果你对创建聊天机器人感兴趣,可以试试上面这个开源项目,结合 Gradio.NET 开发自己的AI聊天,有需要的朋友们可以参考学习。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。

也可以加入微信公众号
[DotNet技术匠]
社区,与其他热爱技术的同行一起交流心得,共同成长!

引言

2024年,这一年注定在全球智能设备市场的历史上写下浓墨重彩的一笔。作为全球科技巨头,华为再次以其前瞻性的布局,推动了技术与应用的深度融合。在这个充满变革的时代,华为通过不断扩展的鸿蒙生态系统,重新定义了操作系统与AI技术的结合方式。
你是否已经感受到这场变革的力量?
在全球瞩目的华为开发者大会上,两项震撼业界的技术——HarmonyOS NEXT与盘古大模型5.0首次亮相,不仅标志着智能化的全新高度,更为AI技术在终端设备中的广泛应用铺平了道路。随着时间的推进和技术的飞速发展,我们不得不重新审视操作系统和AI的未来。

HarmonyOS NEXT:AI与操作系统的深度融合

2024年,HarmonyOS NEXT的发布掀起了智能设备市场的巨大波澜。这个操作系统以惊人的速度实现了多设备之间的无缝连接,
你是否想过,这种无缝连接会如何改变你的生活?
无论是手机、平板,还是智能屏幕,用户都可以在不同设备间自由切换。这种跨端协同能力,延续了鸿蒙系统的优势,并将其提升到了前所未有的高度。

然而,
真正的革命是什么?
HarmonyOS NEXT的真正突破在于它将AI能力深度整合到了操作系统中。借助2024年最新的昇腾计算力和盘古大模型的支持,HarmonyOS NEXT推出了诸如AIGC图像生成和AI声音修复等颠覆性功能。这些功能不仅极大地提升了系统的智能化,还为用户带来了前所未有的体验。

在时间的紧迫驱动下,开发者们也在争分夺秒地利用HarmonyOS NEXT的强大功能。
如果你是开发者,你会如何利用这些新功能?
该系统的API接口已经成为开发者的利器,2024年,开发者不再需要耗费大量时间和资源开发复杂的AI功能。通过调用系统级API,开发者能够在更短的时间内创造出更加智能化和人性化的应用。
据统计,
截至2024年5月,已有超过5000个常用应用启动开发,覆盖了出行、社交、金融等18个领域。HarmonyOS NEXT通过多设备一致性的用户体验,迅速推动了鸿蒙生态的扩展。

盘古大模型5.0:AI技术的全新里程碑

2024年,华为再一次站在了AI技术的最前沿。
盘古大模型5.0的发布意味着什么?
这一模型不仅是AI技术发展的重要里程碑,也为全球科技行业带来了巨大的冲击。这一模型在多模态支持方面的创新引发了广泛关注,它不仅适用于智能手机和PC等端侧设备,还能支持自动驾驶、工业设计等复杂场景的应用。

盘古大模型5.0凭借其强大的计算能力,推动了AI在多个领域的广泛应用。特别是在自动驾驶和工业设计等领域,这一技术展示出了巨大的潜力,使得2024年成为了AI技术爆发的一年。

盘古大模型5.0的推出,标志着AI技术从云端走向了端侧,成为智能设备的核心驱动力。2024年,这一技术不仅提升了设备的智能化水平,还加速了AI技术在终端设备中的普及。基于盘古大模型的夸父机器人首次在2024年亮相,展示了AI技术在复杂任务规划和执行中的能力。夸父机器人能够通过盘古大模型进行复杂任务的自动化处理,标志着AI技术进入了一个新的发展阶段。

HarmonyOS NEXT与盘古大模型的协同效应

2024年,HarmonyOS NEXT和盘古大模型5.0的强强联手,展现了智能科技的无穷潜力。这一协同效应不仅重新定义了智能设备的智能化水平,也极大推动了鸿蒙生态的全面升级。让我们深入探讨这种技术结合如何影响未来的智能设备以及开发者的创新机会。

HarmonyOS NEXT作为华为最新发布的操作系统,其最引人注目的特点之一便是其高度集成的AI功能。通过将AI能力深度融入操作系统,HarmonyOS NEXT不仅提升了设备间的无缝连接性,还实现了跨设备的智能体验。用户在手机、平板和智能屏幕之间的切换变得前所未有的流畅。这种跨端协同能力的提升,使得用户在不同设备间的操作更加自然,同时也带来了更加统一的使用体验。

盘古大模型5.0的发布,则为AI技术的应用注入了新的活力。作为华为在AI领域的重要里程碑,盘古大模型5.0以其卓越的多模态支持能力,赋予了智能设备更强大的处理能力和更广泛的应用场景。无论是在智能手机、PC端,还是在自动驾驶、工业设计等复杂领域,盘古大模型5.0都展现出了极大的潜力。特别是在自动驾驶领域,这一技术通过增强的计算能力和智能算法,推动了自动驾驶系统的快速发展和应用。

当HarmonyOS NEXT与盘古大模型5.0结合时,二者的协同效应变得尤为显著。HarmonyOS NEXT的操作系统架构可以充分发挥盘古大模型5.0的AI计算能力,提供更加智能化和人性化的应用体验。这种深度整合使得AI功能不再仅限于后台处理,而是直接嵌入到用户的日常使用中。例如,用户可以在HarmonyOS NEXT中体验到基于盘古大模型的实时图像生成和语音修复功能。这些功能不仅提升了设备的智能化水平,还使得用户的互动体验更加自然和直观。

此外,这种技术的融合还大大简化了开发者的工作流程。通过提供全面的API接口,HarmonyOS NEXT使开发者能够更容易地调用盘古大模型的强大功能,从而在更短的时间内开发出智能化的应用程序。这种便捷性不仅降低了开发门槛,也激发了开发者的创造力,使得越来越多的创新应用得以迅速推出市场。

总的来说,HarmonyOS NEXT与盘古大模型5.0的协同效应不仅提升了智能设备的智能化水平,还为未来的科技发展提供了新的方向。这种技术结合预示着智能设备将进入一个全新的发展阶段,用户和开发者都将受益于这一变革带来的无限可能。

展望未来:鸿蒙生态的无限可能

展望2024年及以后,鸿蒙生态将继续扩展至更多领域,推动AI技术在全球范围内的普及。 HarmonyOS NEXT和盘古大模型的结合,将为未来的智能设备提供更加广泛的支持。无论是在智能家居、工业设计,还是自动驾驶领域,鸿蒙生态都将发挥越来越重要的作用。

那么
这些技术的发展对全球科技行业又意味着什么?
HarmonyOS NEXT和盘古大模型5.0的推出,将对全球科技行业产生深远影响。它们不仅推动了操作系统的智能化发展,还为未来的AI技术发展奠定了坚实的基础。

结论

2024年,HarmonyOS NEXT和盘古大模型5.0的发布标志着鸿蒙生态进入了一个全新的发展阶段。两者的结合不仅提升了系统的智能化水平,还为未来的科技发展提供了无限可能。

未来几年,随着技术的不断进步,HarmonyOS NEXT和盘古大模型将继续引领智能设备的发展方向,为全球用户带来更加智能化的体验。
下面是鸿蒙发展的一些历史事件:


  1. 2019年8月
    -
    鸿蒙操作系统首次发布
    :华为推出了自主研发的鸿蒙操作系统,标志着其进入操作系统领域的战略起点。

  2. 2020年9月
    -
    HarmonyOS 2.0发布
    :华为在全球发布会上推出HarmonyOS 2.0,进一步扩大了鸿蒙系统的生态布局。

  3. 2021年6月
    -
    鸿蒙系统大规模商用
    :鸿蒙操作系统开始大规模商用于华为智能手机和其他智能设备,迅速扩大用户群体。

  4. 2022年12月
    -
    HarmonyOS 3.0发布
    :进一步提升系统的跨端协同和智能化水平,巩固了鸿蒙在智能设备市场的地位。

  5. 2024年8月
    -
    HarmonyOS NEXT与盘古大模型5.0发布
    :标志着鸿蒙生态进入智能化和AI赋能的新时代,为全球智能设备的未来发展奠定了基础。

这些历史事件,是否让你感受到鸿蒙的迅速崛起与不可忽视的影响力?


下期预告:深入探索HarmonyOS NEXT的开发实践

在下期文章中,我们将深入探讨以下内容:

  • 实践案例分享
    :解析成功应用如何充分利用HarmonyOS NEXT的核心功能。

  • 开发者工具深度剖析
    :详细介绍HarmonyOS NEXT提供的开发者工具和资源。

  • AI功能应用实例
    :展示如何将AIGC图像生成和AI声音修复功能有效集成到应用中。

  • 性能优化与调试技巧
    :提供优化和调试HarmonyOS NEXT应用的实用建议。

敬请关注我的下一篇文章,获取更多关于HarmonyOS NEXT的实战技巧和创新见解!

热点随笔:

·
会员力量:非常感谢58位园友成为终身会员
(
博客园团队
)
·
【故障公告】博客站点遭遇大规模 DDoS 攻击
(
博客园团队
)
·
使用FModel提取《黑神话:悟空》的资产
(
paw5zx
)
·
寻访中国100家.NET中大企业 —— 第二站:苏州行
(
一线码农
)
·
花了一天时间帮财务朋友开发了一个实用小工具
(
程序员晓凡
)
·
网易云音乐故障 2 小时,这次到底谁背锅?(今天记得领补偿)
(
程序员鱼皮
)
·
从网友探秘 《黑神话:悟空》 的脚本说说C#
(
张善友
)
·
可以调用Null的实例方法吗?
(
Artech
)
·
【团队建设】如何做好团队开发中的 CodeReview(代码评审)?
(
CodeBlogMan
)
·
方法的三种调用形式
(
Artech
)
·
小公司后端架构、代码、流程吐槽
(
Go_Solo
)
·
C#开发的应用升级管理器LUAgent客户端 - 开源研究系列文章 - 个人小作品
(
lzhdim
)

热点新闻:

·
拒绝背锅!39 岁失业后,我写出了一个超一万亿使用量的数据库
·
百万在线,大圣归来!《黑神话:悟空》石破天惊,RTX 4090D飞越花果山
·
在中国出售的游戏机缺乏游戏
·
飞行1000公里 中国载人飞艇首次成功跨省转场
·
餐饮“收尸人”亲述:1个月收了42家火锅店
·
《黑神话:悟空》的胜利,是审美的胜利
·
《黑神话》火到破纪录,老黄都要到游戏展秀一把
·
中国游戏发行商 Gamera:赠送员工《黑神话:悟空》,发售当日放假一日
·
离职格力?董明珠为何不拉王自如一把?
·
黑神话悟空之后或有“黑神话姜子牙”“黑神话钟馗”
·
突然现身国内街头!马斯克曾表示在中国很难合法上路,品牌方称暂未销售,业内:平行进口售价或超250万元
·
从“单机之殇”到“国产3A希望”,腾讯为《黑神话:悟空》都做了什么?