Project Icon

protoc-gen-validate

是一个 protoc 插件,用于生成多语言消息验证器

protoc-gen-validate 是一个 protoc 插件,用于生成多语言消息验证器。开发者可在 proto 文件中为消息和字段添加约束规则,插件会在编译时生成相应的验证代码。支持 Go、Java、C++ 等语言,能对结构化数据进行语义验证,确保数据正确性。该项目现处于稳定维护阶段,新项目可考虑使用其后继者 protovalidate。

[][buf] protoc-gen-validate (PGV)

许可证 发布 Slack

[!重要] protoc-gen-validate (PGV) 已达到稳定状态,并处于维护模式。

我们建议新项目和现有项目过渡到使用 [protovalidate][pv]。

如果你想了解更多关于 protoc-gen-validate 的局限性以及我们如何设计 [protovalidate][pv] 来改进它,请阅读[我们的博客文章][pv-announce]。

PGV 是一个 protoc 插件,用于生成多语言消息验证器。虽然 protocol buffers 能有效地保证结构化数据的类型,但它们无法强制执行值的语义规则。这个插件为 protoc 生成的代码添加了支持,以验证这些约束。

开发人员导入 PGV 扩展,并在他们的 proto 文件中用约束规则注释消息和字段:

syntax = "proto3";

package examplepb;

import "validate/validate.proto";

message Person {
  uint64 id = 1 [(validate.rules).uint64.gt = 999];

  string email = 2 [(validate.rules).string.email = true];

  string name = 3 [(validate.rules).string = {
    pattern:   "^[A-Za-z]+( [A-Za-z]+)*$",
    max_bytes: 256,
  }];

  Location home = 4 [(validate.rules).message.required = true];

  message Location {
    double lat = 1 [(validate.rules).double = {gte: -90,  lte: 90}];
    double lng = 2 [(validate.rules).double = {gte: -180, lte: 180}];
  }
}

使用 PGV 和目标语言的默认插件执行 protoc 将在生成的类型上创建 Validate 方法:

p := new(Person)

err := p.Validate() // 错误:Id 必须大于 999
p.Id = 1000

err = p.Validate() // 错误:Email 必须是有效的电子邮件地址
p.Email = "example@bufbuild.com"

err = p.Validate() // 错误:Name 必须匹配模式 '^[A-Za-z]+( [A-Za-z]+)*$'
p.Name = "Protocol Buffer"

err = p.Validate() // 错误:Home 是必需的
p.Home = &Location{37.7, 999}

err = p.Validate() // 错误:Home.Lng 必须在 [-180, 180] 范围内
p.Home.Lng = -122.4

err = p.Validate() // 错误:nil

使用方法

依赖项

  • go 工具链(≥ v1.7)
  • $PATH 中的 protoc 编译器
  • $PATH 中的 protoc-gen-validate
  • 目标语言的官方特定语言插件
  • 目前仅支持 proto3 语法。 计划支持 proto2 语法。

安装

从 GitHub 发布版下载

GitHub 发布版 下载资产,解压缩并将插件添加到 $PATH 中。

从源代码构建

# 将此仓库获取到 $GOPATH 中
go get -d github.com/envoyproxy/protoc-gen-validate

💡 是的,我们的 go 模块路径是 github.com/envoyproxy/protoc-gen-validate 而不是 bufbuild,这是有意为之。

更改模块路径实际上是创建一个新的、独立的模块。我们不希望破坏我们的用户。Go 团队正在努力为路径更改的模块提供更好的 cmd/go 支持,但进展缓慢。在此之前,我们将继续使用 envoyproxy 模块路径。

git clone https://github.com/bufbuild/protoc-gen-validate.git
# 将 PGV 安装到 $GOPATH/bin
cd protoc-gen-validate && make build

参数

  • lang:指定要生成的目标语言。目前,唯一支持的选项是:
    • go
    • cc(用于 C++,部分实现)
    • java
  • 注意:Python 通过运行时代码生成工作。没有编译时生成。有关详细信息,请参阅 Python 部分。

示例

Go

Go 生成应该与官方插件输出到相同的输出路径。对于 proto 文件 example.proto,相应的验证代码生成到 ../generated/example.pb.validate.go

