Skip to content

Commit

Permalink
Merge branch 'master' into feature/license
Browse files Browse the repository at this point in the history
  • Loading branch information
CeerDecy committed Nov 23, 2023
2 parents eb197ba + fd60919 commit e959a21
Show file tree
Hide file tree
Showing 87 changed files with 3,984 additions and 3,647 deletions.
78 changes: 35 additions & 43 deletions .erda/ai-proxy/migrations/ai-proxy/20230823-ai-proxy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -121,50 +121,42 @@ CREATE TABLE `ai_proxy_session`

CREATE TABLE `ai_proxy_filter_audit`
(
`id` CHAR(36) NOT NULL COMMENT 'primary key',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '删除时间, 1970-01-01 00:00:00 表示未删除',

`api_key_sha256` CHAR(64) NOT NULL DEFAULT '' COMMENT '请求使用的 app_key sha256 哈希值',

`username` VARCHAR(128) NOT NULL COMMENT '用户名称, source=dingtalk时, 为钉钉用户名称',
`phone_number` VARCHAR(32) NOT NULL COMMENT '用户手机号码, source=dingtalk时, 为钉钉账号注册手机号',
`job_number` VARCHAR(32) NOT NULL COMMENT '用户工号, source=dingtalk时, 为用户在其组织内的工号',
`email` VARCHAR(64) NOT NULL COMMENT '用户邮箱',
`dingtalk_staff_id` VARCHAR(64) NOT NULL COMMENT '用户钉钉号',

`session_id` VARCHAR(64) NOT NULL COMMENT '对话标识',
`chat_type` VARCHAR(32) NOT NULL COMMENT '对话类型',
`chat_title` VARCHAR(128) NOT NULL COMMENT 'source=dingtalk时, 私聊时为 private, 群聊时为群名称',
`chat_id` VARCHAR(64) NOT NULL COMMENT '钉钉聊天 id',
`source` VARCHAR(128) NOT NULL COMMENT '接入应用: dingtalk, vscode-plugin, jetbrains-plugin ...',
`provider_name` VARCHAR(128) NOT NULL COMMENT 'AI 能力提供商: openai, azure...',
`provider_instance_id` VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'provider 实例 id',
`model` VARCHAR(128) NOT NULL COMMENT '调用的模型名称: gpt-3.5-turbo, gpt-4-8k, ...',
`operation_id` VARCHAR(128) NOT NULL COMMENT '调用的接口名称, HTTP Method + Path',
`prompt` MEDIUMTEXT NOT NULL COMMENT '提示语',
`completion` LONGTEXT NOT NULL COMMENT 'AI 回复多个 choices 中的一个',
`req_func_call_name` VARCHAR(128) NOT NULL COMMENT 'function_call name in request message',
`req_func_call_args` LONGTEXT NOT NULL COMMENT 'function_call arguments in request message',
`res_func_call_name` VARCHAR(128) NOT NULL COMMENT 'function_call name in response message',
`res_func_call_args` LONGTEXT NOT NULL COMMENT 'function_call arguments in response message',
`metadata` LONGTEXT NOT NULL COMMENT '客户端要审计的其他信息',

`x_request_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'http 请求中的 X-Request-Id',
`request_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '请求到达时间',
`response_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '响应到达时间',
`request_content_type` VARCHAR(32) NOT NULL COMMENT '请求使用的 Content-Type',
`request_body` LONGTEXT NOT NULL COMMENT '请求的 Body',
`response_content_type` VARCHAR(32) NOT NULL COMMENT '响应使用的 Content-Type',
`response_body` LONGTEXT NOT NULL COMMENT '响应的 Body',
`user_agent` TEXT NOT NULL COMMENT 'http 客户端 User-Agent',
`server` VARCHAR(32) NOT NULL COMMENT 'response server',
`status` VARCHAR(32) NOT NULL COMMENT 'http response status',
`status_code` INT NOT NULL COMMENT 'http response status code',
`id` CHAR(36) NOT NULL COMMENT 'primary key',
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`deleted_at` DATETIME NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '删除时间, 1970-01-01 00:00:00 表示未删除',
`request_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP COMMENT '请求到达时间',
`response_at` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '响应到达时间',

`status` SMALLINT NULL COMMENT 'http response status',
`username` VARCHAR(128) NULL COMMENT '用户名',
`source` VARCHAR(128) NULL COMMENT '接入应用: dingtalk, vscode-plugin, jetbrains-plugin ...',
`prompt` MEDIUMTEXT NULL COMMENT '提示语',
`completion` LONGTEXT NULL COMMENT 'AI 回复多个 choices 中的一个',
`request_body` LONGTEXT NULL COMMENT '请求的 Body',
`response_body` LONGTEXT NULL COMMENT '响应的 Body',
`actual_request_body` LONGTEXT NULL COMMENT '实际调用大模型请求的 Body',
`actual_response_body` LONGTEXT NULL COMMENT '实际调用大模型响应的 Body',
`user_agent` TEXT NULL COMMENT 'http 客户端 User-Agent',
`x_request_id` VARCHAR(64) NULL COMMENT 'http 请求中的 X-Request-Id',

`auth_key` CHAR(64) NULL COMMENT 'auth key: api_key or token',
`client_id` char(36) NULL COMMENT '客户端 id',
`model_id` char(36) NULL COMMENT '模型 id',
`session_id` VARCHAR(64) NULL COMMENT '对话标识',

`email` VARCHAR(64) NULL COMMENT '用户邮箱',

`operation_id` VARCHAR(128) NULL COMMENT '调用的接口名称, HTTP Method + Path',

`res_func_call_name` VARCHAR(128) NULL COMMENT 'function_call name in response message',

`metadata` LONGTEXT NULL COMMENT '客户端要审计的其他信息',
PRIMARY KEY (`id`),
INDEX `idx_job_number` (`job_number`),
INDEX `idx_dingtalk_staff_id` (`dingtalk_staff_id`)
INDEX `idx_username` (`username`),
INDEX `idx_email` (`email`),
INDEX `idx_auth_key` (`auth_key`),
INDEX `idx_session_id` (`session_id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COMMENT 'AI 审计表';
Expand Down
1 change: 0 additions & 1 deletion api/proto/apps/aifunction/ai-function.proto
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ message ApplyRequest {
string functionName = 1 [(validate.rules).string = {min_len: 1}];
google.protobuf.Value functionParams = 2 [(validate.rules).message = {required: true}];
Background background = 3 [(validate.rules).message = {required: true}];
bool needAdjust = 4;
}

message Background {
Expand Down
144 changes: 144 additions & 0 deletions api/proto/apps/aiproxy/audit/audit.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
syntax = "proto3";

package erda.apps.aiproxy;
option go_package = "github.com/erda-project/erda-proto-go/apps/aiproxy/audit/pb";

import "google/api/annotations.proto";
import "apps/aiproxy/metadata/metadata.proto";
import "google/protobuf/timestamp.proto";
import "github.com/envoyproxy/protoc-gen-validate/validate/validate.proto";
import "common/http.proto";

service AuditService {
rpc Get(AuditGetRequest) returns (Audit) {
option(google.api.http) = {
get: "/api/ai-proxy/audits/{auditId}"
};
}
rpc Paging(AuditPagingRequest) returns (AuditPagingResponse) {
option(google.api.http) = {
get: "/api/ai-proxy/audits"
};
}
}

message Audit {
string id = 1;
google.protobuf.Timestamp createdAt = 2;
google.protobuf.Timestamp updatedAt = 3;
google.protobuf.Timestamp deletedAt = 4;
google.protobuf.Timestamp requestAt = 5;
google.protobuf.Timestamp responseAt = 6;

string authKey = 7;
int32 status = 8;
string prompt = 9;
string completion = 10;
string requestBody = 11;
string responseBody = 12;
string actualRequestBody = 13;
string actualResponseBody = 14;
string userAgent = 15;
string xRequestId = 16;

string clientId = 17;
string modelId = 18;
string sessionId = 19;

string username = 20;
string email = 21;

string bizSource = 22; // 客户端定义的业务来源
string operationId = 23;

string responseFunctionCallName = 24;

Metadata metadata = 25;
}

message AuditCreateRequestWhenReceived {
google.protobuf.Timestamp requestAt = 1;
string authKey = 2;
string requestBody = 3;
string userAgent = 4;
string xRequestId = 5;

string requestContentType = 6;
string requestHeader = 7;

string identityPhoneNumber = 8;
string identityJobNumber = 9;

string dingtalkStaffId = 10;
string dingtalkChatType = 11;
string dingtalkChatTitle = 12;
string dingtalkChatId = 13;

string username = 15;
string email = 16;
string bizSource = 17;
}

message AuditUpdateRequestAfterContextParsed {
string auditId = 1 [(validate.rules).string = {len: 36}];
string prompt = 2;

string clientId = 3 [(validate.rules).string = {len: 36}];
string modelId = 4 [(validate.rules).string = {len: 36}];
string sessionId = 5 [(validate.rules).string = {ignore_empty: true, len: 36}];

string bizSource = 7;
string operationId = 8;

string requestFunctionCallName = 9;

// parsed from client token
string dingtalkStaffId = 10;
string email = 11;
string identityJobNumber = 12;
string username = 13;
string identityPhoneNumber = 14;
}

message AuditUpdateRequestAfterLLMDirectorInvoke {
string auditId = 1 [(validate.rules).string = {len: 36}];
string actualRequestBody = 2;
string actualRequestURL = 3;
string actualRequestHeader = 4;
}

message AuditUpdateRequestAfterLLMResponse {
string auditId = 1 [(validate.rules).string = {len: 36}];
google.protobuf.Timestamp responseAt = 2; // first response
google.protobuf.Timestamp responseStreamDoneAt = 3;
int32 status = 4;
string actualResponseBody = 5;
string actualResponseHeader = 6;

string responseContentType = 7;
}

message AuditUpdateRequestAfterLLMDirectorResponse {
string auditId = 1 [(validate.rules).string = {len: 36}];
string completion = 2;
string responseBody = 3;
string responseHeader = 4;
string responseFunctionCallName = 5;
}

message AuditGetRequest {
string auditId = 1 [(validate.rules).string = {len: 36}];
}

message AuditPagingRequest {
int64 pageNum = 1;
int64 pageSize = 2;

repeated string ids = 3 [(validate.rules).repeated.items.string = {len: 36}];
string source = 4;
}

message AuditPagingResponse {
int64 total = 1;
repeated Audit list = 2;
}
42 changes: 42 additions & 0 deletions api/proto/dop/ai/ai.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
syntax = "proto3";

package erda.dop.ai;
option go_package = "github.com/erda-project/erda-proto-go/dop/ai/pb";

import "google/api/annotations.proto";
import "google/protobuf/timestamp.proto";
import "common/openapi.proto";
import "google/protobuf/struct.proto";
import "common/http.proto";
import "github.com/envoyproxy/protoc-gen-validate/validate/validate.proto";

service AIRelated {
option(erda.common.openapi_service) = {
service: "dop",
auth: {
check_login: true,
check_token: true,
}
};

rpc EXPORT_AI_GENERATED_TESTCASES (TestCaseAIGeneratedExportRequest) returns (TestCaseAIGeneratedExportResponse) {
option (google.api.http) = {
post: "/api/testcases/actions/export-ai-testcases",
};
option (erda.common.openapi) = {
path: "/api/testcases/actions/export-ai-testcases",
doc: "summary: 导出 AI 生成的测试用例",
};
};
}

message TestCaseAIGeneratedExportRequest {
google.protobuf.Value testCasePagingRequest = 1;
string fileType = 2;
string locale = 3;
google.protobuf.Value testSetCasesMetas = 4;
}

message TestCaseAIGeneratedExportResponse {
uint64 data = 1;
}
1 change: 1 addition & 0 deletions apistructs/performance_measure.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type PersonalContributionRequest struct {
UserEmail string `json:"userEmail"`
ProjectIDs []uint64 `json:"projectIDs"`
GroupByProject bool `json:"groupByProject"`
GroupByDay bool `json:"groupByDay"`
}

type FuncPointTrendRequest struct {
Expand Down
73 changes: 48 additions & 25 deletions apistructs/testcase.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,22 @@ const (
// TestCase 测试用例详情
type TestCase struct {
ID uint64 `json:"id"`
Name string `json:"name"` // 用例名称
Priority TestCasePriority `json:"priority"` // 优先级
PreCondition string `json:"preCondition"` // 前置条件
Desc string `json:"desc"` // 补充说明
Recycled *bool `json:"recycled"` // 是否回收,0:不回收,1:回收
TestSetID uint64 `json:"testSetID"` // 所属测试集 ID
ProjectID uint64 `json:"projectID"` // 当前项目id,用于权限校验
CreatorID string `json:"creatorID"` // 创建者 ID
UpdaterID string `json:"updaterID"` // 更新者 ID
BugIDs []uint64 `json:"bugIDs"` // 关联缺陷 IDs
LabelIDs []uint64 `json:"labelIDs"` // 关联缺陷 IDs
Attachments []string `json:"attachments"` // 上传附件 uuid 列表,仅供创建时使用
StepAndResults []TestCaseStepAndResult `json:"stepAndResults"` // 步骤及结果
Labels []ProjectLabel `json:"labels"` // 标签
APIs []*ApiTestInfo `json:"apis"` // 接口测试集合
Name string `json:"name"` // 用例名称
Priority TestCasePriority `json:"priority"` // 优先级
PreCondition string `json:"preCondition"` // 前置条件
Desc string `json:"desc"` // 补充说明
Recycled *bool `json:"recycled"` // 是否回收,0:不回收,1:回收
TestSetID uint64 `json:"testSetID"` // 所属测试集 ID
TestSetDir string `json:"testSetDir,omitempty"` // 所属测试集 Directory
ProjectID uint64 `json:"projectID"` // 当前项目id,用于权限校验
CreatorID string `json:"creatorID"` // 创建者 ID
UpdaterID string `json:"updaterID"` // 更新者 ID
BugIDs []uint64 `json:"bugIDs"` // 关联缺陷 IDs
LabelIDs []uint64 `json:"labelIDs"` // 关联缺陷 IDs
Attachments []string `json:"attachments"` // 上传附件 uuid 列表,仅供创建时使用
StepAndResults []TestCaseStepAndResult `json:"stepAndResults"` // 步骤及结果
Labels []ProjectLabel `json:"labels"` // 标签
APIs []*ApiTestInfo `json:"apis"` // 接口测试集合
APICount TestCaseAPICount `json:"apiCount"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Expand Down Expand Up @@ -115,15 +116,20 @@ type TestCaseGetResponse struct {

// TestCaseCreateRequest POST 创建测试用例请求
type TestCaseCreateRequest struct {
ProjectID uint64 `json:"projectID"` // 当前项目 ID,用于权限校验
TestSetID uint64 `json:"testSetID"` // 所属测试集 ID
Name string `json:"name"` // 用例名称
PreCondition string `json:"preCondition"` // 前置条件
StepAndResults []TestCaseStepAndResult `json:"stepAndResults"` // 步骤及结果
APIs []*ApiTestInfo `json:"apis"` // 接口测试集合
Desc string `json:"desc"` // 补充说明
Priority TestCasePriority `json:"priority"` // 优先级
LabelIDs []uint64 `json:"labelIDs"` // 关联缺陷 IDs
TestCaseID uint64 `json:"testcaseID,omitempty"` // 创建测试用例成功后可以回填,专用于 AI 生成测试用例的场景
ProjectID uint64 `json:"projectID"` // 当前项目 ID,用于权限校验
ParentTestSetID uint64 `json:"parentTestSetID"` // 所属测试集的 Parent 测试集 ID
ParentTestSetDir string `json:"parentTestSetDir"` // 所属测试集的 Parent 测试集 Directory
TestSetID uint64 `json:"testSetID"` // 所属测试集 ID
TestSetDir string `json:"testSetDir"` // 所属测试集 Directory
TestSetName string `json:"testSetName"` // 所属测试集 Name
Name string `json:"name"` // 用例名称
PreCondition string `json:"preCondition"` // 前置条件
StepAndResults []TestCaseStepAndResult `json:"stepAndResults"` // 步骤及结果
APIs []*ApiTestInfo `json:"apis"` // 接口测试集合
Desc string `json:"desc"` // 补充说明
Priority TestCasePriority `json:"priority"` // 优先级
LabelIDs []uint64 `json:"labelIDs"` // 关联缺陷 IDs

IdentityInfo
}
Expand Down Expand Up @@ -352,8 +358,25 @@ type TestCaseExportRequest struct {

FileType TestCaseFileType `schema:"fileType"`

Locale string `schema:"-"`
Locale string `schema:"-"`
TestSetCasesMetas []TestCasesMeta `schema:"testSetCasesMetas"`
}

// TestCaseMeta 用于关联分组生成的测试用例与对应的需求
type TestCasesMeta struct {
Reqs []TestCaseCreateRequest `json:"testCaseCreateReqs,omitempty"` // 当前项目 ID 对应的创建测试用例请求
RequirementName string `json:"requirementName"` // 需求对应的 issue 的 Title
RequirementID uint64 `json:"issueID"` // 需求对应的 issueID
}

// TestCaseMeta 用于关联单组生成的测试用例与对应的需求
type TestCaseMeta struct {
Req TestCaseCreateRequest `json:"testCaseCreateReq,omitempty"` // 当前项目 ID 对应的创建测试用例请求
RequirementName string `json:"requirementName"` // 需求对应的 issue 的 Title
RequirementID uint64 `json:"issueID"` // 需求对应的 issueID
TestCaseID uint64 `json:"testcaseID,omitempty"` // 创建测试用例成功返回的测试用例 ID
}

type TestCaseExportResponse struct {
Header
Data uint64 `json:"data"`
Expand Down
1 change: 1 addition & 0 deletions apistructs/testset.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type TestSetWithAncestors struct {

type TestSetGetRequest struct {
ID uint64 `json:"id"`
IdentityInfo
}
type TestSetGetResponse struct {
Header
Expand Down
Loading

0 comments on commit e959a21

Please sign in to comment.