feat: add fallback mode for AI agents and update knowledge base handling
- Introduced AIAgentFallbackMode with options for NoAnswer and SuggestRetry. - Updated AI agent edit component to include fallback mode selection. - Modified API types and payloads to accommodate fallback mode. - Removed deprecated KnowledgeFallbackMode and related logic from knowledge base. - Adjusted knowledge retrieval and response handling to utilize new fallback logic. - Updated tests to reflect changes in fallback mode handling for AI agents.
This commit is contained in:
@@ -17,7 +17,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
enumsPkgName = "enums"
|
enumsPkgName = "enums"
|
||||||
enumsDir = "internal/pkg/enums"
|
enumsDir = "internal/pkg/enums"
|
||||||
outputPath = "web/lib/generated/enums.ts"
|
outputPath = "dashboard/lib/generated/enums.ts"
|
||||||
)
|
)
|
||||||
|
|
||||||
type enumValueType string
|
type enumValueType string
|
||||||
|
|||||||
Vendored
+1
@@ -87,6 +87,7 @@ func buildSeedItems(aiConfigID int64, knowledgeIDs []int64, defaultTeamIDs strin
|
|||||||
ReplyTimeoutSeconds: 180,
|
ReplyTimeoutSeconds: 180,
|
||||||
TeamIDs: defaultTeamIDs,
|
TeamIDs: defaultTeamIDs,
|
||||||
HandoffMode: enums.AIAgentHandoffModeWaitPool,
|
HandoffMode: enums.AIAgentHandoffModeWaitPool,
|
||||||
|
FallbackMode: enums.AIAgentFallbackModeSuggestRetry,
|
||||||
FallbackMessage: "我暂时没有找到足够准确的信息。你可以补充具体的问题,我再继续帮你查。",
|
FallbackMessage: "我暂时没有找到足够准确的信息。你可以补充具体的问题,我再继续帮你查。",
|
||||||
KnowledgeIDs: utils.JoinInt64s(knowledgeIDs),
|
KnowledgeIDs: utils.JoinInt64s(knowledgeIDs),
|
||||||
SkillIDs: defaultSkillIDs,
|
SkillIDs: defaultSkillIDs,
|
||||||
|
|||||||
Vendored
-3
@@ -118,7 +118,6 @@ func ensureKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) {
|
|||||||
ChunkMaxTokens: 400,
|
ChunkMaxTokens: 400,
|
||||||
ChunkOverlapTokens: 40,
|
ChunkOverlapTokens: 40,
|
||||||
AnswerMode: int(enums.KnowledgeAnswerModeStrict),
|
AnswerMode: int(enums.KnowledgeAnswerModeStrict),
|
||||||
FallbackMode: int(enums.KnowledgeFallbackModeNoAnswer),
|
|
||||||
AuditFields: models.AuditFields{
|
AuditFields: models.AuditFields{
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
CreateUserID: constants.SystemAuditUserID,
|
CreateUserID: constants.SystemAuditUserID,
|
||||||
@@ -168,7 +167,6 @@ func ensureFAQKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) {
|
|||||||
ChunkMaxTokens: 0,
|
ChunkMaxTokens: 0,
|
||||||
ChunkOverlapTokens: 0,
|
ChunkOverlapTokens: 0,
|
||||||
AnswerMode: int(enums.KnowledgeAnswerModeStrict),
|
AnswerMode: int(enums.KnowledgeAnswerModeStrict),
|
||||||
FallbackMode: int(enums.KnowledgeFallbackModeNoAnswer),
|
|
||||||
Remark: "测试数据初始化自动生成",
|
Remark: "测试数据初始化自动生成",
|
||||||
AuditFields: models.AuditFields{
|
AuditFields: models.AuditFields{
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
@@ -197,7 +195,6 @@ func ensureFAQKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) {
|
|||||||
"chunk_max_tokens": 0,
|
"chunk_max_tokens": 0,
|
||||||
"chunk_overlap_tokens": 0,
|
"chunk_overlap_tokens": 0,
|
||||||
"answer_mode": int(enums.KnowledgeAnswerModeStrict),
|
"answer_mode": int(enums.KnowledgeAnswerModeStrict),
|
||||||
"fallback_mode": int(enums.KnowledgeFallbackModeNoAnswer),
|
|
||||||
"remark": "测试数据初始化自动生成",
|
"remark": "测试数据初始化自动生成",
|
||||||
"update_user_id": constants.SystemAuditUserID,
|
"update_user_id": constants.SystemAuditUserID,
|
||||||
"update_user_name": constants.SystemAuditUserName,
|
"update_user_name": constants.SystemAuditUserName,
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ import {
|
|||||||
} from "@/lib/api/admin";
|
} from "@/lib/api/admin";
|
||||||
import { getEnumOptions } from "@/lib/enums";
|
import { getEnumOptions } from "@/lib/enums";
|
||||||
import {
|
import {
|
||||||
|
AIAgentFallbackMode,
|
||||||
|
AIAgentFallbackModeLabels,
|
||||||
AIAgentHandoffMode,
|
AIAgentHandoffMode,
|
||||||
AIAgentHandoffModeLabels,
|
AIAgentHandoffModeLabels,
|
||||||
AIModelType,
|
AIModelType,
|
||||||
@@ -93,6 +95,7 @@ const schema = z.object({
|
|||||||
.number()
|
.number()
|
||||||
.min(0, "回复超时秒数必须是大于等于 0 的整数"),
|
.min(0, "回复超时秒数必须是大于等于 0 的整数"),
|
||||||
handoffMode: z.string().trim().min(1, "请选择转人工模式"),
|
handoffMode: z.string().trim().min(1, "请选择转人工模式"),
|
||||||
|
fallbackMode: z.string().trim().min(1, "请选择兜底策略"),
|
||||||
fallbackMessage: z.string().trim(),
|
fallbackMessage: z.string().trim(),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -118,6 +121,13 @@ const handoffModeOptions = getEnumOptions(AIAgentHandoffModeLabels).map(
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const fallbackModeOptions = getEnumOptions(AIAgentFallbackModeLabels).map(
|
||||||
|
(option) => ({
|
||||||
|
value: String(option.value),
|
||||||
|
label: option.label,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
function buildForm(item: AIAgent | null): EditForm {
|
function buildForm(item: AIAgent | null): EditForm {
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return {
|
return {
|
||||||
@@ -129,6 +139,7 @@ function buildForm(item: AIAgent | null): EditForm {
|
|||||||
welcomeMessage: "",
|
welcomeMessage: "",
|
||||||
replyTimeoutSeconds: 180,
|
replyTimeoutSeconds: 180,
|
||||||
handoffMode: String(AIAgentHandoffMode.WaitPool),
|
handoffMode: String(AIAgentHandoffMode.WaitPool),
|
||||||
|
fallbackMode: String(AIAgentFallbackMode.NoAnswer),
|
||||||
fallbackMessage: "",
|
fallbackMessage: "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -141,6 +152,7 @@ function buildForm(item: AIAgent | null): EditForm {
|
|||||||
welcomeMessage: item.welcomeMessage || "",
|
welcomeMessage: item.welcomeMessage || "",
|
||||||
replyTimeoutSeconds: item.replyTimeoutSeconds ?? 180,
|
replyTimeoutSeconds: item.replyTimeoutSeconds ?? 180,
|
||||||
handoffMode: String(item.handoffMode),
|
handoffMode: String(item.handoffMode),
|
||||||
|
fallbackMode: String(item.fallbackMode),
|
||||||
fallbackMessage: item.fallbackMessage || "",
|
fallbackMessage: item.fallbackMessage || "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -163,6 +175,7 @@ function buildPayload(
|
|||||||
replyTimeoutSeconds: Number(form.replyTimeoutSeconds),
|
replyTimeoutSeconds: Number(form.replyTimeoutSeconds),
|
||||||
teamIds,
|
teamIds,
|
||||||
handoffMode: Number(form.handoffMode),
|
handoffMode: Number(form.handoffMode),
|
||||||
|
fallbackMode: Number(form.fallbackMode),
|
||||||
fallbackMessage: form.fallbackMessage.trim(),
|
fallbackMessage: form.fallbackMessage.trim(),
|
||||||
knowledgeIds,
|
knowledgeIds,
|
||||||
skillIds,
|
skillIds,
|
||||||
@@ -737,13 +750,34 @@ function EditDialogBody({
|
|||||||
</FieldContent>
|
</FieldContent>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
|
<Field data-invalid={!!errors.fallbackMode}>
|
||||||
|
<FieldLabel>知识库兜底策略</FieldLabel>
|
||||||
|
<FieldContent className="space-y-3">
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="fallbackMode"
|
||||||
|
render={({ field }) => (
|
||||||
|
<OptionCombobox
|
||||||
|
value={field.value}
|
||||||
|
options={fallbackModeOptions}
|
||||||
|
placeholder="请选择兜底策略"
|
||||||
|
searchPlaceholder="搜索兜底策略"
|
||||||
|
emptyText="未找到兜底策略"
|
||||||
|
onChange={field.onChange}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<FieldError errors={[errors.fallbackMode]} />
|
||||||
|
</FieldContent>
|
||||||
|
</Field>
|
||||||
|
|
||||||
<Field data-invalid={!!errors.fallbackMessage}>
|
<Field data-invalid={!!errors.fallbackMessage}>
|
||||||
<FieldLabel htmlFor="ai-agent-fallback-message">
|
<FieldLabel htmlFor="ai-agent-fallback-message">
|
||||||
兜底文案
|
兜底文案
|
||||||
</FieldLabel>
|
</FieldLabel>
|
||||||
<FieldContent>
|
<FieldContent>
|
||||||
<div className="text-xs text-muted-foreground mb-1">
|
<div className="text-xs text-muted-foreground mb-1">
|
||||||
仅在兜底模式为“直接声明无答案”或“引导补充信息”时使用。转人工已统一改为 AI Graph Tool,不再通过兜底模式直接触发。
|
知识库未命中或命中证据不足时,会按这里的策略和文案进行兜底回复。转人工请通过 Graph Tool 配合转人工模式实现。
|
||||||
</div>
|
</div>
|
||||||
<Textarea
|
<Textarea
|
||||||
id="ai-agent-fallback-message"
|
id="ai-agent-fallback-message"
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ import {
|
|||||||
KnowledgeChunkProviderLabels,
|
KnowledgeChunkProviderLabels,
|
||||||
KnowledgeAnswerMode,
|
KnowledgeAnswerMode,
|
||||||
KnowledgeAnswerModeLabels,
|
KnowledgeAnswerModeLabels,
|
||||||
KnowledgeFallbackMode,
|
|
||||||
KnowledgeFallbackModeLabels,
|
|
||||||
} from "@/lib/generated/enums";
|
} from "@/lib/generated/enums";
|
||||||
import { getEnumLabel, getEnumOptions } from "@/lib/enums";
|
import { getEnumLabel, getEnumOptions } from "@/lib/enums";
|
||||||
|
|
||||||
@@ -60,7 +58,6 @@ const emptyForm: EditForm = {
|
|||||||
chunkMaxTokens: "400",
|
chunkMaxTokens: "400",
|
||||||
chunkOverlapTokens: "40",
|
chunkOverlapTokens: "40",
|
||||||
answerMode: String(KnowledgeAnswerMode.Strict),
|
answerMode: String(KnowledgeAnswerMode.Strict),
|
||||||
fallbackMode: String(KnowledgeFallbackMode.NoAnswer),
|
|
||||||
remark: "",
|
remark: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,7 +73,6 @@ const knowledgeBaseFormSchema = z.object({
|
|||||||
chunkMaxTokens: z.string().trim().min(1, "请输入最大 token 数"),
|
chunkMaxTokens: z.string().trim().min(1, "请输入最大 token 数"),
|
||||||
chunkOverlapTokens: z.string().trim().min(1, "请输入重叠 token 数"),
|
chunkOverlapTokens: z.string().trim().min(1, "请输入重叠 token 数"),
|
||||||
answerMode: z.string().trim().min(1, "请选择回答模式"),
|
answerMode: z.string().trim().min(1, "请选择回答模式"),
|
||||||
fallbackMode: z.string().trim().min(1, "请选择回退模式"),
|
|
||||||
remark: z.string().trim().max(500, "备注最多500个字符"),
|
remark: z.string().trim().max(500, "备注最多500个字符"),
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -106,7 +102,6 @@ function buildForm(item: KnowledgeBase | null): EditForm {
|
|||||||
chunkMaxTokens: String(item.chunkMaxTokens),
|
chunkMaxTokens: String(item.chunkMaxTokens),
|
||||||
chunkOverlapTokens: String(item.chunkOverlapTokens),
|
chunkOverlapTokens: String(item.chunkOverlapTokens),
|
||||||
answerMode: String(item.answerMode),
|
answerMode: String(item.answerMode),
|
||||||
fallbackMode: String(item.fallbackMode),
|
|
||||||
remark: item.remark || "",
|
remark: item.remark || "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -124,7 +119,6 @@ function buildPayload(form: EditForm): CreateKnowledgeBasePayload {
|
|||||||
chunkMaxTokens: Number(form.chunkMaxTokens),
|
chunkMaxTokens: Number(form.chunkMaxTokens),
|
||||||
chunkOverlapTokens: Number(form.chunkOverlapTokens),
|
chunkOverlapTokens: Number(form.chunkOverlapTokens),
|
||||||
answerMode: Number(form.answerMode),
|
answerMode: Number(form.answerMode),
|
||||||
fallbackMode: Number(form.fallbackMode),
|
|
||||||
remark: form.remark.trim(),
|
remark: form.remark.trim(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -477,43 +471,6 @@ function KnowledgeBaseFormDialogBody({
|
|||||||
<FieldError errors={[errors.answerMode]} />
|
<FieldError errors={[errors.answerMode]} />
|
||||||
</FieldContent>
|
</FieldContent>
|
||||||
</Field>
|
</Field>
|
||||||
<Field data-invalid={!!errors.fallbackMode}>
|
|
||||||
<FieldLabel htmlFor="kb-fallback-mode">回退模式</FieldLabel>
|
|
||||||
<FieldContent>
|
|
||||||
<Controller
|
|
||||||
control={control}
|
|
||||||
name="fallbackMode"
|
|
||||||
render={({ field }) => (
|
|
||||||
<Select value={field.value} onValueChange={field.onChange}>
|
|
||||||
<SelectTrigger
|
|
||||||
id="kb-fallback-mode"
|
|
||||||
aria-invalid={!!errors.fallbackMode}
|
|
||||||
>
|
|
||||||
<SelectValue placeholder="选择回退模式">
|
|
||||||
{field.value
|
|
||||||
? getEnumLabel(
|
|
||||||
KnowledgeFallbackModeLabels,
|
|
||||||
Number(field.value),
|
|
||||||
)
|
|
||||||
: undefined}
|
|
||||||
</SelectValue>
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{getEnumOptions(KnowledgeFallbackModeLabels).map((option) => (
|
|
||||||
<SelectItem
|
|
||||||
key={option.value}
|
|
||||||
value={String(option.value)}
|
|
||||||
>
|
|
||||||
{option.label}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FieldError errors={[errors.fallbackMode]} />
|
|
||||||
</FieldContent>
|
|
||||||
</Field>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Field data-invalid={!!errors.remark}>
|
<Field data-invalid={!!errors.remark}>
|
||||||
|
|||||||
@@ -208,6 +208,8 @@ export type AIAgent = {
|
|||||||
teams: { id: number; name: string }[]
|
teams: { id: number; name: string }[]
|
||||||
handoffMode: number
|
handoffMode: number
|
||||||
handoffModeName: string
|
handoffModeName: string
|
||||||
|
fallbackMode: number
|
||||||
|
fallbackModeName: string
|
||||||
fallbackMessage: string
|
fallbackMessage: string
|
||||||
knowledgeIds: number[]
|
knowledgeIds: number[]
|
||||||
knowledgeBaseNames: string[]
|
knowledgeBaseNames: string[]
|
||||||
@@ -239,6 +241,7 @@ export type CreateAIAgentPayload = {
|
|||||||
replyTimeoutSeconds: number
|
replyTimeoutSeconds: number
|
||||||
teamIds: number[]
|
teamIds: number[]
|
||||||
handoffMode: number
|
handoffMode: number
|
||||||
|
fallbackMode: number
|
||||||
fallbackMessage: string
|
fallbackMessage: string
|
||||||
knowledgeIds: number[]
|
knowledgeIds: number[]
|
||||||
skillIds: number[]
|
skillIds: number[]
|
||||||
@@ -1189,8 +1192,6 @@ export type KnowledgeBase = {
|
|||||||
chunkOverlapTokens: number
|
chunkOverlapTokens: number
|
||||||
answerMode: number
|
answerMode: number
|
||||||
answerModeName: string
|
answerModeName: string
|
||||||
fallbackMode: number
|
|
||||||
fallbackModeName: string
|
|
||||||
documentCount: number
|
documentCount: number
|
||||||
faqCount: number
|
faqCount: number
|
||||||
remark: string
|
remark: string
|
||||||
@@ -1212,7 +1213,6 @@ export type CreateKnowledgeBasePayload = {
|
|||||||
chunkMaxTokens: number
|
chunkMaxTokens: number
|
||||||
chunkOverlapTokens: number
|
chunkOverlapTokens: number
|
||||||
answerMode: number
|
answerMode: number
|
||||||
fallbackMode: number
|
|
||||||
remark: string
|
remark: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1400,7 +1400,6 @@ export type KnowledgeSearchPayload = {
|
|||||||
|
|
||||||
export type KnowledgeAnswerPayload = KnowledgeSearchPayload & {
|
export type KnowledgeAnswerPayload = KnowledgeSearchPayload & {
|
||||||
answerMode?: number
|
answerMode?: number
|
||||||
fallbackMode?: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateKnowledgeDocumentPayload = {
|
export type CreateKnowledgeDocumentPayload = {
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
// Code generated by cmd/enums/generator.go. DO NOT EDIT.
|
// Code generated by cmd/enums/generator.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
export enum AIAgentFallbackMode {
|
||||||
|
NoAnswer = 1,
|
||||||
|
SuggestRetry = 2,
|
||||||
|
}
|
||||||
|
export const AIAgentFallbackModeLabels: Record<AIAgentFallbackMode, string> = {
|
||||||
|
[AIAgentFallbackMode.NoAnswer]: "直接声明无答案",
|
||||||
|
[AIAgentFallbackMode.SuggestRetry]: "建议补充信息",
|
||||||
|
}
|
||||||
|
|
||||||
export enum AIAgentHandoffMode {
|
export enum AIAgentHandoffMode {
|
||||||
WaitPool = 1,
|
WaitPool = 1,
|
||||||
DefaultTeamPool = 2,
|
DefaultTeamPool = 2,
|
||||||
@@ -274,17 +283,6 @@ export const KnowledgeDocumentIndexStatusLabels: Record<KnowledgeDocumentIndexSt
|
|||||||
[KnowledgeDocumentIndexStatus.Failed]: "索引失败",
|
[KnowledgeDocumentIndexStatus.Failed]: "索引失败",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum KnowledgeFallbackMode {
|
|
||||||
NoAnswer = 1,
|
|
||||||
SuggestRetry = 2,
|
|
||||||
TransferHuman = 3,
|
|
||||||
}
|
|
||||||
export const KnowledgeFallbackModeLabels: Record<KnowledgeFallbackMode, string> = {
|
|
||||||
[KnowledgeFallbackMode.NoAnswer]: "直接声明无答案",
|
|
||||||
[KnowledgeFallbackMode.SuggestRetry]: "建议重试",
|
|
||||||
[KnowledgeFallbackMode.TransferHuman]: "转人工",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum KnowledgeFeedbackType {
|
export enum KnowledgeFeedbackType {
|
||||||
Like = 1,
|
Like = 1,
|
||||||
Dislike = 2,
|
Dislike = 2,
|
||||||
|
|||||||
+1
-1
Submodule docs updated: 3b32ffb2f8...c694af9a91
@@ -112,15 +112,7 @@ func (s *answer) DebugAnswer(ctx context.Context, req request.KnowledgeAnswerReq
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackMode := enums.KnowledgeFallbackMode(req.FallbackMode)
|
fallbackMode := enums.AIAgentFallbackModeNoAnswer
|
||||||
if fallbackMode == 0 {
|
|
||||||
if knowledgeBase != nil {
|
|
||||||
fallbackMode = enums.KnowledgeFallbackMode(knowledgeBase.FallbackMode)
|
|
||||||
}
|
|
||||||
if fallbackMode == 0 {
|
|
||||||
fallbackMode = enums.KnowledgeFallbackModeNoAnswer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
answerStatus := enums.KnowledgeAnswerStatusNormal
|
answerStatus := enums.KnowledgeAnswerStatusNormal
|
||||||
answer := ""
|
answer := ""
|
||||||
@@ -391,12 +383,10 @@ func buildAnswerSystemPrompt(answerMode enums.KnowledgeAnswerMode) string {
|
|||||||
return "你是严格的客服知识库助手。只能依据提供的知识片段回答;如果资料不足,请明确说明知识库暂无明确信息。"
|
return "你是严格的客服知识库助手。只能依据提供的知识片段回答;如果资料不足,请明确说明知识库暂无明确信息。"
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildFallbackAnswer(fallbackMode enums.KnowledgeFallbackMode) string {
|
func buildFallbackAnswer(fallbackMode enums.AIAgentFallbackMode) string {
|
||||||
switch fallbackMode {
|
switch fallbackMode {
|
||||||
case enums.KnowledgeFallbackModeSuggestRetry:
|
case enums.AIAgentFallbackModeSuggestRetry:
|
||||||
return "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。"
|
return "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。"
|
||||||
case enums.KnowledgeFallbackModeTransferHuman:
|
|
||||||
return "当前知识库里没有找到足够明确的信息,建议转人工进一步处理。"
|
|
||||||
default:
|
default:
|
||||||
return "当前知识库暂无明确信息。"
|
return "当前知识库暂无明确信息。"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,24 +11,19 @@ import (
|
|||||||
func TestBuildFallbackAnswer(t *testing.T) {
|
func TestBuildFallbackAnswer(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
mode enums.KnowledgeFallbackMode
|
mode enums.AIAgentFallbackMode
|
||||||
expected string
|
expected string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no answer",
|
name: "no answer",
|
||||||
mode: enums.KnowledgeFallbackModeNoAnswer,
|
mode: enums.AIAgentFallbackModeNoAnswer,
|
||||||
expected: "当前知识库暂无明确信息。",
|
expected: "当前知识库暂无明确信息。",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "suggest retry",
|
name: "suggest retry",
|
||||||
mode: enums.KnowledgeFallbackModeSuggestRetry,
|
mode: enums.AIAgentFallbackModeSuggestRetry,
|
||||||
expected: "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。",
|
expected: "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "transfer human",
|
|
||||||
mode: enums.KnowledgeFallbackModeTransferHuman,
|
|
||||||
expected: "当前知识库里没有找到足够明确的信息,建议转人工进一步处理。",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func buildKnowledgeGuardDecision(aiAgent models.AIAgent, retrieveResult *retriev
|
|||||||
if retrieveResult == nil || len(retrieveResult.KnowledgeBaseIDs) == 0 {
|
if retrieveResult == nil || len(retrieveResult.KnowledgeBaseIDs) == 0 {
|
||||||
return knowledgeGuardDecision{}
|
return knowledgeGuardDecision{}
|
||||||
}
|
}
|
||||||
fallbackReply := resolveKnowledgeFallbackReply(aiAgent, retrieveResult.FallbackMode)
|
fallbackReply := resolveKnowledgeFallbackReply(aiAgent)
|
||||||
if len(retrieveResult.Hits) == 0 {
|
if len(retrieveResult.Hits) == 0 {
|
||||||
return knowledgeGuardDecision{FallbackReply: fallbackReply}
|
return knowledgeGuardDecision{FallbackReply: fallbackReply}
|
||||||
}
|
}
|
||||||
@@ -32,15 +32,13 @@ func buildKnowledgeGuardDecision(aiAgent models.AIAgent, retrieveResult *retriev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveKnowledgeFallbackReply(aiAgent models.AIAgent, fallbackMode enums.KnowledgeFallbackMode) string {
|
func resolveKnowledgeFallbackReply(aiAgent models.AIAgent) string {
|
||||||
if reply := strings.TrimSpace(aiAgent.FallbackMessage); reply != "" {
|
if reply := strings.TrimSpace(aiAgent.FallbackMessage); reply != "" {
|
||||||
return reply
|
return reply
|
||||||
}
|
}
|
||||||
switch fallbackMode {
|
switch aiAgent.FallbackMode {
|
||||||
case enums.KnowledgeFallbackModeSuggestRetry:
|
case enums.AIAgentFallbackModeSuggestRetry:
|
||||||
return "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。"
|
return "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。"
|
||||||
case enums.KnowledgeFallbackModeTransferHuman:
|
|
||||||
return "当前知识库里没有找到足够明确的信息,建议转人工进一步处理。"
|
|
||||||
default:
|
default:
|
||||||
return "当前知识库暂无明确信息。"
|
return "当前知识库暂无明确信息。"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
|
|
||||||
func TestBuildKnowledgeGuardDecisionFallsBackWhenKnowledgeMisses(t *testing.T) {
|
func TestBuildKnowledgeGuardDecisionFallsBackWhenKnowledgeMisses(t *testing.T) {
|
||||||
agent := newKnowledgeGuardAgentFixture()
|
agent := newKnowledgeGuardAgentFixture()
|
||||||
|
agent.FallbackMode = enums.AIAgentFallbackModeSuggestRetry
|
||||||
decision := buildKnowledgeGuardDecision(agent, &retrievers.KnowledgeRetrieveResult{
|
decision := buildKnowledgeGuardDecision(agent, &retrievers.KnowledgeRetrieveResult{
|
||||||
KnowledgeBaseIDs: []int64{1},
|
KnowledgeBaseIDs: []int64{1},
|
||||||
FallbackMode: enums.KnowledgeFallbackModeSuggestRetry,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if decision.FallbackReply != "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。" {
|
if decision.FallbackReply != "当前知识库里没有找到足够明确的信息,你可以换个更具体的问法再试一次。" {
|
||||||
@@ -30,7 +30,6 @@ func TestBuildKnowledgeGuardDecisionUsesAgentFallbackMessage(t *testing.T) {
|
|||||||
agent.FallbackMessage = "请联系人工客服"
|
agent.FallbackMessage = "请联系人工客服"
|
||||||
decision := buildKnowledgeGuardDecision(agent, &retrievers.KnowledgeRetrieveResult{
|
decision := buildKnowledgeGuardDecision(agent, &retrievers.KnowledgeRetrieveResult{
|
||||||
KnowledgeBaseIDs: []int64{1},
|
KnowledgeBaseIDs: []int64{1},
|
||||||
FallbackMode: enums.KnowledgeFallbackModeNoAnswer,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if decision.FallbackReply != "请联系人工客服" {
|
if decision.FallbackReply != "请联系人工客服" {
|
||||||
@@ -45,8 +44,7 @@ func TestBuildKnowledgeGuardDecisionInjectsStrictInstructionOnHit(t *testing.T)
|
|||||||
Hits: []rag.RetrieveResult{
|
Hits: []rag.RetrieveResult{
|
||||||
{KnowledgeBaseID: 1, Score: 0.88},
|
{KnowledgeBaseID: 1, Score: 0.88},
|
||||||
},
|
},
|
||||||
AnswerMode: enums.KnowledgeAnswerModeStrict,
|
AnswerMode: enums.KnowledgeAnswerModeStrict,
|
||||||
FallbackMode: enums.KnowledgeFallbackModeNoAnswer,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if decision.FallbackReply != "" {
|
if decision.FallbackReply != "" {
|
||||||
@@ -65,5 +63,7 @@ func TestBuildKnowledgeGuardDecisionInjectsStrictInstructionOnHit(t *testing.T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newKnowledgeGuardAgentFixture() models.AIAgent {
|
func newKnowledgeGuardAgentFixture() models.AIAgent {
|
||||||
return models.AIAgent{}
|
return models.AIAgent{
|
||||||
|
FallbackMode: enums.AIAgentFallbackModeNoAnswer,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ type KnowledgeRetrieveResult struct {
|
|||||||
ContextText string
|
ContextText string
|
||||||
TopScore float64
|
TopScore float64
|
||||||
AnswerMode enums.KnowledgeAnswerMode
|
AnswerMode enums.KnowledgeAnswerMode
|
||||||
FallbackMode enums.KnowledgeFallbackMode
|
|
||||||
Trace *rag.RetrieveTrace
|
Trace *rag.RetrieveTrace
|
||||||
TraceItems []callbacks.RetrieverTraceItem
|
TraceItems []callbacks.RetrieverTraceItem
|
||||||
TraceSummary callbacks.RetrieverTraceSummary
|
TraceSummary callbacks.RetrieverTraceSummary
|
||||||
@@ -127,7 +126,7 @@ func (r *KnowledgeRetriever) RetrieveContextByOptions(ctx context.Context, opts
|
|||||||
ret.ContextResults = limitContextResults(ret.ContextResults, maxContextItems)
|
ret.ContextResults = limitContextResults(ret.ContextResults, maxContextItems)
|
||||||
ret.ContextText = strings.TrimSpace(buildContextText(ret.ContextResults))
|
ret.ContextText = strings.TrimSpace(buildContextText(ret.ContextResults))
|
||||||
ret.TopScore = resolveTopScore(results)
|
ret.TopScore = resolveTopScore(results)
|
||||||
ret.AnswerMode, ret.FallbackMode = resolveRuntimeAnswerSettings(knowledgeBaseIDs, results)
|
ret.AnswerMode = resolveRuntimeAnswerMode(knowledgeBaseIDs, results)
|
||||||
ret.TraceItems = buildRetrieverTraceItems(queryPreview, results, trace)
|
ret.TraceItems = buildRetrieverTraceItems(queryPreview, results, trace)
|
||||||
ret.TraceSummary = buildRetrieverTraceSummary(ret.Options, ret.Policies, ret.ContextResults, results, trace)
|
ret.TraceSummary = buildRetrieverTraceSummary(ret.Options, ret.Policies, ret.ContextResults, results, trace)
|
||||||
return ret, nil
|
return ret, nil
|
||||||
@@ -188,34 +187,30 @@ func (r *KnowledgeRetriever) resolvePolicies(knowledgeBaseIDs []int64, opts Know
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveRuntimeAnswerSettings(knowledgeBaseIDs []int64, results []rag.RetrieveResult) (enums.KnowledgeAnswerMode, enums.KnowledgeFallbackMode) {
|
func resolveRuntimeAnswerMode(knowledgeBaseIDs []int64, results []rag.RetrieveResult) enums.KnowledgeAnswerMode {
|
||||||
knowledgeBases := loadRuntimeKnowledgeBases(knowledgeBaseIDs)
|
knowledgeBases := loadRuntimeKnowledgeBases(knowledgeBaseIDs)
|
||||||
if len(knowledgeBases) == 0 {
|
if len(knowledgeBases) == 0 {
|
||||||
return enums.KnowledgeAnswerModeStrict, enums.KnowledgeFallbackModeNoAnswer
|
return enums.KnowledgeAnswerModeStrict
|
||||||
}
|
}
|
||||||
if len(results) > 0 {
|
if len(results) > 0 {
|
||||||
if knowledgeBase, ok := knowledgeBases[results[0].KnowledgeBaseID]; ok {
|
if knowledgeBase, ok := knowledgeBases[results[0].KnowledgeBaseID]; ok {
|
||||||
return normalizeRuntimeAnswerSettings(knowledgeBase)
|
return normalizeRuntimeAnswerMode(knowledgeBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, knowledgeBaseID := range knowledgeBaseIDs {
|
for _, knowledgeBaseID := range knowledgeBaseIDs {
|
||||||
if knowledgeBase, ok := knowledgeBases[knowledgeBaseID]; ok {
|
if knowledgeBase, ok := knowledgeBases[knowledgeBaseID]; ok {
|
||||||
return normalizeRuntimeAnswerSettings(knowledgeBase)
|
return normalizeRuntimeAnswerMode(knowledgeBase)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return enums.KnowledgeAnswerModeStrict, enums.KnowledgeFallbackModeNoAnswer
|
return enums.KnowledgeAnswerModeStrict
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeRuntimeAnswerSettings(knowledgeBase models.KnowledgeBase) (enums.KnowledgeAnswerMode, enums.KnowledgeFallbackMode) {
|
func normalizeRuntimeAnswerMode(knowledgeBase models.KnowledgeBase) enums.KnowledgeAnswerMode {
|
||||||
answerMode := enums.KnowledgeAnswerMode(knowledgeBase.AnswerMode)
|
answerMode := enums.KnowledgeAnswerMode(knowledgeBase.AnswerMode)
|
||||||
if answerMode == 0 {
|
if answerMode == 0 {
|
||||||
answerMode = enums.KnowledgeAnswerModeStrict
|
answerMode = enums.KnowledgeAnswerModeStrict
|
||||||
}
|
}
|
||||||
fallbackMode := enums.KnowledgeFallbackMode(knowledgeBase.FallbackMode)
|
return answerMode
|
||||||
if fallbackMode == 0 {
|
|
||||||
fallbackMode = enums.KnowledgeFallbackModeNoAnswer
|
|
||||||
}
|
|
||||||
return answerMode, fallbackMode
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadRuntimeKnowledgeBases(ids []int64) map[int64]models.KnowledgeBase {
|
func loadRuntimeKnowledgeBases(ids []int64) map[int64]models.KnowledgeBase {
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ func BuildKnowledgeBase(item *models.KnowledgeBase) response.KnowledgeBaseRespon
|
|||||||
ChunkOverlapTokens: item.ChunkOverlapTokens,
|
ChunkOverlapTokens: item.ChunkOverlapTokens,
|
||||||
AnswerMode: item.AnswerMode,
|
AnswerMode: item.AnswerMode,
|
||||||
AnswerModeName: enums.GetKnowledgeAnswerModeLabel(enums.KnowledgeAnswerMode(item.AnswerMode)),
|
AnswerModeName: enums.GetKnowledgeAnswerModeLabel(enums.KnowledgeAnswerMode(item.AnswerMode)),
|
||||||
FallbackMode: item.FallbackMode,
|
|
||||||
FallbackModeName: enums.GetKnowledgeFallbackModeLabel(enums.KnowledgeFallbackMode(item.FallbackMode)),
|
|
||||||
Remark: item.Remark,
|
Remark: item.Remark,
|
||||||
CreatedAt: item.CreatedAt,
|
CreatedAt: item.CreatedAt,
|
||||||
UpdatedAt: item.UpdatedAt,
|
UpdatedAt: item.UpdatedAt,
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse {
|
|||||||
ReplyTimeoutSeconds: item.ReplyTimeoutSeconds,
|
ReplyTimeoutSeconds: item.ReplyTimeoutSeconds,
|
||||||
HandoffMode: item.HandoffMode,
|
HandoffMode: item.HandoffMode,
|
||||||
HandoffModeName: enums.GetAIAgentHandoffModeLabel(item.HandoffMode),
|
HandoffModeName: enums.GetAIAgentHandoffModeLabel(item.HandoffMode),
|
||||||
|
FallbackMode: item.FallbackMode,
|
||||||
|
FallbackModeName: enums.GetAIAgentFallbackModeLabel(item.FallbackMode),
|
||||||
FallbackMessage: item.FallbackMessage,
|
FallbackMessage: item.FallbackMessage,
|
||||||
KnowledgeIDs: utils.SplitInt64s(item.KnowledgeIDs),
|
KnowledgeIDs: utils.SplitInt64s(item.KnowledgeIDs),
|
||||||
SkillIDs: utils.SplitInt64s(item.SkillIDs),
|
SkillIDs: utils.SplitInt64s(item.SkillIDs),
|
||||||
|
|||||||
@@ -509,6 +509,7 @@ type AIAgent struct {
|
|||||||
ReplyTimeoutSeconds int `gorm:"type:int;not null;default:180"` // ReplyTimeoutSeconds 为异步自动回复超时秒数。
|
ReplyTimeoutSeconds int `gorm:"type:int;not null;default:180"` // ReplyTimeoutSeconds 为异步自动回复超时秒数。
|
||||||
TeamIDs string `gorm:"type:varchar(500);not null;default:''"` // TeamIDs 为转人工时可路由的客服组ID列表,多个之间使用逗号分隔。
|
TeamIDs string `gorm:"type:varchar(500);not null;default:''"` // TeamIDs 为转人工时可路由的客服组ID列表,多个之间使用逗号分隔。
|
||||||
HandoffMode enums.AIAgentHandoffMode `gorm:"type:int;not null;default:1"` // HandoffMode 为转人工模式,如进入待接入池、进入默认客服组待接入池。
|
HandoffMode enums.AIAgentHandoffMode `gorm:"type:int;not null;default:1"` // HandoffMode 为转人工模式,如进入待接入池、进入默认客服组待接入池。
|
||||||
|
FallbackMode enums.AIAgentFallbackMode `gorm:"type:int;not null;default:1"` // FallbackMode 为知识库未命中时的兜底策略。
|
||||||
FallbackMessage string `gorm:"type:text"` // FallbackMessage 为兜底回复文案。
|
FallbackMessage string `gorm:"type:text"` // FallbackMessage 为兜底回复文案。
|
||||||
KnowledgeIDs string `gorm:"type:varchar(500);not null;default:''"` // KnowledgeIDs 为绑定的知识库ID列表,按顺序表示优先级。
|
KnowledgeIDs string `gorm:"type:varchar(500);not null;default:''"` // KnowledgeIDs 为绑定的知识库ID列表,按顺序表示优先级。
|
||||||
SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。
|
SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。
|
||||||
@@ -775,7 +776,6 @@ type KnowledgeBase struct {
|
|||||||
ChunkMaxTokens int `gorm:"type:int;not null;default:400"` // ChunkMaxTokens 为单 chunk 最大 token 数。
|
ChunkMaxTokens int `gorm:"type:int;not null;default:400"` // ChunkMaxTokens 为单 chunk 最大 token 数。
|
||||||
ChunkOverlapTokens int `gorm:"type:int;not null;default:40"` // ChunkOverlapTokens 为相邻 chunk 重叠 token 数。
|
ChunkOverlapTokens int `gorm:"type:int;not null;default:40"` // ChunkOverlapTokens 为相邻 chunk 重叠 token 数。
|
||||||
AnswerMode int `gorm:"type:int;not null;default:1"` // AnswerMode 为回答模式:1严格知识库模式 2辅助解释模式。
|
AnswerMode int `gorm:"type:int;not null;default:1"` // AnswerMode 为回答模式:1严格知识库模式 2辅助解释模式。
|
||||||
FallbackMode int `gorm:"type:int;not null;default:1"` // FallbackMode 为兜底模式:1声明无答案 2引导换问法 3转人工。
|
|
||||||
SortNo int `gorm:"type:int;not null;default:0;index"` // SortNo 为排序号,用于后台展示和知识库的人工排序管理。
|
SortNo int `gorm:"type:int;not null;default:0;index"` // SortNo 为排序号,用于后台展示和知识库的人工排序管理。
|
||||||
Remark string `gorm:"type:text"` // Remark 为备注。
|
Remark string `gorm:"type:text"` // Remark 为备注。
|
||||||
AuditFields
|
AuditFields
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ type CreateAIAgentRequest struct {
|
|||||||
ReplyTimeoutSeconds int `json:"replyTimeoutSeconds"`
|
ReplyTimeoutSeconds int `json:"replyTimeoutSeconds"`
|
||||||
TeamIDs []int64 `json:"teamIds"`
|
TeamIDs []int64 `json:"teamIds"`
|
||||||
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
||||||
|
FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"`
|
||||||
FallbackMessage string `json:"fallbackMessage"`
|
FallbackMessage string `json:"fallbackMessage"`
|
||||||
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
||||||
SkillIDs []int64 `json:"skillIds"`
|
SkillIDs []int64 `json:"skillIds"`
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ type CreateKnowledgeBaseRequest struct {
|
|||||||
ChunkMaxTokens int `json:"chunkMaxTokens"`
|
ChunkMaxTokens int `json:"chunkMaxTokens"`
|
||||||
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
||||||
AnswerMode int `json:"answerMode"`
|
AnswerMode int `json:"answerMode"`
|
||||||
FallbackMode int `json:"fallbackMode"`
|
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +70,6 @@ type KnowledgeAnswerRequest struct {
|
|||||||
SessionID string `json:"sessionId"`
|
SessionID string `json:"sessionId"`
|
||||||
ConversationID int64 `json:"conversationId"`
|
ConversationID int64 `json:"conversationId"`
|
||||||
AnswerMode int `json:"answerMode"`
|
AnswerMode int `json:"answerMode"`
|
||||||
FallbackMode int `json:"fallbackMode"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreateKnowledgeFeedbackRequest struct {
|
type CreateKnowledgeFeedbackRequest struct {
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ type AIAgentResponse struct {
|
|||||||
Teams []AIAgentTeamResponse `json:"teams"`
|
Teams []AIAgentTeamResponse `json:"teams"`
|
||||||
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"`
|
||||||
HandoffModeName string `json:"handoffModeName"`
|
HandoffModeName string `json:"handoffModeName"`
|
||||||
|
FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"`
|
||||||
|
FallbackModeName string `json:"fallbackModeName"`
|
||||||
FallbackMessage string `json:"fallbackMessage"`
|
FallbackMessage string `json:"fallbackMessage"`
|
||||||
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
||||||
KnowledgeBaseNames []string `json:"knowledgeBaseNames"`
|
KnowledgeBaseNames []string `json:"knowledgeBaseNames"`
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ type KnowledgeBaseResponse struct {
|
|||||||
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
ChunkOverlapTokens int `json:"chunkOverlapTokens"`
|
||||||
AnswerMode int `json:"answerMode"`
|
AnswerMode int `json:"answerMode"`
|
||||||
AnswerModeName string `json:"answerModeName"`
|
AnswerModeName string `json:"answerModeName"`
|
||||||
FallbackMode int `json:"fallbackMode"`
|
|
||||||
FallbackModeName string `json:"fallbackModeName"`
|
|
||||||
DocumentCount int64 `json:"documentCount"`
|
DocumentCount int64 `json:"documentCount"`
|
||||||
FAQCount int64 `json:"faqCount"`
|
FAQCount int64 `json:"faqCount"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
|||||||
@@ -215,6 +215,27 @@ func GetAIAgentHandoffModeLabel(mode AIAgentHandoffMode) string {
|
|||||||
return aiAgentHandoffModeLabelMap[mode]
|
return aiAgentHandoffModeLabelMap[mode]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AIAgentFallbackMode int
|
||||||
|
|
||||||
|
const (
|
||||||
|
AIAgentFallbackModeNoAnswer AIAgentFallbackMode = 1
|
||||||
|
AIAgentFallbackModeSuggestRetry AIAgentFallbackMode = 2
|
||||||
|
)
|
||||||
|
|
||||||
|
var AIAgentFallbackModeValues = []AIAgentFallbackMode{
|
||||||
|
AIAgentFallbackModeNoAnswer,
|
||||||
|
AIAgentFallbackModeSuggestRetry,
|
||||||
|
}
|
||||||
|
|
||||||
|
var aiAgentFallbackModeLabelMap = map[AIAgentFallbackMode]string{
|
||||||
|
AIAgentFallbackModeNoAnswer: "直接声明无答案",
|
||||||
|
AIAgentFallbackModeSuggestRetry: "建议补充信息",
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAIAgentFallbackModeLabel(mode AIAgentFallbackMode) string {
|
||||||
|
return aiAgentFallbackModeLabelMap[mode]
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
IMRealtimeEventConnected = "connected"
|
IMRealtimeEventConnected = "connected"
|
||||||
IMRealtimeEventPong = "pong"
|
IMRealtimeEventPong = "pong"
|
||||||
|
|||||||
@@ -214,21 +214,3 @@ var knowledgeAnswerModeLabelMap = map[KnowledgeAnswerMode]string{
|
|||||||
func GetKnowledgeAnswerModeLabel(mode KnowledgeAnswerMode) string {
|
func GetKnowledgeAnswerModeLabel(mode KnowledgeAnswerMode) string {
|
||||||
return knowledgeAnswerModeLabelMap[mode]
|
return knowledgeAnswerModeLabelMap[mode]
|
||||||
}
|
}
|
||||||
|
|
||||||
type KnowledgeFallbackMode int
|
|
||||||
|
|
||||||
const (
|
|
||||||
KnowledgeFallbackModeNoAnswer KnowledgeFallbackMode = 1
|
|
||||||
KnowledgeFallbackModeSuggestRetry KnowledgeFallbackMode = 2
|
|
||||||
KnowledgeFallbackModeTransferHuman KnowledgeFallbackMode = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
var knowledgeFallbackModeLabelMap = map[KnowledgeFallbackMode]string{
|
|
||||||
KnowledgeFallbackModeNoAnswer: "直接声明无答案",
|
|
||||||
KnowledgeFallbackModeSuggestRetry: "建议重试",
|
|
||||||
KnowledgeFallbackModeTransferHuman: "转人工",
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetKnowledgeFallbackModeLabel(mode KnowledgeFallbackMode) string {
|
|
||||||
return knowledgeFallbackModeLabelMap[mode]
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ func (s *aIAgentService) UpdateAIAgent(req request.UpdateAIAgentRequest, operato
|
|||||||
"reply_timeout_seconds": item.ReplyTimeoutSeconds,
|
"reply_timeout_seconds": item.ReplyTimeoutSeconds,
|
||||||
"team_ids": item.TeamIDs,
|
"team_ids": item.TeamIDs,
|
||||||
"handoff_mode": item.HandoffMode,
|
"handoff_mode": item.HandoffMode,
|
||||||
|
"fallback_mode": item.FallbackMode,
|
||||||
"fallback_message": item.FallbackMessage,
|
"fallback_message": item.FallbackMessage,
|
||||||
"knowledge_ids": item.KnowledgeIDs,
|
"knowledge_ids": item.KnowledgeIDs,
|
||||||
"skill_ids": item.SkillIDs,
|
"skill_ids": item.SkillIDs,
|
||||||
@@ -157,6 +158,12 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
|
|||||||
if !slices.Contains(enums.AIAgentHandoffModeValues, enums.AIAgentHandoffMode(req.HandoffMode)) {
|
if !slices.Contains(enums.AIAgentHandoffModeValues, enums.AIAgentHandoffMode(req.HandoffMode)) {
|
||||||
return nil, errorsx.InvalidParam("转人工模式不合法")
|
return nil, errorsx.InvalidParam("转人工模式不合法")
|
||||||
}
|
}
|
||||||
|
if req.FallbackMode == 0 {
|
||||||
|
req.FallbackMode = enums.AIAgentFallbackModeNoAnswer
|
||||||
|
}
|
||||||
|
if !slices.Contains(enums.AIAgentFallbackModeValues, enums.AIAgentFallbackMode(req.FallbackMode)) {
|
||||||
|
return nil, errorsx.InvalidParam("兜底策略不合法")
|
||||||
|
}
|
||||||
if enums.AIAgentHandoffMode(req.HandoffMode) == enums.AIAgentHandoffModeDefaultTeamPool && len(teamIDs) == 0 {
|
if enums.AIAgentHandoffMode(req.HandoffMode) == enums.AIAgentHandoffModeDefaultTeamPool && len(teamIDs) == 0 {
|
||||||
return nil, errorsx.InvalidParam("默认客服组待接入池模式必须至少选择一个客服组")
|
return nil, errorsx.InvalidParam("默认客服组待接入池模式必须至少选择一个客服组")
|
||||||
}
|
}
|
||||||
@@ -209,6 +216,7 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
|
|||||||
ReplyTimeoutSeconds: req.ReplyTimeoutSeconds,
|
ReplyTimeoutSeconds: req.ReplyTimeoutSeconds,
|
||||||
TeamIDs: utils.JoinInt64s(teamIDs),
|
TeamIDs: utils.JoinInt64s(teamIDs),
|
||||||
HandoffMode: req.HandoffMode,
|
HandoffMode: req.HandoffMode,
|
||||||
|
FallbackMode: req.FallbackMode,
|
||||||
FallbackMessage: strings.TrimSpace(req.FallbackMessage),
|
FallbackMessage: strings.TrimSpace(req.FallbackMessage),
|
||||||
KnowledgeIDs: utils.JoinInt64s(knowledgeIDs),
|
KnowledgeIDs: utils.JoinInt64s(knowledgeIDs),
|
||||||
SkillIDs: utils.JoinInt64s(skillIDs),
|
SkillIDs: utils.JoinInt64s(skillIDs),
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ func (s *knowledgeBaseService) UpdateKnowledgeBase(req request.UpdateKnowledgeBa
|
|||||||
"chunk_max_tokens": item.ChunkMaxTokens,
|
"chunk_max_tokens": item.ChunkMaxTokens,
|
||||||
"chunk_overlap_tokens": item.ChunkOverlapTokens,
|
"chunk_overlap_tokens": item.ChunkOverlapTokens,
|
||||||
"answer_mode": item.AnswerMode,
|
"answer_mode": item.AnswerMode,
|
||||||
"fallback_mode": item.FallbackMode,
|
|
||||||
"remark": item.Remark,
|
"remark": item.Remark,
|
||||||
"update_user_id": operator.UserID,
|
"update_user_id": operator.UserID,
|
||||||
"update_user_name": operator.Username,
|
"update_user_name": operator.Username,
|
||||||
@@ -161,7 +160,6 @@ func (s *knowledgeBaseService) buildKnowledgeBaseModel(req request.CreateKnowled
|
|||||||
ChunkMaxTokens: req.ChunkMaxTokens,
|
ChunkMaxTokens: req.ChunkMaxTokens,
|
||||||
ChunkOverlapTokens: req.ChunkOverlapTokens,
|
ChunkOverlapTokens: req.ChunkOverlapTokens,
|
||||||
AnswerMode: req.AnswerMode,
|
AnswerMode: req.AnswerMode,
|
||||||
FallbackMode: req.FallbackMode,
|
|
||||||
Remark: req.Remark,
|
Remark: req.Remark,
|
||||||
}
|
}
|
||||||
if item.DefaultTopK == 0 {
|
if item.DefaultTopK == 0 {
|
||||||
@@ -208,9 +206,6 @@ func (s *knowledgeBaseService) buildKnowledgeBaseModel(req request.CreateKnowled
|
|||||||
if item.AnswerMode == 0 {
|
if item.AnswerMode == 0 {
|
||||||
item.AnswerMode = 1
|
item.AnswerMode = 1
|
||||||
}
|
}
|
||||||
if item.FallbackMode == 0 {
|
|
||||||
item.FallbackMode = 1
|
|
||||||
}
|
|
||||||
return item, nil
|
return item, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,389 @@
|
|||||||
|
// Code generated by cmd/enums/generator.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
export enum AIAgentFallbackMode {
|
||||||
|
NoAnswer = 1,
|
||||||
|
SuggestRetry = 2,
|
||||||
|
}
|
||||||
|
export const AIAgentFallbackModeLabels: Record<AIAgentFallbackMode, string> = {
|
||||||
|
[AIAgentFallbackMode.NoAnswer]: "直接声明无答案",
|
||||||
|
[AIAgentFallbackMode.SuggestRetry]: "建议补充信息",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AIAgentHandoffMode {
|
||||||
|
WaitPool = 1,
|
||||||
|
DefaultTeamPool = 2,
|
||||||
|
AIHoldAndNotify = 3,
|
||||||
|
}
|
||||||
|
export const AIAgentHandoffModeLabels: Record<AIAgentHandoffMode, string> = {
|
||||||
|
[AIAgentHandoffMode.WaitPool]: "进入待接入池",
|
||||||
|
[AIAgentHandoffMode.DefaultTeamPool]: "进入默认客服组待接入池",
|
||||||
|
[AIAgentHandoffMode.AIHoldAndNotify]: "AI托底并提醒人工",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AIModelType {
|
||||||
|
LLM = "llm",
|
||||||
|
Embedding = "embedding",
|
||||||
|
Rerank = "rerank",
|
||||||
|
}
|
||||||
|
export const AIModelTypeLabels: Record<AIModelType, string> = {
|
||||||
|
[AIModelType.LLM]: "大语言模型",
|
||||||
|
[AIModelType.Embedding]: "向量模型",
|
||||||
|
[AIModelType.Rerank]: "重排序模型",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AIProvider {
|
||||||
|
OpenAI = "openai",
|
||||||
|
}
|
||||||
|
export const AIProviderLabels: Record<AIProvider, string> = {
|
||||||
|
[AIProvider.OpenAI]: "OpenAI",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AssetProvider {
|
||||||
|
Local = "local",
|
||||||
|
OSS = "oss",
|
||||||
|
}
|
||||||
|
export const AssetProviderLabels: Record<AssetProvider, string> = {
|
||||||
|
[AssetProvider.Local]: "本地存储",
|
||||||
|
[AssetProvider.OSS]: "对象存储",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AssetStatus {
|
||||||
|
Pending = 1,
|
||||||
|
Success = 2,
|
||||||
|
Failed = 3,
|
||||||
|
Deleted = 4,
|
||||||
|
}
|
||||||
|
export const AssetStatusLabels: Record<AssetStatus, string> = {
|
||||||
|
[AssetStatus.Pending]: "处理中",
|
||||||
|
[AssetStatus.Success]: "成功",
|
||||||
|
[AssetStatus.Failed]: "失败",
|
||||||
|
[AssetStatus.Deleted]: "已删除",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ContactType {
|
||||||
|
Mobile = "mobile",
|
||||||
|
Email = "email",
|
||||||
|
Other = "other",
|
||||||
|
}
|
||||||
|
export const ContactTypeLabels: Record<ContactType, string> = {
|
||||||
|
[ContactType.Mobile]: "手机号",
|
||||||
|
[ContactType.Email]: "邮箱",
|
||||||
|
[ContactType.Other]: "其他",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ExternalSource {
|
||||||
|
WebChat = "web_chat",
|
||||||
|
WxWorkKF = "wxwork_kf",
|
||||||
|
}
|
||||||
|
export const ExternalSourceLabels: Record<ExternalSource, string> = {
|
||||||
|
[ExternalSource.WebChat]: "网页客服",
|
||||||
|
[ExternalSource.WxWorkKF]: "企业微信客服",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Gender {
|
||||||
|
Unknown = 0,
|
||||||
|
Male = 1,
|
||||||
|
Female = 2,
|
||||||
|
}
|
||||||
|
export const GenderLabels: Record<Gender, string> = {
|
||||||
|
[Gender.Unknown]: "未知",
|
||||||
|
[Gender.Male]: "男",
|
||||||
|
[Gender.Female]: "女",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMAssignmentStatus {
|
||||||
|
Active = 0,
|
||||||
|
Inactive = 1,
|
||||||
|
}
|
||||||
|
export const IMAssignmentStatusLabels: Record<IMAssignmentStatus, string> = {
|
||||||
|
[IMAssignmentStatus.Active]: "进行中",
|
||||||
|
[IMAssignmentStatus.Inactive]: "已结束",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMAssignmentType {
|
||||||
|
Assign = "assign",
|
||||||
|
Transfer = "transfer",
|
||||||
|
}
|
||||||
|
export const IMAssignmentTypeLabels: Record<IMAssignmentType, string> = {
|
||||||
|
[IMAssignmentType.Assign]: "分配",
|
||||||
|
[IMAssignmentType.Transfer]: "转接",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMConversationServiceMode {
|
||||||
|
AIOnly = 1,
|
||||||
|
HumanOnly = 2,
|
||||||
|
AIFirst = 3,
|
||||||
|
}
|
||||||
|
export const IMConversationServiceModeLabels: Record<IMConversationServiceMode, string> = {
|
||||||
|
[IMConversationServiceMode.AIOnly]: "仅AI",
|
||||||
|
[IMConversationServiceMode.HumanOnly]: "仅人工",
|
||||||
|
[IMConversationServiceMode.AIFirst]: "AI优先",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMConversationStatus {
|
||||||
|
AIServing = 1,
|
||||||
|
Pending = 2,
|
||||||
|
Active = 3,
|
||||||
|
Closed = 4,
|
||||||
|
}
|
||||||
|
export const IMConversationStatusLabels: Record<IMConversationStatus, string> = {
|
||||||
|
[IMConversationStatus.AIServing]: "AI接待中",
|
||||||
|
[IMConversationStatus.Pending]: "待接入",
|
||||||
|
[IMConversationStatus.Active]: "处理中",
|
||||||
|
[IMConversationStatus.Closed]: "已关闭",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMEventType {
|
||||||
|
Create = "create",
|
||||||
|
Assign = "assign",
|
||||||
|
Transfer = "transfer",
|
||||||
|
Close = "close",
|
||||||
|
MessageSend = "message_send",
|
||||||
|
MessageRecall = "message_recall",
|
||||||
|
}
|
||||||
|
export const IMEventTypeLabels: Record<IMEventType, string> = {
|
||||||
|
[IMEventType.Create]: "创建会话",
|
||||||
|
[IMEventType.Assign]: "分配会话",
|
||||||
|
[IMEventType.Transfer]: "转接会话",
|
||||||
|
[IMEventType.Close]: "关闭会话",
|
||||||
|
[IMEventType.MessageSend]: "发送消息",
|
||||||
|
[IMEventType.MessageRecall]: "撤回消息",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMMessageStatus {
|
||||||
|
Sending = 1,
|
||||||
|
Sent = 2,
|
||||||
|
Delivered = 3,
|
||||||
|
Read = 4,
|
||||||
|
Failed = 5,
|
||||||
|
Recalled = 6,
|
||||||
|
}
|
||||||
|
export const IMMessageStatusLabels: Record<IMMessageStatus, string> = {
|
||||||
|
[IMMessageStatus.Sending]: "发送中",
|
||||||
|
[IMMessageStatus.Sent]: "已发送",
|
||||||
|
[IMMessageStatus.Delivered]: "已送达",
|
||||||
|
[IMMessageStatus.Read]: "已读",
|
||||||
|
[IMMessageStatus.Failed]: "发送失败",
|
||||||
|
[IMMessageStatus.Recalled]: "已撤回",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMMessageType {
|
||||||
|
Text = "text",
|
||||||
|
Image = "image",
|
||||||
|
Attachment = "attachment",
|
||||||
|
HTML = "html",
|
||||||
|
}
|
||||||
|
export const IMMessageTypeLabels: Record<IMMessageType, string> = {
|
||||||
|
[IMMessageType.Text]: "文本",
|
||||||
|
[IMMessageType.Image]: "图片",
|
||||||
|
[IMMessageType.Attachment]: "附件",
|
||||||
|
[IMMessageType.HTML]: "富文本",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMParticipantType {
|
||||||
|
Customer = "customer",
|
||||||
|
Agent = "agent",
|
||||||
|
AI = "ai",
|
||||||
|
System = "system",
|
||||||
|
}
|
||||||
|
export const IMParticipantTypeLabels: Record<IMParticipantType, string> = {
|
||||||
|
[IMParticipantType.Customer]: "客户",
|
||||||
|
[IMParticipantType.Agent]: "客服",
|
||||||
|
[IMParticipantType.AI]: "AI",
|
||||||
|
[IMParticipantType.System]: "系统",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum IMSenderType {
|
||||||
|
Agent = "agent",
|
||||||
|
Customer = "customer",
|
||||||
|
AI = "ai",
|
||||||
|
System = "system",
|
||||||
|
}
|
||||||
|
export const IMSenderTypeLabels: Record<IMSenderType, string> = {
|
||||||
|
[IMSenderType.Agent]: "客服",
|
||||||
|
[IMSenderType.Customer]: "客户",
|
||||||
|
[IMSenderType.AI]: "AI",
|
||||||
|
[IMSenderType.System]: "系统",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeAnswerMode {
|
||||||
|
Strict = 1,
|
||||||
|
Assist = 2,
|
||||||
|
}
|
||||||
|
export const KnowledgeAnswerModeLabels: Record<KnowledgeAnswerMode, string> = {
|
||||||
|
[KnowledgeAnswerMode.Strict]: "严格模式",
|
||||||
|
[KnowledgeAnswerMode.Assist]: "辅助模式",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeAnswerStatus {
|
||||||
|
Normal = 1,
|
||||||
|
NoAnswer = 2,
|
||||||
|
Fallback = 3,
|
||||||
|
Blocked = 4,
|
||||||
|
}
|
||||||
|
export const KnowledgeAnswerStatusLabels: Record<KnowledgeAnswerStatus, string> = {
|
||||||
|
[KnowledgeAnswerStatus.Normal]: "正常",
|
||||||
|
[KnowledgeAnswerStatus.NoAnswer]: "无答案",
|
||||||
|
[KnowledgeAnswerStatus.Fallback]: "兜底回复",
|
||||||
|
[KnowledgeAnswerStatus.Blocked]: "已屏蔽",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeBaseType {
|
||||||
|
Document = "document",
|
||||||
|
FAQ = "faq",
|
||||||
|
}
|
||||||
|
export const KnowledgeBaseTypeLabels: Record<KnowledgeBaseType, string> = {
|
||||||
|
[KnowledgeBaseType.Document]: "文档知识库",
|
||||||
|
[KnowledgeBaseType.FAQ]: "FAQ知识库",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeChunkProvider {
|
||||||
|
Fixed = "fixed",
|
||||||
|
Structured = "structured",
|
||||||
|
FAQ = "faq",
|
||||||
|
Semantic = "semantic",
|
||||||
|
}
|
||||||
|
export const KnowledgeChunkProviderLabels: Record<KnowledgeChunkProvider, string> = {
|
||||||
|
[KnowledgeChunkProvider.Fixed]: "固定长度",
|
||||||
|
[KnowledgeChunkProvider.Structured]: "结构化分块",
|
||||||
|
[KnowledgeChunkProvider.FAQ]: "问答式分块",
|
||||||
|
[KnowledgeChunkProvider.Semantic]: "语义分块",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeChunkType {
|
||||||
|
Text = "text",
|
||||||
|
FAQ = "faq",
|
||||||
|
Table = "table",
|
||||||
|
Code = "code",
|
||||||
|
}
|
||||||
|
export const KnowledgeChunkTypeLabels: Record<KnowledgeChunkType, string> = {
|
||||||
|
[KnowledgeChunkType.Text]: "文本",
|
||||||
|
[KnowledgeChunkType.FAQ]: "问答",
|
||||||
|
[KnowledgeChunkType.Table]: "表格",
|
||||||
|
[KnowledgeChunkType.Code]: "代码",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeDocumentContentType {
|
||||||
|
HTML = "html",
|
||||||
|
Markdown = "markdown",
|
||||||
|
}
|
||||||
|
export const KnowledgeDocumentContentTypeLabels: Record<KnowledgeDocumentContentType, string> = {
|
||||||
|
[KnowledgeDocumentContentType.HTML]: "HTML",
|
||||||
|
[KnowledgeDocumentContentType.Markdown]: "Markdown",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeDocumentIndexStatus {
|
||||||
|
Pending = "pending",
|
||||||
|
Indexed = "indexed",
|
||||||
|
Failed = "failed",
|
||||||
|
}
|
||||||
|
export const KnowledgeDocumentIndexStatusLabels: Record<KnowledgeDocumentIndexStatus, string> = {
|
||||||
|
[KnowledgeDocumentIndexStatus.Pending]: "待索引",
|
||||||
|
[KnowledgeDocumentIndexStatus.Indexed]: "已索引",
|
||||||
|
[KnowledgeDocumentIndexStatus.Failed]: "索引失败",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeFeedbackType {
|
||||||
|
Like = 1,
|
||||||
|
Dislike = 2,
|
||||||
|
NotHelpful = 3,
|
||||||
|
WrongCitation = 4,
|
||||||
|
Other = 5,
|
||||||
|
}
|
||||||
|
export const KnowledgeFeedbackTypeLabels: Record<KnowledgeFeedbackType, string> = {
|
||||||
|
[KnowledgeFeedbackType.Like]: "点赞",
|
||||||
|
[KnowledgeFeedbackType.Dislike]: "点踩",
|
||||||
|
[KnowledgeFeedbackType.NotHelpful]: "无帮助",
|
||||||
|
[KnowledgeFeedbackType.WrongCitation]: "引用错误",
|
||||||
|
[KnowledgeFeedbackType.Other]: "其他",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeRetrieveChannel {
|
||||||
|
IM = "im",
|
||||||
|
AgentAssist = "agent_assist",
|
||||||
|
API = "api",
|
||||||
|
Debug = "debug",
|
||||||
|
}
|
||||||
|
export const KnowledgeRetrieveChannelLabels: Record<KnowledgeRetrieveChannel, string> = {
|
||||||
|
[KnowledgeRetrieveChannel.IM]: "客服会话",
|
||||||
|
[KnowledgeRetrieveChannel.AgentAssist]: "客服助手",
|
||||||
|
[KnowledgeRetrieveChannel.API]: "API接口",
|
||||||
|
[KnowledgeRetrieveChannel.Debug]: "调试",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum KnowledgeRetrieveScene {
|
||||||
|
FirstResponse = "first_response",
|
||||||
|
Assist = "assist",
|
||||||
|
QA = "qa",
|
||||||
|
}
|
||||||
|
export const KnowledgeRetrieveSceneLabels: Record<KnowledgeRetrieveScene, string> = {
|
||||||
|
[KnowledgeRetrieveScene.FirstResponse]: "首次回复",
|
||||||
|
[KnowledgeRetrieveScene.Assist]: "辅助回复",
|
||||||
|
[KnowledgeRetrieveScene.QA]: "问答",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ServiceStatus {
|
||||||
|
Idle = 0,
|
||||||
|
Busy = 1,
|
||||||
|
}
|
||||||
|
export const ServiceStatusLabels: Record<ServiceStatus, string> = {
|
||||||
|
[ServiceStatus.Idle]: "空闲",
|
||||||
|
[ServiceStatus.Busy]: "忙碌",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Status {
|
||||||
|
Ok = 0,
|
||||||
|
Disabled = 1,
|
||||||
|
Deleted = 2,
|
||||||
|
}
|
||||||
|
export const StatusLabels: Record<Status, string> = {
|
||||||
|
[Status.Ok]: "启用",
|
||||||
|
[Status.Disabled]: "禁用",
|
||||||
|
[Status.Deleted]: "已删除",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ThirdProvider {
|
||||||
|
WxWork = "wxwork",
|
||||||
|
Dingtalk = "dingtalk",
|
||||||
|
}
|
||||||
|
export const ThirdProviderLabels: Record<ThirdProvider, string> = {
|
||||||
|
[ThirdProvider.WxWork]: "企业微信",
|
||||||
|
[ThirdProvider.Dingtalk]: "钉钉",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TicketSeverity {
|
||||||
|
Minor = 1,
|
||||||
|
Major = 2,
|
||||||
|
Critical = 3,
|
||||||
|
}
|
||||||
|
export const TicketSeverityLabels: Record<TicketSeverity, string> = {
|
||||||
|
[TicketSeverity.Minor]: "轻微",
|
||||||
|
[TicketSeverity.Major]: "严重",
|
||||||
|
[TicketSeverity.Critical]: "致命",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TicketStatus {
|
||||||
|
New = "new",
|
||||||
|
Open = "open",
|
||||||
|
PendingCustomer = "pending_customer",
|
||||||
|
PendingInternal = "pending_internal",
|
||||||
|
Resolved = "resolved",
|
||||||
|
Closed = "closed",
|
||||||
|
Cancelled = "cancelled",
|
||||||
|
}
|
||||||
|
export const TicketStatusLabels: Record<TicketStatus, string> = {
|
||||||
|
[TicketStatus.New]: "新建",
|
||||||
|
[TicketStatus.Open]: "处理中",
|
||||||
|
[TicketStatus.PendingCustomer]: "待客户反馈",
|
||||||
|
[TicketStatus.PendingInternal]: "待内部处理",
|
||||||
|
[TicketStatus.Resolved]: "已解决",
|
||||||
|
[TicketStatus.Closed]: "已关闭",
|
||||||
|
[TicketStatus.Cancelled]: "已取消",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum VectorDBType {
|
||||||
|
Qdrant = "qdrant",
|
||||||
|
}
|
||||||
|
export const VectorDBTypeLabels: Record<VectorDBType, string> = {
|
||||||
|
[VectorDBType.Qdrant]: "Qdrant",
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user