protoc \
  -I . \
  -I path/to/validate/ \
  --go_out=":../generated" \
  --validate_out="lang=go:../generated" \
  example.proto

所有生成的消息都包含以下方法:

  • Validate() error,在验证过程中返回遇到的第一个错误。
  • ValidateAll() error,返回验证过程中遇到的所有错误。

PGV 不需要从现有生成的代码中添加任何额外的运行时依赖项。

注意:默认情况下,example.pb.validate.go 嵌套在与你的 option go_package 名称匹配的目录结构中。你可以使用 protoc 参数 paths=source_relative:. 来更改这一点,比如 --validate_out="lang=go,paths=source_relative:../generated"。然后 --validate_out 将在预期的位置输出文件。有关更多信息,请参阅 Google 的 protobuf 文档或包和输入路径参数

还支持 module=example.com/foo 标志,如此处所述

使用较新的 Buf CLI 版本(>v1.9.0),你可以使用新的插件键,而不是直接使用 protoc 命令:

# buf.gen.yaml

version: v1
plugins:
  - plugin: buf.build/bufbuild/validate-go
    out: gen
# proto/buf.yaml

version: v1
deps:
  - buf.build/envoyproxy/protoc-gen-validate

Java

Java 生成与现有的 Java 项目 protobuf 工具链集成。对于 Maven 项目,在你的 pom.xml 或 build.gradle 中添加以下内容。


<dependencies>
    <dependency>
        <groupId>build.buf.protoc-gen-validate</groupId>
        <artifactId>pgv-java-stub</artifactId>
        <version>${pgv.version}</version>
    </dependency>
</dependencies>

<build>
<extensions>
    <extension>
        <groupId>kr.motd.maven</groupId>
        <artifactId>os-maven-plugin</artifactId>
        <version>1.4.1.Final</version>
    </extension>
</extensions>
<plugins>
    <plugin>
        <groupId>org.xolstice.maven.plugins</groupId>
        <artifactId>protobuf-maven-plugin</artifactId>
        <version>0.6.1</version>
        <configuration>
            <protocArtifact>
                com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
            </protocArtifact>
        </configuration>
        <executions>
            <execution>
                <id>protoc-java-pgv</id>
                <goals>
                    <goal>compile-custom</goal>
                </goals>
                <configuration>
                    <pluginParameter>lang=java</pluginParameter>
                    <pluginId>java-pgv</pluginId>
                    <pluginArtifact>
                        build.buf.protoc-gen-validate:protoc-gen-validate:${pgv.version}:exe:${os.detected.classifier}
                    </pluginArtifact>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>
</build>
plugins {
    ...
    id "com.google.protobuf" version "${protobuf.version}"
    ...
}

protobuf {
    protoc {
        artifact = "com.google.protobuf:protoc:${protoc.version}"
    }

    plugins {
        javapgv {
            artifact = "build.buf.protoc-gen-validate:protoc-gen-validate:${pgv.version}"
        }
    }

    generateProtoTasks {
        all()*.plugins {
            javapgv {
                option "lang=java"
            }
        }
    }
}
// 创建一个反射加载生成的验证器的验证器索引
ValidatorIndex index = new ReflectiveValidatorIndex();
// 断言消息是有效的
index.validatorFor(message.getClass()).assertValid(message);

// 创建 gRPC 客户端和服务器拦截器以自动验证消息(需要 pgv-java-grpc 模块)
clientStub = clientStub.withInterceptors(new ValidatingClientInterceptor(index));
serverBuilder.addService(ServerInterceptors.intercept(svc, new ValidatingServerInterceptor(index)));

Python

Python 实现通过即时代码生成工作。换句话说,validate(msg) 函数是按需编写并 exec-ed 的。LRU 缓存通过存储每个描述符的生成函数来提高性能。

Python 包可在 PyPI 上获得。

要运行 validate(),请执行以下操作:

from entities_pb2 import Person
from protoc_gen_validate.validator import validate, ValidationFailed

p = Person(first_name="Foo", last_name="Bar", age=42)
try:
    validate(p)
except ValidationFailed as err:
    print(err)

你可以使用 print_validate() 函数查看生成的代码。

约束规则

