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:
YeYuheng
2025-12-30 11:20:55 +08:00
committed by GitHub
parent 5ff4cc11b0
commit 84570bda6f
7 changed files with 54 additions and 22 deletions

View File

@@ -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:

View File

@@ -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,

View File

@@ -48,6 +48,8 @@ declare global {
CHAT_LOG_SOURCE_ID_PREFIX?: string;
NEXT_PUBLIC_BASE_URL: string;
MAX_HTML_TRANSFORM_CHARS: string;
}
}
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -113,6 +113,8 @@ SHOW_COUPON=false
SHOW_DISCOUNT_COUPON=false
# 自定义 config.json 路径
CONFIG_JSON_PATH=
# HTML 转 Markdown 最大字符数(超过字符数不执行转化)
MAX_HTML_TRANSFORM_CHARS=
# 对话日志推送服务
# # 日志服务地址

View File

@@ -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('');