mirror of
https://github.com/dataelement/bisheng.git
synced 2026-10-29 18:14:15 +08:00
fix: bug修复
This commit is contained in:
@@ -199,9 +199,17 @@ export default function AdjustFilesUpload() {
|
||||
submittingRef.current = true;
|
||||
setIsSubmitting(true);
|
||||
|
||||
/**
|
||||
* 将 UI 可见的换行转义("\\n")还原为真实换行("\n")
|
||||
*/
|
||||
const normalizeSeparators = (arr) =>
|
||||
(arr || []).map((s) =>
|
||||
typeof s === 'string' ? s.replace(/\\n/g, '\n') : s
|
||||
);
|
||||
|
||||
const apiConfig = {
|
||||
knowledge_id: Number(_config.rules.knowledgeId || initFileData.knowledgeId || knowledgeId),
|
||||
separator: _config.rules.separator,
|
||||
separator: normalizeSeparators(_config.rules.separator),
|
||||
separator_rule: _config.rules.separatorRule,
|
||||
chunk_size: _config.rules.chunkSize,
|
||||
chunk_overlap: _config.rules.chunkOverlap,
|
||||
@@ -216,6 +224,8 @@ export default function AdjustFilesUpload() {
|
||||
captureAndAlertRequestErrorHoc(
|
||||
rebUploadFile(apiConfig)
|
||||
.then(res => {
|
||||
console.log(apiConfig,2323);
|
||||
|
||||
// 1. 修复重复文件判断(单个对象处理)
|
||||
const _repeatFiles = res.status === 3 ? [res] : [];
|
||||
if (_repeatFiles.length) {
|
||||
|
||||
@@ -539,8 +539,8 @@ export default function KnowledgeFile() {
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex items-center justify-center size-12 bg-primary text-white rounded-[4px] w-[40px] h-[40px]">
|
||||
<BookCopy />
|
||||
<div className="flex items-center justify-center size-12 bg-primary/60 text-white rounded-[4px] w-[40px] h-[40px]">
|
||||
<BookCopy className="size-5"/>
|
||||
</div>
|
||||
<div>
|
||||
<div className="truncate max-w-[500px] w-[264px] text-[14px] font-medium pt-2 flex items-center gap-2">
|
||||
|
||||
@@ -13,12 +13,12 @@ import { getKnowledgeModelConfig, getModelListApi } from "@/controllers/API/fine
|
||||
import { captureAndAlertRequestErrorHoc } from "@/controllers/request";
|
||||
import { useTable } from "@/util/hook";
|
||||
import { t } from "i18next";
|
||||
import { Ellipsis, Trash2 } from "lucide-react";
|
||||
import { Ellipsis, MessageSquare, MessageSquareIcon, MessagesSquare, Trash2 } from "lucide-react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import index from "../BuildPage/bench/LingSiWork";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@radix-ui/react-dropdown-menu";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger } from "@/components/bs-ui/select";
|
||||
import { QuestionTooltip, TooltipContent, TooltipTrigger } from "@/components/bs-ui/tooltip";
|
||||
|
||||
function CreateModal({ datalist, open, setOpen, onLoadEnd }) {
|
||||
@@ -167,6 +167,8 @@ export default function KnowledgeQa(params) {
|
||||
const navigate = useNavigate()
|
||||
const [copyLoadingId, setCopyLoadingId] = useState<string | null>(null);
|
||||
const [openMenus, setOpenMenus] = useState<Record<string, boolean>>({});
|
||||
const [selectOpenId, setSelectOpenId] = useState<string | null>(null);
|
||||
const [modalKey, setModalKey] = useState(0);
|
||||
|
||||
const { page, pageSize, data: datalist, total, loading, setPage, search, reload } = useTable({}, (param) => {
|
||||
return readFileLibDatabase({ ...param, name: param.keyword, type: 1 })
|
||||
@@ -257,11 +259,9 @@ export default function KnowledgeQa(params) {
|
||||
{/* 名称+描述单元格:恢复原有气泡结构,确保蓝色生效 */}
|
||||
<TableCell className="font-medium max-w-[280px]">
|
||||
<div className="flex items-center gap-2">
|
||||
<img
|
||||
src={__APP_ENV__.BASE_URL + "/assets/qa-logo.svg"}
|
||||
alt="知识库图标"
|
||||
className="w-[50px] h-[50px] mt-1 flex-shrink-0"
|
||||
/>
|
||||
<div className="flex items-center justify-center size-[40px] min-w-[40px] bg-[rgb(255,237,160)] text-white rounded-[4px] ">
|
||||
<MessagesSquare className="size-5 text-black"/>
|
||||
</div>
|
||||
|
||||
<div className="min-w-0 overflow-visible">
|
||||
{/* 知识库名称(不变) */}
|
||||
@@ -298,42 +298,52 @@ export default function KnowledgeQa(params) {
|
||||
|
||||
{/* 操作列:修复「按钮移入行不高亮」 */}
|
||||
<TableCell className="text-right">
|
||||
{/* 关键:hover:bg-transparent覆盖行的hover:bg-gray-50 */}
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
className="size-10 px-2 bg-transparent border-none shadow-none hover:bg-gray-300 flex items-center justify-center duration-200 relative"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Ellipsis size={24} color="#a69ba2" strokeWidth={1.75} />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
<Select
|
||||
key={`${el.id}-${modalKey}`}
|
||||
open={selectOpenId === el.id}
|
||||
onOpenChange={(isOpen) => {
|
||||
setSelectOpenId(isOpen ? el.id : null);
|
||||
}}
|
||||
onValueChange={(selectedValue) => {
|
||||
setSelectOpenId(null);
|
||||
console.log("Selected value:", selectedValue, "for qa:", el.id);
|
||||
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
className="rounded-md shadow-lg py-1 border-gray-200 z-[100] border border-transparent"
|
||||
style={{ backgroundColor: 'white', opacity: 1 }}
|
||||
onInteractOutside={() => setOpenMenus({})}
|
||||
>
|
||||
<DropdownMenuItem
|
||||
className={`flex items-center gap-2 px-4 py-2 ${(el.copiable || user.role === 'admin')
|
||||
? 'hover:bg-gray-100 cursor-pointer'
|
||||
: 'text-gray-400 cursor-not-allowed'
|
||||
}`}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
switch (selectedValue) {
|
||||
case 'delete':
|
||||
if (el.copiable || user.role === 'admin') {
|
||||
handleDelete(el.id);
|
||||
}
|
||||
}}
|
||||
break;
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SelectTrigger
|
||||
showIcon={false}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className="size-10 px-2 bg-transparent border-none shadow-none hover:bg-gray-300 flex items-center justify-center duration-200 relative"
|
||||
>
|
||||
<Ellipsis size={24} color="#a69ba2" strokeWidth={1.75} />
|
||||
</SelectTrigger>
|
||||
<SelectContent
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className="z-50"
|
||||
>
|
||||
<SelectItem
|
||||
value="delete"
|
||||
disabled={!(el.copiable || user.role === 'admin')}
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
{t('delete')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<div className="flex gap-2 items-center">
|
||||
<Trash2 className="w-4 h-4" />
|
||||
{t('delete')}
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
@@ -28,6 +28,7 @@ interface IProps {
|
||||
onNext: (step: number, config?: any) => void
|
||||
onPrev: () => void
|
||||
isAdjustMode?: boolean
|
||||
kId?: string | number
|
||||
}
|
||||
const enum DisplayModeType {
|
||||
OnlyTables = 'table',
|
||||
@@ -86,26 +87,50 @@ const FileUploadStep2 = forwardRef(({ step, resultFiles, isSubmitting, onNext, o
|
||||
useEffect(() => {
|
||||
applyRuleRef.current = applyRule;
|
||||
}, [applyRule]);
|
||||
// 起始行不能大于结束行校验
|
||||
// 起始行与切分参数校验
|
||||
const vildateCell = () => {
|
||||
// 表头行区间校验
|
||||
if (applyEachCell
|
||||
? rules.fileList.some(file => file.excelRule.append_header && Number(file.excelRule.header_start_row) > Number(file.excelRule.header_end_row))
|
||||
: cellGeneralConfig.append_header && Number(cellGeneralConfig.header_start_row) > Number(cellGeneralConfig.header_end_row)) {
|
||||
return toast({
|
||||
toast({
|
||||
variant: 'warning',
|
||||
description: '最小行不能大于最大行'
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
// 切分长度与重叠长度校验
|
||||
const chunkSizeNum = Number((rules as any)?.chunkSize ?? (rules as any)?.chunk_size ?? 0)
|
||||
const chunkOverlapNum = Number((rules as any)?.chunkOverlap ?? (rules as any)?.chunk_overlap ?? 0)
|
||||
if (!Number.isNaN(chunkSizeNum) && !Number.isNaN(chunkOverlapNum) && chunkOverlapNum > chunkSizeNum) {
|
||||
toast({
|
||||
variant: 'warning',
|
||||
description: '重叠区长度不能大于预期切分长度'
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
const { toast } = useToast()
|
||||
const internalHandleNext = () => {
|
||||
console.log(step, displayStep,'previewCount11');
|
||||
// 全局校验:无论在哪个分支,都先校验参数
|
||||
if (vildateCell()) return;
|
||||
// 规则校验:过滤后若为空或存在空regex,阻止继续
|
||||
const hasEmptyCustomRule = (strategies || []).some(s => String(s?.regex ?? '') === '');
|
||||
if (hasEmptyCustomRule) {
|
||||
toast({ variant: 'warning', description: '自定义规则不能为空' });
|
||||
return;
|
||||
}
|
||||
if (!rules.separator || rules.separator.length === 0) {
|
||||
toast({ variant: 'warning', description: '请至少添加一个分割规则' });
|
||||
return;
|
||||
}
|
||||
const nextStep = step + 1;
|
||||
if (step === 2 || displayStep === 2) {
|
||||
if (vildateCell()) return;
|
||||
|
||||
const config = {
|
||||
applyEachCell,
|
||||
cellGeneralConfig,
|
||||
@@ -153,6 +178,15 @@ useEffect(() => {
|
||||
}, [applyEachCell, cellGeneralConfig, rules]);
|
||||
const handlePreview = () => {
|
||||
if (vildateCell()) return
|
||||
const hasEmptyCustomRule = (strategies || []).some(s => String(s?.regex ?? '') === '');
|
||||
if (hasEmptyCustomRule) {
|
||||
toast({ variant: 'warning', description: '自定义规则不能为空' });
|
||||
return;
|
||||
}
|
||||
if (!rules.separator || rules.separator.length === 0) {
|
||||
toast({ variant: 'warning', description: '请至少添加一个分割规则' });
|
||||
return;
|
||||
}
|
||||
setShowPreview(true)
|
||||
setPreviewLoading(true);
|
||||
setPreviewCount(c => c + 1) // 刷新分段
|
||||
@@ -197,7 +231,7 @@ useEffect(() => {
|
||||
rules={rules}
|
||||
setRules={setRules}
|
||||
strategies={strategies}
|
||||
setStrategies={setStrategies}
|
||||
setStrategies={(next) => setStrategies(next)}
|
||||
showPreview={showPreview}
|
||||
/>
|
||||
</TabsContent>
|
||||
@@ -231,7 +265,7 @@ useEffect(() => {
|
||||
|
||||
{/* 原文预览 & 分段预览:预览时占50% */}
|
||||
{
|
||||
(showPreview || step === 3) ? (
|
||||
(showPreview || (step === 3&&!isAdjustMode)) ? (
|
||||
<div className={cn(
|
||||
"relative",
|
||||
// 预览时占50%宽度
|
||||
@@ -272,7 +306,7 @@ useEffect(() => {
|
||||
<Button
|
||||
className="h-8"
|
||||
// disabled={strategies.length === 0}
|
||||
disabled={previewFailed || isSubmitting}
|
||||
disabled={previewFailed || isSubmitting||strategies.length === 0}
|
||||
onClick={internalHandleNext}
|
||||
>
|
||||
{isSubmitting ? (
|
||||
@@ -290,17 +324,34 @@ export default FileUploadStep2;
|
||||
|
||||
|
||||
const useFileProcessingRules = (initialStrategies, resultFiles, kid, splitRule) => {
|
||||
// 统一解析 splitRule:可能是字符串或对象
|
||||
const parsedSplitRule = useMemo(() => {
|
||||
if (!splitRule) return {} as any;
|
||||
if (typeof splitRule === 'string') {
|
||||
try {
|
||||
const obj = JSON.parse(splitRule);
|
||||
return obj && typeof obj === 'object' ? obj : {};
|
||||
} catch (e) {
|
||||
console.error('splitRule 解析失败:', e);
|
||||
return {} as any;
|
||||
}
|
||||
}
|
||||
return splitRule || {};
|
||||
}, [splitRule]);
|
||||
const [rules, setRules] = useState({
|
||||
knowledgeId: kid,
|
||||
fileList: [],
|
||||
separator: splitRule?.separator || ['\\n\\n', '\\n'],
|
||||
separatorRule: splitRule?.separator_rule || ['after', 'after'],
|
||||
chunkSize: splitRule?.chunk_size?.toString() || "1000",
|
||||
chunkOverlap: splitRule?.chunk_overlap?.toString() || "0",
|
||||
retainImages: splitRule?.retain_images ?? true,
|
||||
enableFormula: splitRule?.enable_formula ?? true,
|
||||
forceOcr: splitRule?.force_ocr ?? true,
|
||||
pageHeaderFooter: splitRule?.filter_page_header_footer ?? true
|
||||
// 统一显示:将真实换行转为可见的转义形式
|
||||
separator: (parsedSplitRule?.separator || ['\\n\\n', '\\n']).map((s) =>
|
||||
typeof s === 'string' ? s.replace(/\n/g, '\\n') : s
|
||||
),
|
||||
separatorRule: parsedSplitRule?.separator_rule || ['after', 'after'],
|
||||
chunkSize: parsedSplitRule?.chunk_size?.toString() || "1000",
|
||||
chunkOverlap: parsedSplitRule?.chunk_overlap?.toString() || "0",
|
||||
retainImages: parsedSplitRule?.retain_images ?? true,
|
||||
enableFormula: parsedSplitRule?.enable_formula ?? true,
|
||||
forceOcr: parsedSplitRule?.force_ocr ?? true,
|
||||
pageHeaderFooter: parsedSplitRule?.filter_page_header_footer ?? true
|
||||
});
|
||||
|
||||
const [applyEachCell, setApplyEachCell] = useState(false);
|
||||
@@ -316,8 +367,12 @@ const useFileProcessingRules = (initialStrategies, resultFiles, kid, splitRule)
|
||||
// 根据正则表达式生成策略描述
|
||||
const getStrategyRuleDescription = (regex) => {
|
||||
const ruleMap = {
|
||||
// 转义形式
|
||||
'\\n\\n': '双换行后切分,用于分隔段落',
|
||||
'\\n': '单换行后切分,用于分隔普通换行',
|
||||
// 真实换行字符形式
|
||||
'\n\n': '双换行后切分,用于分隔段落',
|
||||
'\n': '单换行后切分,用于分隔普通换行',
|
||||
'第.{1,3}章': '"第X章"前切分,切分章节等',
|
||||
'第.{1,3}条': '"第X条"前切分,切分条目等',
|
||||
'。': '中文句号后切分,中文断句',
|
||||
@@ -326,21 +381,24 @@ const useFileProcessingRules = (initialStrategies, resultFiles, kid, splitRule)
|
||||
return ruleMap[regex] || `自定义规则: ${regex}`;
|
||||
};
|
||||
const [strategies, setStrategies] = useState(() => {
|
||||
if (splitRule?.separator && splitRule?.separator_rule) {
|
||||
// 从 splitRule 初始化策略
|
||||
return splitRule.separator.map((regex, index) => ({
|
||||
if (parsedSplitRule?.separator && parsedSplitRule?.separator_rule) {
|
||||
// 从 parsedSplitRule 初始化策略(将真实换行标准化为可见的转义形式)
|
||||
return parsedSplitRule.separator.map((regex, index) => ({
|
||||
id: `strategy-${index}`,
|
||||
regex,
|
||||
position: splitRule.separator_rule[index] || 'after',
|
||||
regex: typeof regex === 'string' ? regex.replace(/\n/g, '\\n') : regex,
|
||||
position: parsedSplitRule.separator_rule[index] || 'after',
|
||||
rule: getStrategyRuleDescription(regex) // 根据正则生成描述
|
||||
}));
|
||||
}
|
||||
return initialStrategies;
|
||||
});
|
||||
// Update rules when strategies change
|
||||
// Update rules when strategies change(不过滤只含换行的规则)
|
||||
useEffect(() => {
|
||||
const [separator, separatorRule] = strategies.reduce(([_separator, _separatorRule], strategy) => {
|
||||
const { regex, position } = strategy;
|
||||
const cleaned = (strategies || []).filter(s => String(s?.regex ?? '') !== '');
|
||||
const [separator, separatorRule] = cleaned.reduce(([_separator, _separatorRule], strategy) => {
|
||||
// 统一显示:确保换行以可见转义“\\n”存在,避免 UI 为空
|
||||
const regex = String(strategy.regex).replace(/\n/g, '\\n');
|
||||
const position = strategy.position || 'after';
|
||||
return [[..._separator, regex], [..._separatorRule, position]];
|
||||
}, [[], []]);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ export default function PreviewFile({
|
||||
edit = false,
|
||||
previewUrl
|
||||
}: {
|
||||
urlState: { load: false; url: '' };
|
||||
urlState: { load: boolean; url: string };
|
||||
file: any;
|
||||
partitions: Partition;
|
||||
chunks: any;
|
||||
@@ -203,7 +203,7 @@ export default function PreviewFile({
|
||||
const previewFileUrl = targetFile.url;
|
||||
|
||||
// 强制uns类型的Excel文件使用pdf预览
|
||||
const renderType = fileParseType === 'etl4lm' && ['ppt', 'pptx'].includes(suffix)
|
||||
const renderType = (fileParseType === 'etl4lm'||fileParseType === 'un_etl4lm') && ['ppt', 'pptx'].includes(suffix)
|
||||
? 'pdf'
|
||||
: suffix;
|
||||
// 加载状态处理
|
||||
|
||||
@@ -24,6 +24,7 @@ interface IProps {
|
||||
cellGeneralConfig: any;
|
||||
handlePreviewResult: (isSuccess: boolean) => void;
|
||||
kId?: string | number;
|
||||
showPreview?: boolean;
|
||||
}
|
||||
export type Partition = {
|
||||
[key in string]: { text: string, type: string, part_id: string }
|
||||
@@ -57,7 +58,7 @@ console.log(showPreview, previewCount, rules, step, applyEachCell, cellGeneralCo
|
||||
}
|
||||
return _currentFile
|
||||
}, [selectId, rules])
|
||||
const [fileViewUrl, setFileViewUrl] = useState({ load: true, url: '' }) // 当前选择文件预览url
|
||||
const [fileViewUrl, setFileViewUrl] = useState<{ load: boolean; url: string }>({ load: true, url: '' }) // 当前选择文件预览url
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
const prevPreviewCountMapRef = useRef({})
|
||||
@@ -82,6 +83,11 @@ console.log(showPreview, previewCount, rules, step, applyEachCell, cellGeneralCo
|
||||
preview_url = currentFile?.filePath
|
||||
}
|
||||
|
||||
// 将 UI 可见的 "\\n" 还原为真实 "\n"
|
||||
const normalizeSeparators = (arr) => (arr || []).map((s) =>
|
||||
typeof s === 'string' ? s.replace(/\\n/g, '\n') : s
|
||||
);
|
||||
|
||||
captureAndAlertRequestErrorHoc(previewFileSplitApi({
|
||||
// 缓存(修改规则后需要清空缓存, 切换文件使用缓存)
|
||||
// previewCount变更时为重新预览分段操作,不使用缓存
|
||||
@@ -93,7 +99,7 @@ console.log(showPreview, previewCount, rules, step, applyEachCell, cellGeneralCo
|
||||
? currentFile.excelRule
|
||||
: { ...cellGeneralConfig }
|
||||
}],
|
||||
separator,
|
||||
separator: normalizeSeparators(separator),
|
||||
separator_rule: separatorRule,
|
||||
chunk_size: chunkSize,
|
||||
chunk_overlap: chunkOverlap,
|
||||
|
||||
@@ -32,6 +32,17 @@ const getStrategyId = (regexStr, position) => {
|
||||
return `strategy-${Math.abs(hash)}`;
|
||||
};
|
||||
|
||||
interface RuleFileProps {
|
||||
rules: any;
|
||||
setRules: (updater: any) => void;
|
||||
strategies?: any[];
|
||||
setStrategies?: (newStrategies: any[]) => void;
|
||||
originalSplitRule?: any;
|
||||
setOriginalSplitRule?: (updater: any) => void;
|
||||
isAdjustMode?: boolean;
|
||||
showPreview?: boolean;
|
||||
}
|
||||
|
||||
export default function RuleFile({
|
||||
rules,
|
||||
setRules,
|
||||
@@ -41,7 +52,7 @@ export default function RuleFile({
|
||||
setOriginalSplitRule = () => {},
|
||||
isAdjustMode = false,
|
||||
showPreview =false
|
||||
}) {
|
||||
}: RuleFileProps) {
|
||||
console.log(showPreview,199);
|
||||
|
||||
const { appConfig } = useContext(locationContext);
|
||||
|
||||
@@ -93,6 +93,16 @@ const ItemForm = ({ data, setData }) => {
|
||||
|
||||
|
||||
|
||||
interface RuleTableProps {
|
||||
rules: any;
|
||||
setRules: (updater: any) => void;
|
||||
applyEachCell: boolean;
|
||||
setApplyEachCell: (checked: boolean) => void;
|
||||
cellGeneralConfig: any;
|
||||
setCellGeneralConfig: (updater: any) => void;
|
||||
showPreview?: boolean;
|
||||
}
|
||||
|
||||
export default function RuleTable({
|
||||
rules,
|
||||
setRules,
|
||||
@@ -101,7 +111,7 @@ export default function RuleTable({
|
||||
cellGeneralConfig,
|
||||
setCellGeneralConfig,
|
||||
showPreview,
|
||||
}) {
|
||||
}: RuleTableProps) {
|
||||
const { t } = useTranslation('knowledge')
|
||||
|
||||
console.log('rules.fileList :>> ', rules.fileList);
|
||||
|
||||
@@ -111,10 +111,18 @@ export default function FilesUpload() {
|
||||
submittingRef.current = true;
|
||||
setIsSubmitting(true);
|
||||
|
||||
/**
|
||||
* 将 UI 可见的换行转义("\\n")还原为真实换行("\n")
|
||||
*/
|
||||
const normalizeSeparators = (arr) =>
|
||||
(arr || []).map((s) =>
|
||||
typeof s === 'string' ? s.replace(/\\n/g, '\n') : s
|
||||
);
|
||||
|
||||
// 正常模式API参数格式
|
||||
const apiConfig = {
|
||||
knowledge_id: Number(_config.rules.knowledgeId || knowledgeId),
|
||||
separator: _config.rules.separator,
|
||||
separator: normalizeSeparators(_config.rules.separator),
|
||||
separator_rule: _config.rules.separatorRule,
|
||||
chunk_size: _config.rules.chunkSize,
|
||||
chunk_overlap: _config.rules.chunkOverlap,
|
||||
|
||||
Reference in New Issue
Block a user