提供的约束 主要是根据 JSON Schema 中的约束建模的。PGV 规则可以为同一字段混合使用;插件确保应用于字段的规则在代码生成之前不会相互矛盾。

查看约束规则比较矩阵以了解特定语言的约束能力。

数字

所有数字类型(floatdoubleint32int64uint32uint64sint32sint64fixed32fixed64sfixed32sfixed64)共享相同的规则。

  • const:字段必须精确地等于指定值。

    // x 必须精确等于 1.23
    float x = 1 [(validate.rules).float.const = 1.23];
    
  • lt/lte/gt/gte:这些不等式(分别为 <<=>>=)允许推导字段必须位于的范围。

    // x 必须小于 10
    int32 x = 1 [(validate.rules).int32.lt = 10];
    
    // x 必须大于或等于 20
    uint64 x = 1 [(validate.rules).uint64.gte = 20];
    
    // x 必须在 [30, 40) 范围内
    fixed32 x = 1 [(validate.rules).fixed32 = {gte:30, lt: 40}];
    

    反转 lt(e)gt(e) 的值是有效的,并创建一个排除范围。

    // x 必须在 [30, 40) 范围之外
    double x = 1 [(validate.rules).double = {lt:30, gte:40}];
    
  • in/not_in:这两个规则允许为字段的值指定允许/拒绝列表。

    // x 必须是 1、2 或 3
    uint32 x = 1 [(validate.rules).uint32 = {in: [1,2,3]}];
    
    // x 不能是 0 或 0.99
    float x = 1 [(validate.rules).float = {not_in: [0, 0.99]}];
    
  • ignore_empty:此规则指定如果字段为空或设置为默认值,则忽略任何验证规则。这些通常在更新请求中能够取消设置字段时很有用,或者在切换到 WKT 不可行的情况下跳过可选字段的验证。

    uint32 x = 1 [(validate.rules).uint32 = {ignore_empty: true, gte: 200}];
    

布尔值

  • const:字段必须精确地等于指定值。

    // x 必须设置为 true
    bool x = 1 [(validate.rules).bool.const = true];
    
    // x 不能设置为 true
    bool x = 1 [(validate.rules).bool.const = false];
    

字符串

  • const:字段必须精确地等于指定值。

// x 必须是一个有效的主机名(根据 RFC 1034) string x = 1 [(validate.rules).string.hostname = true];

// x 必须是一个有效的 IP 地址(IPv4 或 IPv6) string x = 1 [(validate.rules).string.ip = true];

// x 必须是一个有效的 IPv4 地址 // 例如: "192.168.0.1" string x = 1 [(validate.rules).string.ipv4 = true];

// x 必须是一个有效的 IPv6 地址 // 例如: "fe80::3" string x = 1 [(validate.rules).string.ipv6 = true];

// x 必须是一个有效的绝对 URI (根据 RFC 3986) string x = 1 [(validate.rules).string.uri = true];

// x 必须是一个有效的 URI 引用(绝对或相对) string x = 1 [(validate.rules).string.uri_ref = true];

// x 必须是一个有效的 UUID (根据 RFC 4122) string x = 1 [(validate.rules).string.uuid = true];

// x 必须符合 HTTP 头名称的已知正则表达式(根据 RFC 7230) string x = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_NAME]

// x 必须符合 HTTP 头值的已知正则表达式(根据 RFC 7230) string x = 1 [(validate.rules).string.well_known_regex = HTTP_HEADER_VALUE];

// x 必须符合头部的已知正则表达式,不允许 \r\n\0 字符。 string x = 1 [(validate.rules).string {well_known_regex: HTTP_HEADER_VALUE, strict: false}];


### 字节

> 字面值应该使用字符串表示,必要时使用转义。

