mirror of
https://github.com/labring/FastGPT.git
synced 2026-02-27 01:02:22 +08:00
fix:agent eval and doc file (#6158)
* agent eval * eval auth * html transofrm size * fix: test --------- Co-authored-by: xxyyh <2289112474@qq> Co-authored-by: archer <545436317@qq.com>
This commit is contained in:
@@ -163,6 +163,8 @@ ${{vec.db}}
|
||||
CHAT_FILE_EXPIRE_TIME: 7
|
||||
# 服务器接收请求,最大大小,单位 MB
|
||||
SERVICE_REQUEST_MAX_CONTENT_LENGTH: 10
|
||||
# HTML 转换最大字符数
|
||||
MAX_HTML_TRANSFORM_CHARS: 1000000
|
||||
volumes:
|
||||
- ./config.json:/app/data/config.json
|
||||
sandbox:
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { EvaluationSchemaType } from '@fastgpt/global/core/app/evaluation/t
|
||||
import type { AuthModeType } from '../type';
|
||||
import { MongoEvaluation } from '../../../core/app/evaluation/evalSchema';
|
||||
import { parseHeaderCert } from '../auth/common';
|
||||
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
|
||||
|
||||
export const authEval = async ({
|
||||
evalId,
|
||||
@@ -21,7 +22,13 @@ export const authEval = async ({
|
||||
}> => {
|
||||
const { teamId, tmbId, isRoot } = await parseHeaderCert(props);
|
||||
|
||||
const evaluation = await MongoEvaluation.findById(evalId, 'tmbId').lean();
|
||||
const evaluation = await MongoEvaluation.findOne(
|
||||
{
|
||||
_id: evalId,
|
||||
teamId
|
||||
},
|
||||
'tmbId appId'
|
||||
).lean();
|
||||
if (!evaluation) {
|
||||
return Promise.reject('Evaluation not found');
|
||||
}
|
||||
@@ -34,6 +41,7 @@ export const authEval = async ({
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
// App read per
|
||||
if (per === ReadPermissionVal) {
|
||||
await authAppByTmbId({
|
||||
@@ -42,6 +50,7 @@ export const authEval = async ({
|
||||
per: ReadPermissionVal,
|
||||
isRoot
|
||||
});
|
||||
|
||||
return {
|
||||
teamId,
|
||||
tmbId,
|
||||
@@ -56,6 +65,13 @@ export const authEval = async ({
|
||||
per: ManagePermissionVal,
|
||||
isRoot
|
||||
});
|
||||
} catch (error) {
|
||||
// If app does not exist, allow operation (app was deleted, allow eval cleanup)
|
||||
if (error !== AppErrEnum.unExist) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
teamId,
|
||||
tmbId,
|
||||
|
||||
2
packages/service/type/env.d.ts
vendored
2
packages/service/type/env.d.ts
vendored
@@ -48,6 +48,8 @@ declare global {
|
||||
CHAT_LOG_SOURCE_ID_PREFIX?: string;
|
||||
|
||||
NEXT_PUBLIC_BASE_URL: string;
|
||||
|
||||
MAX_HTML_TRANSFORM_CHARS: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { simpleMarkdownText } from '@fastgpt/global/common/string/markdown';
|
||||
// @ts-ignore
|
||||
const turndownPluginGfm = require('joplin-turndown-plugin-gfm');
|
||||
|
||||
const MAX_HTML_SIZE = 100 * 1000; // 100k characters limit
|
||||
const MAX_HTML_SIZE = Number(process.env.MAX_HTML_TRANSFORM_CHARS || 1000000);
|
||||
|
||||
const processBase64Images = (htmlContent: string) => {
|
||||
// 优化后的正则:
|
||||
@@ -70,9 +70,9 @@ export const html2md = (
|
||||
// Base64 img to id, otherwise it will occupy memory when going to md
|
||||
const { processedHtml, images } = processBase64Images(html);
|
||||
|
||||
// if html is too large, return the original html
|
||||
// if html is too large, return the original html (but preserve image list)
|
||||
if (processedHtml.length > MAX_HTML_SIZE) {
|
||||
return { rawText: processedHtml, imageList: [] };
|
||||
return { rawText: processedHtml, imageList: images };
|
||||
}
|
||||
|
||||
const md = turndownService.turndown(processedHtml);
|
||||
|
||||
@@ -12,6 +12,7 @@ export enum WorkerNameEnum {
|
||||
|
||||
export const getSafeEnv = () => {
|
||||
return {
|
||||
MAX_HTML_TRANSFORM_CHARS: process.env.MAX_HTML_TRANSFORM_CHARS,
|
||||
LOG_LEVEL: process.env.LOG_LEVEL,
|
||||
STORE_LOG_LEVEL: process.env.STORE_LOG_LEVEL,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
|
||||
@@ -113,6 +113,8 @@ SHOW_COUPON=false
|
||||
SHOW_DISCOUNT_COUPON=false
|
||||
# 自定义 config.json 路径
|
||||
CONFIG_JSON_PATH=
|
||||
# HTML 转 Markdown 最大字符数(超过字符数不执行转化)
|
||||
MAX_HTML_TRANSFORM_CHARS=
|
||||
|
||||
# 对话日志推送服务
|
||||
# # 日志服务地址
|
||||
|
||||
@@ -108,7 +108,7 @@ describe('html2md 性能和功能测试', () => {
|
||||
|
||||
it('大型 base64 图片性能(~1MB)', () => {
|
||||
// 生成约 1MB 的 base64 数据
|
||||
const base64Data = 'A'.repeat(1024 * 1024);
|
||||
const base64Data = 'A'.repeat(1000000);
|
||||
const html = `<img src="data:image/png;base64,${base64Data}">`;
|
||||
|
||||
const start = Date.now();
|
||||
@@ -160,14 +160,23 @@ describe('html2md 性能和功能测试', () => {
|
||||
});
|
||||
|
||||
describe('防御性功能', () => {
|
||||
it('应该拒绝超大 HTML 文档', () => {
|
||||
const hugeHtml = 'x'.repeat(100 * 1000 + 1);
|
||||
it('应该拒绝超大 HTML 文档(>1MB)', () => {
|
||||
const hugeHtml = 'x'.repeat(1000000 + 1);
|
||||
const result = html2md(hugeHtml);
|
||||
|
||||
expect(result.rawText).toBe(hugeHtml);
|
||||
expect(result.imageList).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('应该正常处理大型 HTML 文档(<1MB)', () => {
|
||||
const largeHtml = 'x'.repeat(1000000 - 1);
|
||||
const result = html2md(largeHtml);
|
||||
|
||||
// 即使很大,但在限制内,应该正常处理
|
||||
expect(result.rawText).toBeTruthy();
|
||||
expect(result.rawText.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('应该处理空 HTML', () => {
|
||||
const result = html2md('');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user