Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion app/protos/grpc.proto
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,8 @@ service Yak {

// 从规则中提取数据
rpc QueryMITMRuleExtractedData(QueryMITMRuleExtractedDataRequest) returns (QueryMITMRuleExtractedDataResponse);
// 按规则名 + 提取内容聚合(JOIN http_flows,可按 Host / RuntimeId 等过滤)
rpc QueryMITMExtractedAggregate(QueryMITMExtractedAggregateRequest) returns (QueryMITMExtractedAggregateResponse);
rpc ExportMITMRuleExtractedData(ExportMITMRuleExtractedDataRequest) returns (stream ExportMITMRuleExtractedDataResponse);
rpc DeleteMITMRuleExtractedData(DeleteMITMRuleExtractedDataRequest) returns (Empty);
rpc DeduplicateMITMRuleExtractedData(DeduplicateMITMRuleExtractedDataRequest) returns (DeduplicateMITMRuleExtractedDataResponse);
Expand Down Expand Up @@ -1955,7 +1957,7 @@ message AIEventFilter {

repeated string NodeId = 8;

bool UseOR = 9; //默认是AND关系,也就是多条件同时满足,如果UseOR是true,那是满足任一条件即可
bool UseOR = 9; // 默认是 AND 关系,也就是多条件同时满足,如果 UseOR 是 true,那么就是满足任一条件即可
}

message AIEventQueryRequest {
Expand Down Expand Up @@ -2845,6 +2847,15 @@ message ThirdPartyApplicationConfig {
string Endpoint = 14;
bool EnableEndpoint = 15;
repeated KVPair Headers = 16;
bool EnableThinking = 17;
// 以下为模型采样/推理相关可选参数;未设置时不写入上游请求(由模型或网关默认行为决定)
optional int64 MaxTokens = 18;
optional double Temperature = 19;
optional double TopP = 20;
optional int64 TopK = 21;
optional double FrequencyPenalty = 22;
optional string ReasoningEffort = 23;
optional bool EnableThinkingOpt = 24;
}

message DiagnoseNetworkRequest {
Expand Down Expand Up @@ -3331,6 +3342,36 @@ message DeduplicateMITMRuleExtractedDataResponse {
int64 DeletedCount = 1;
}

// MITM 提取聚合。规则组维度:RuleGroup、RuleGroupKeyword、OnlyUncategorizedRules 互斥(实现上精确 RuleGroup 优先)。
message QueryMITMExtractedAggregateRequest {
Paging Pagination = 1;
string HostContains = 2;
string RuntimeId = 3;
repeated string RuleVerbose = 4;
string RuleVerboseKeyword = 5;
int64 UpdatedAtSince = 6;
string RuleGroup = 7;
bool OnlyUncategorizedRules = 8;
bool IncludeDistinctRuleGroups = 9;
QueryHTTPFlowRequest HttpFlowFilter = 10;
string RuleGroupKeyword = 11;
}

message MITMExtractedAggregateRow {
string RuleVerbose = 1;
string DisplayData = 2;
int64 HitCount = 3;
int64 LatestUpdatedAt = 4;
repeated string SampleTraceIds = 5;
}

message QueryMITMExtractedAggregateResponse {
repeated MITMExtractedAggregateRow Data = 1;
int64 Total = 2;
Paging Pagination = 3;
repeated string DistinctRuleGroups = 4;
}

message ExportProjectRequest {
string ProjectName = 1;
string Password = 2;
Expand Down Expand Up @@ -6546,6 +6587,11 @@ message GetHTTPFlowBodyByIdRequest {
bool IsRisk = 5;
}

message MITMExtractAggregateFlowFilterRow {
string RuleVerbose = 1;
string DisplayData = 2;
}

message QueryHTTPFlowRequest {
Paging Pagination = 1;
string SourceType = 2;
Expand Down Expand Up @@ -6614,6 +6660,7 @@ message QueryHTTPFlowRequest {

// 高级配置的hostname过滤(模糊匹配)
repeated string HostnameFilter = 49;
repeated MITMExtractAggregateFlowFilterRow MitmExtractAggregateFilterRows = 50;
}

message HTTPFlowsToOnlineRequest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,28 @@
.config-form {
padding: 24px 24px 0 24px;
.ai-third-party-application-config-collapse {
.panel-heard {
display: flex;
align-items: center;
gap: 4px;
font-size: 12px;
line-height: 16px;
.title {
font-weight: 500;
color: var(--Colors-Use-Neutral-Text-1-Title);
}
.tip {
color: var(--Colors-Use-Neutral-Text-4-Help-text);
}
}
:global(.ant-collapse-header:hover) {
.panel-heard {
background-color: var(--Colors-Use-Basic-Background);
.title {
color: var(--Colors-Use-Main-Primary);
}
}
}
:global {
.ant-collapse-item {
background-color: var(--Colors-Use-Basic-Background);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,20 @@ export interface ThirdPartyApplicationConfig {
Endpoint?: string
EnableEndpoint?: boolean
Headers?: KVPair[]
/**为空,不传给后端 */
MaxTokens?: number
/**为空,不传给后端 */
Temperature?: number
/**为空,不传给后端 */
TopP?: number
/**为空,不传给后端 */
TopK?: number
/**为空,不传给后端 */
FrequencyPenalty?: number
/**为空,不传给后端 */
ReasoningEffort?: string
/**为空,不传给后端 */
EnableThinkingOpt?: boolean
}
type TenumBuffer = Buffer | Uint8Array

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import classNames from 'classnames'
import { TFunction, useI18nNamespaces } from '@/i18n/useI18nNamespaces'
import { OutlineClipboardcopyIcon } from '@/assets/icon/outline'
import { setClipboardText } from '@/utils/clipboard'
import { YakitInputNumber } from '../yakitUI/YakitInputNumber/YakitInputNumber'
const { ipcRenderer } = window.require('electron')

export interface ThirdPartyAppConfigItemTemplate {
Expand Down Expand Up @@ -991,7 +992,7 @@ export const NewAIThirdPartyApplicationConfigBase: React.FC<NewAIThirdPartyAppli
<Form
form={form}
layout={FormProps?.layout ?? 'horizontal'}
labelCol={{ span: FormProps?.labelCol ?? 5 }}
labelCol={{ span: FormProps?.labelCol ?? 6 }}
wrapperCol={{ span: FormProps?.wrapperCol ?? 18 }}
initialValues={initialValues}
onValuesChange={(changedValues, allValues) => {
Expand Down Expand Up @@ -1048,7 +1049,7 @@ export const NewAIThirdPartyApplicationConfigBase: React.FC<NewAIThirdPartyAppli
bordered={false}
className={styles['ai-third-party-application-config-collapse']}
>
<Collapse.Panel header="高级配置" key="1" forceRender={true}>
<YakitCollapse.YakitPanel header="高级配置" key="1" forceRender={true}>
{/* 可选的表单项 */}
{renderOptionalFormItems()}
<Form.Item label={'Header'} name="Headers">
Expand Down Expand Up @@ -1084,7 +1085,53 @@ export const NewAIThirdPartyApplicationConfigBase: React.FC<NewAIThirdPartyAppli
添加
</YakitButton>
</Form.Item>
</Collapse.Panel>
</YakitCollapse.YakitPanel>
<YakitCollapse.YakitPanel
header={
<div className={styles['panel-heard']}>
<span className={styles['title']}>模型配置</span>
<span className={styles['tip']}>以下值可以为空,为空代表不设置</span>
</div>
}
key="2"
>
<Form.Item label="Enable Thiking" name="EnableThinkingOpt">
<YakitSelect
options={[
{ label: '不设置', value: 'no-set' },
{ label: '开启', value: 'open' },
{ label: '不开启', value: 'close' },
]}
/>
</Form.Item>
<Form.Item label="Max Tokens" name="MaxTokens">
<YakitInputNumber min={1} max={163840} />
</Form.Item>
<Form.Item label="Temperature" name="Temperature">
<YakitInputNumber min={0} max={2} step={0.1} />
</Form.Item>
<Form.Item label="Top-P" name="TopP">
<YakitInputNumber min={0} max={1} step={0.1} />
</Form.Item>
<Form.Item label="Top-K" name="TopK">
<YakitInputNumber min={0} max={100} />
</Form.Item>
<Form.Item label="Frequency Penalty" name="FrequencyPenalty">
<YakitInputNumber min={0} max={2} step={0.1} />
</Form.Item>
<Form.Item label="Reasoning Effort" name="ReasoningEffort">
<YakitSelect
options={[
{ label: '不设置', value: 'no-set' },
{ label: 'none', value: 'none' },
{ label: 'low', value: 'low' },
{ label: 'middle', value: 'middle' },
{ label: 'high', value: 'high' },
{ label: 'xhigh', value: 'xhigh' },
]}
/>
</Form.Item>
</YakitCollapse.YakitPanel>
</YakitCollapse>
</Form>
<div className={styles['config-footer']}>{footer}</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import { AIModelTypeEnum, AIModelTypeInterFileNameEnum } from '../../defaultCons
import { YakitInput } from '@/components/yakitUI/YakitInput/YakitInput'
import { yakitNotify } from '@/utils/notification'
import emiter from '@/utils/eventBus/eventBus'
import { cloneDeep } from 'lodash'
import { cloneDeep, has, isNil } from 'lodash'
import { ThirdPartyApplicationConfig } from '@/components/configNetwork/ConfigNetworkPage'
import { showYakitModal } from '@/components/yakitUI/YakitModal/YakitModalConfirm'
import styles from './AIModelForm.module.scss'
Expand Down Expand Up @@ -165,8 +165,61 @@ export const buildAIConfigHealthCheckFormValues = (config: ThirdPartyApplication
endpoint: config.Endpoint ?? '',
enable_endpoint: config.EnableEndpoint ?? false,
Headers: config.Headers ?? [],
EnableThinkingOpt: has(config, 'EnableThinkingOpt')
? `${config.EnableThinkingOpt === true ? 'open' : 'close'}`
: 'no-set',
MaxTokens: config?.MaxTokens,
Temperature: config?.Temperature,
TopP: config?.TopP,
TopK: config?.TopK,
FrequencyPenalty: config?.FrequencyPenalty,
ReasoningEffort: config?.ReasoningEffort || 'no-set',
} as AIThirdPartyApplicationConfig
}

const formValueToAIConfigProvider = (res) => {
const date: ThirdPartyApplicationConfig = {
Type: res.Type,
APIKey: res.api_key,
APIType: normalizeAIAPIType(res.api_type),
Domain: res.domain,
Proxy: res.proxy,
NoHttps: res.no_https,
ExtraParams: [],
BaseURL: res.base_url,
Endpoint: res.endpoint,
EnableEndpoint: res.enable_endpoint,
Headers: res.Headers,
/** 下面这些字段ai中没有 */
// UserIdentifier: "",
// UserSecret: "",
// Namespace: "",
// WebhookURL: "",
// Disabled: false
}
if (has(res, 'EnableThinkingOpt') && res.EnableThinkingOpt !== 'no-set') {
date.EnableThinkingOpt = res.EnableThinkingOpt === 'open'
}
if (has(res, 'MaxTokens') && !isNil(res.MaxTokens)) {
date.MaxTokens = res.MaxTokens
}
if (has(res, 'Temperature') && !isNil(res.Temperature)) {
date.Temperature = res.Temperature
}
if (has(res, 'TopP') && !isNil(res.TopP)) {
date.TopP = res.TopP
}
if (has(res, 'TopK') && !isNil(res.TopK)) {
date.TopK = res.TopK
}
if (has(res, 'FrequencyPenalty') && !isNil(res.FrequencyPenalty)) {
date.FrequencyPenalty = res.FrequencyPenalty
}
if (has(res, 'ReasoningEffort') && res.ReasoningEffort !== 'no-set') {
date.ReasoningEffort = res.ReasoningEffort
}
return date
}
export const AIModelForm: React.FC<AIModelFormProps> = React.memo((props) => {
const { item, aiModelType, onSuccess, onClose } = props

Expand Down Expand Up @@ -229,23 +282,7 @@ export const AIModelForm: React.FC<AIModelFormProps> = React.memo((props) => {
const newItem: AIModelConfig = {
ProviderId: res.api_key_id,
Provider: {
Type: res.Type,
APIKey: res.api_key,
APIType: normalizeAIAPIType(res.api_type),
Domain: res.domain,
Proxy: res.proxy,
NoHttps: res.no_https,
ExtraParams: [],
BaseURL: res.base_url,
Endpoint: res.endpoint,
EnableEndpoint: res.enable_endpoint,
Headers: res.Headers,
/** 下面这些字段ai中没有 */
// UserIdentifier: "",
// UserSecret: "",
// Namespace: "",
// WebhookURL: "",
// Disabled: false
...formValueToAIConfigProvider(res),
},
ModelName: res.model,
ExtraParams: [],
Expand Down
Loading