- **const**: 字段必须完全等于指定的值。

  ```protobuf
  // x 必须设置为 "foo" ("\x66\x6f\x6f")
  bytes x = 1 [(validate.rules).bytes.const = "foo"];

  // x 必须设置为 "\xf0\x90\x28\xbc"
  bytes x = 1 [(validate.rules).bytes.const = "\xf0\x90\x28\xbc"];
  • len/min_len/max_len: 这些规则限制字段中的字节数。

    // x 必须正好是 3 个字节
    bytes x = 1 [(validate.rules).bytes.len = 3];
    
    // x 必须至少是 3 个字节长
    bytes x = 1 [(validate.rules).bytes.min_len = 3];
    
    // x 必须在 5 到 10 个字节之间,包含边界值
    bytes x = 1 [(validate.rules).bytes = {min_len: 5, max_len: 10}];
    
  • pattern: 字段必须匹配指定的 [RE2 兼容][re2] 正则表达式。包含的表达式应省略任何分隔符(即 /\d+/ 应该只写成 \d+)。

    // x 必须是非空的 ASCII 字节序列
    bytes x = 1 [(validate.rules).bytes.pattern = "^[\x00-\x7F]+$"];
    
  • prefix/suffix/contains: 字段必须包含指定的字节序列,可以选择指定位置。

    // x 必须以 "\x99" 开头
    bytes x = 1 [(validate.rules).bytes.prefix = "\x99"];
    
    // x 必须以 "buz\x7a" 结尾
    bytes x = 1 [(validate.rules).bytes.suffix = "buz\x7a"];
    
    // x 必须在任意位置包含 "baz" 
    bytes x = 1 [(validate.rules).bytes.contains = "baz"];
    
  • in/not_in: 这两个规则允许为字段的值指定允许/拒绝列表。

    // x 必须是 "foo"、"bar" 或 "baz" 之一
    bytes x = 1 [(validate.rules).bytes = {in: ["foo", "bar", "baz"]}];
    
    // x 不能是 "fizz" 或 "buzz"
    bytes x = 1 [(validate.rules).bytes = {not_in: ["fizz", "buzz"]}];
    
  • ignore_empty: 此规则指定如果字段为空或设置为默认值,则忽略任何验证规则。这通常在更新请求中可以取消设置字段,或者在无法切换到 WKT 的可选字段上跳过验证时很有用。

    bytes x = 1 [(validate.rules).bytes = {ignore_empty: true, in: ["foo", "bar", "baz"]}];
    
  • 常见格式: 这些规则为常见模式提供高级约束。这些约束通常比等效的正则表达式模式更宽松和高效,同时提供更具解释性的失败描述。

    // x 必须是字节格式的有效 IP 地址(IPv4 或 IPv6)
    bytes x = 1 [(validate.rules).bytes.ip = true];
    
    // x 必须是字节格式的有效 IPv4 地址
    // 例如: "\xC0\xA8\x00\x01"
    bytes x = 1 [(validate.rules).bytes.ipv4 = true];
    
    // x 必须是字节格式的有效 IPv6 地址
    // 例如: "\x20\x01\x0D\xB8\x85\xA3\x00\x00\x00\x00\x8A\x2E\x03\x70\x73\x34"
    bytes x = 1 [(validate.rules).bytes.ipv6 = true];
    

枚举

所有字面值应使用枚举描述符中定义的数字(int32)值。

以下示例使用此 State 枚举

enum State {
  INACTIVE = 0;
  PENDING = 1;
  ACTIVE = 2;
}
  • const: 字段必须完全等于指定的值。

    // x 必须设置为 ACTIVE (2)
    State x = 1 [(validate.rules).enum.const = 2];
    
  • defined_only: 字段必须是枚举描述符中指定的值之一。

    // x 只能是 INACTIVE、PENDING 或 ACTIVE
    State x = 1 [(validate.rules).enum.defined_only = true];
    
  • in/not_in: 这两个规则允许为字段的值指定允许/拒绝列表。

    // x 必须是 INACTIVE (0) 或 ACTIVE (2)
    State x = 1 [(validate.rules).enum = {in: [0,2]}];
    
    // x 不能是 PENDING (1)
    State x = 1 [(validate.rules).enum = {not_in: [1]}];
    

消息

如果字段包含一个消息,并且该消息是使用 PGV 生成的,将递归执行验证。未使用 PGV 生成的消息将被跳过。

// 如果 Person 是用 PGV 生成的,并且 x 被设置,
// x 的字段将被验证。
    Person x = 1;
  • skip: 此规则指定不应评估此字段的验证规则。

    // Person x 的字段将不会被验证。
    Person x = 1 [(validate.rules).message.skip = true];
    
  • required: 此规则指定字段不能未设置。

    // x 不能未设置
    Person x = 1 [(validate.rules).message.required = true];
    
    // x 不能未设置,但不会对 x 执行验证
    Person x = 1 [(validate.rules).message = {required: true, skip: true}];
    

重复

  • min_items/max_items: 这些规则控制字段中包含的元素数量

    // x 必须至少包含 3 个元素
    repeated int32 x = 1 [(validate.rules).repeated.min_items = 3];
    
    // x 必须包含 5 到 10 个 Person,包含边界值
    repeated Person x = 1 [(validate.rules).repeated = {min_items: 5, max_items: 10}];
    
    // x 必须恰好包含 7 个元素
    repeated double x = 1 [(validate.rules).repeated = {min_items: 7, max_items: 7}];
    
  • unique: 此规则要求字段中的所有元素必须是唯一的。此规则不支持重复的消息。

    // x 必须包含唯一的 int64 值
    repeated int64 x = 1 [(validate.rules).repeated.unique = true];
    
  • items: 此规则指定应该应用于字段中每个元素的约束。重复的消息字段也会应用其验证规则,除非在此约束上指定了 skip

    // x 必须包含正浮点值
    repeated float x = 1 [(validate.rules).repeated.items.float.gt = 0];
    
    // x 必须包含 Person,但不验证它们
    repeated Person x = 1 [(validate.rules).repeated.items.message.skip = true];
    
  • ignore_empty: 此规则指定如果字段为空或设置为默认值,则忽略任何验证规则。这通常在更新请求中可以取消设置字段,或者在无法切换到 WKT 的可选字段上跳过验证时很有用。

    repeated int64 x = 1 [(validate.rules).repeated = {ignore_empty: true, items: {int64: {gt: 200}}}];
    

映射

  • min_pairs/max_pairs: 这些规则控制此字段中包含的键值对数量

    // x 必须至少包含 3 个键值对
    map<string, uint64> x = 1 [(validate.rules).map.min_pairs = 3];
    
    // x 必须包含 5 到 10 个键值对
    map<string, string> x = 1 [(validate.rules).map = {min_pairs: 5, max_pairs: 10}];
    
    // x 必须恰好包含 7 个键值对
    map<string, Person> x = 1 [(validate.rules).map = {min_pairs: 7, max_pairs: 7}];
    
  • no_sparse: 对于具有消息值的映射字段,将此规则设置为 true 会禁止具有未设置值的键。

    // x 中的所有值都必须设置
    map<uint64, Person> x = 1 [(validate.rules).map.no_sparse = true];
    
  • keys: 此规则指定应用于字段中键的约束。

    // x 的键必须全部为负数
    <sint32, string> x = [(validate.rules).map.keys.sint32.lt = 0];
    
  • values: 此规则指定应用于字段中每个值的约束。重复的消息字段也会应用其验证规则,除非在此约束上指定了 skip

    // x 必须包含至少 3 个字符的字符串
    map<string, string> x = 1 [(validate.rules).map.values.string.min_len = 3];
    
    // x 必须包含 Person,但不验证它们
    map<string, Person> x = 1 [(validate.rules).map.values.message.skip = true];
    
  • ignore_empty: 此规则指定如果字段为空或设置为默认值,则忽略任何验证规则。这通常在更新请求中可以取消设置字段,或者在无法切换到 WKT 的可选字段上跳过验证时很有用。

    map<string, string> x = 1 [(validate.rules).map = {ignore_empty: true, values: {string: {min_len: 3}}}];
    

众所周知的类型(WKTs)

一组 [WKTs][wkts] 与 protoc 打包在一起,是许多领域中有用的常见消息模式。

标量值包装器

proto3 语法中,无法区分未设置和标量字段的零值。值 WKTs 通过将它们包装在消息中来允许这种区分。PGV 允许使用包装器封装的相同标量规则。

// 如果设置了,x 必须大于 3
    google.protobuf.Int32Value x = 1 [(validate.rules).int32.gt = 3];

消息规则也可以与标量众所周知的类型(WKTs)一起使用:

// 确保如果没有为 age 设置值,尽管其零值为 0,也不会通过验证。
message X {google.protobuf.Int32Value age = 1 [(validate.rules).int32.gt = -1, (validate.rules).message.required = true];}

Any

  • required: 此规则指定必须设置字段

    // x 不能未设置
    google.protobuf.Any x = 1 [(validate.rules).any.required = true];
    
  • in/not_in: 这两个规则允许为此字段中的 type_url 值指定允许/拒绝列表。如果可能,请考虑使用 oneof 联合而不是 in

    // x 不能是 Duration 或 Timestamp WKT
    google.protobuf.Any x = 1 [(validate.rules).any = {not_in: [
        "type.googleapis.com/google.protobuf.Duration",
        "type.googleapis.com/google.protobuf.Timestamp"
      ]}
    

// x必须在[epoch, 2009/11/10T23:00:00Z)范围内 google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = { gte: {}, lt: {seconds: 63393490800} }];


将`lt(e)`和`gt(e)`的值互换是有效的,并创建一个排除范围。

```protobuf
// x必须在[epoch, 2009/11/10T23:00:00Z)范围之外
google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = {
    lt:  {},
    gte: {seconds: 63393490800}
  }];
  • lt_now/gt_now: 这些不等式允许相对于当前时间的范围。这些规则不能与上面的绝对规则一起使用。
// x必须小于当前时间戳
google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.lt_now = true];
  • within: 此规则指定字段的值应在当前时间的一定持续时间内。此规则可与lt_nowgt_now一起使用来控制这些范围。
// x必须在当前时间的±1秒内
google.protobuf.Timestamp x = 1 [(validate.rules).timestamp.within.seconds = 1];

// x必须在(now, now+1h)范围内
google.protobuf.Timestamp x = 1 [(validate.rules).timestamp = {
    gt_now: true,
    within: {seconds: 3600}
  }];

消息全局

  • disabled: 可以取消消息字段的所有验证规则,包括任何支持验证的消息字段本身。
message Person {
  option (validate.disabled) = true;

  // x将不需要大于123
  uint64 x = 1 [(validate.rules).uint64.gt = 123];

  // y的字段将不会被验证
  Person y = 2;
}
  • ignored: 不为此消息生成验证方法或任何相关的验证代码。
message Person {
  option (validate.ignored) = true;

  // x将不需要大于123
  uint64 x = 1 [(validate.rules).uint64.gt = 123];

  // y的字段将不会被验证
  Person y = 2;
}

OneOfs

  • required: 要求oneof中的一个字段必须被设置。默认情况下,联合字段中的无或一个可以被设置。启用此规则不允许全部未设置。
oneof id {
  // x、y或z必须设置其中一个。
  option (validate.required) = true;

  string x = 1;
  int32  y = 2;
  Person z = 3;
}

开发

PGV是用Go语言在[protoc-gen-star][pg*]框架之上编写的,并编译成独立的二进制文件。

依赖

目前所有PGV依赖都已检入项目。要测试PGV,必须安装protoc,可以从[源码][protoc-source]、提供的[发布版][protoc-releases]或包管理器安装。还应安装目标语言的官方protoc插件。

Make目标

  • make build: 生成约束proto并将PGV编译到$GOPATH/bin

  • make lint: 对PGV代码库运行静态分析规则,包括golintgo vetgofmt -s

  • make testcases: 生成/tests/harness/cases中的proto文件。这些文件被测试工具用来验证为每种语言生成的验证规则。

  • make harness: 对每种语言的测试工具执行测试用例。

在Bazel下运行所有测试

确保您的PATH设置包含protoc-gen-goprotoc,然后:

bazel test //tests/...

Docker

PGV带有一个Dockerfile用于一致的开发工具和CI。主要入口点是make,默认目标是build

# 构建镜像
docker build -t bufbuild/protoc-gen-validate .

# 执行默认make目标: build
docker run --rm \
  bufbuild/protoc-gen-validate

# 执行'ci' make目标
docker run --rm \
  bufbuild/protoc-gen-validate ci

# 执行'build'和'testcases' make目标
docker run --rm \
  bufbuild/protoc-gen-validate build testcases

# 覆盖入口点并直接与容器交互
# 当想在本地没有安装bazel的情况下运行bazel命令时,这可能很有用。
docker run --rm \
 -it --entrypoint=/bin/bash \
 bufbuild/protoc-gen-validate
项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号