修改字数限制
This commit is contained in:
parent
ba9de3ed94
commit
ff27395f3a
|
|
@ -197,11 +197,6 @@ async def process_file_background(
|
||||||
# 拼接所有 chunks 的内容用于生成摘要
|
# 拼接所有 chunks 的内容用于生成摘要
|
||||||
file_content = "\n\n".join([content for _, content, _, _ in result.chunks])
|
file_content = "\n\n".join([content for _, content, _, _ in result.chunks])
|
||||||
|
|
||||||
# 限制内容长度,避免超出 LLM 限制
|
|
||||||
max_content_length = 10000 # 约 3000-4000 tokens
|
|
||||||
if len(file_content) > max_content_length:
|
|
||||||
file_content = file_content[:max_content_length] + "..."
|
|
||||||
|
|
||||||
logger.info(f"正在为文件 {file_id} 生成摘要,内容长度: {len(file_content)} 字符")
|
logger.info(f"正在为文件 {file_id} 生成摘要,内容长度: {len(file_content)} 字符")
|
||||||
|
|
||||||
# 将文本内容转换为 Document 对象
|
# 将文本内容转换为 Document 对象
|
||||||
|
|
@ -283,11 +278,6 @@ async def process_url_background(file_id: int, url: str, knowledge_base_id: int)
|
||||||
# 拼接所有 chunks 的内容用于生成摘要
|
# 拼接所有 chunks 的内容用于生成摘要
|
||||||
file_content = "\n\n".join([content for _, content, _, _ in result.chunks])
|
file_content = "\n\n".join([content for _, content, _, _ in result.chunks])
|
||||||
|
|
||||||
# 限制内容长度
|
|
||||||
max_content_length = 10000
|
|
||||||
if len(file_content) > max_content_length:
|
|
||||||
file_content = file_content[:max_content_length] + "..."
|
|
||||||
|
|
||||||
logger.info(f"正在为 URL {file_id} 生成摘要,内容长度: {len(file_content)} 字符")
|
logger.info(f"正在为 URL {file_id} 生成摘要,内容长度: {len(file_content)} 字符")
|
||||||
|
|
||||||
docs = [Document(page_content=file_content)]
|
docs = [Document(page_content=file_content)]
|
||||||
|
|
|
||||||
|
|
@ -2,22 +2,20 @@
|
||||||
知识库与对话文件的正文长度限制。
|
知识库与对话文件的正文长度限制。
|
||||||
|
|
||||||
处理流程对比:
|
处理流程对比:
|
||||||
知识图谱 每块 1 次串行 LLM 抽关系 → 最严格,8 万字
|
知识图谱 每块 1 次串行 LLM 抽关系 → 300 万字
|
||||||
知识库 批量 embedding + 单次摘要 → 较宽松,100 万字
|
知识库 批量 embedding + 单次摘要 → 300 万字
|
||||||
对话文件 批量 embedding + 单次摘要(临时会话上下文)→ 20 万字
|
对话文件 批量 embedding + 单次摘要(临时会话上下文)→ 300 万字
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# ---------- 知识库 ----------
|
# ---------- 知识库 ----------
|
||||||
# chunk_size=4096、overlap=200 → 有效步长约 3896 字/块
|
# chunk_size=4096、overlap=200 → 有效步长约 3896 字/块
|
||||||
# 100 万字 ≈ 250+ 块向量化(PDF 等格式分块更细,上限留足余量)
|
# 300 万字 PDF 等格式分块更细,块数上限留足余量
|
||||||
MAX_KB_INPUT_CHARS = 1_000_000
|
MAX_KB_INPUT_CHARS = 3_000_000
|
||||||
MAX_KB_VECTOR_CHUNKS = 1000
|
MAX_KB_VECTOR_CHUNKS = 3000
|
||||||
|
|
||||||
# ---------- 对话文件(聊天时上传) ----------
|
# ---------- 对话文件(聊天时上传) ----------
|
||||||
# 对话文件是单次会话临时上下文,精度要求高于知识库;过长会稀释检索精度
|
MAX_CHAT_FILE_INPUT_CHARS = 3_000_000
|
||||||
# 20 万字 ≈ 51 块,兼顾处理速度与上下文覆盖
|
MAX_CHAT_FILE_VECTOR_CHUNKS = 3000
|
||||||
MAX_CHAT_FILE_INPUT_CHARS = 200_000
|
|
||||||
MAX_CHAT_FILE_VECTOR_CHUNKS = 60
|
|
||||||
|
|
||||||
|
|
||||||
def decode_txt_char_count(raw: bytes) -> int:
|
def decode_txt_char_count(raw: bytes) -> int:
|
||||||
|
|
|
||||||
|
|
@ -635,6 +635,7 @@ class KnowledgeProcessingExecutor:
|
||||||
"""
|
"""
|
||||||
from langchain_core.messages import HumanMessage, SystemMessage
|
from langchain_core.messages import HumanMessage, SystemMessage
|
||||||
from core.llm_catalog import build_chat_model
|
from core.llm_catalog import build_chat_model
|
||||||
|
from services.summary_service import truncate_text_for_summary
|
||||||
|
|
||||||
logger.info(f"执行总结任务: {task.task_name}")
|
logger.info(f"执行总结任务: {task.task_name}")
|
||||||
|
|
||||||
|
|
@ -644,7 +645,8 @@ class KnowledgeProcessingExecutor:
|
||||||
files_text += f"\n\n【文件{idx}: {file_data['file_name']}】\n"
|
files_text += f"\n\n【文件{idx}: {file_data['file_name']}】\n"
|
||||||
if file_data['summary']:
|
if file_data['summary']:
|
||||||
files_text += f"摘要: {file_data['summary']}\n\n"
|
files_text += f"摘要: {file_data['summary']}\n\n"
|
||||||
files_text += f"内容:\n{file_data['content']}\n"
|
content = truncate_text_for_summary(file_data['content'])
|
||||||
|
files_text += f"内容:\n{content}\n"
|
||||||
files_text += "=" * 80
|
files_text += "=" * 80
|
||||||
|
|
||||||
prompt = f"""你是一个文档总结助手。用户需要总结多个文件的内容。
|
prompt = f"""你是一个文档总结助手。用户需要总结多个文件的内容。
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@ from logger.logging import get_logger
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
# 知识图谱抽取上限:每块约 900 字、重叠 120,每块 1 次 DeepSeek 调用(串行)。
|
# 知识图谱抽取上限:每块约 900 字、重叠 120,每块 1 次 DeepSeek 调用(串行)。
|
||||||
# 8 万字 ≈ 100 次调用,后台约 5–10 分钟可完成;50 万字需 600+ 次,基本不可行。
|
# 300 万字时块数上限需与 MAX_INPUT_CHARS 匹配。
|
||||||
MAX_INPUT_CHARS = 80_000
|
MAX_INPUT_CHARS = 3_000_000
|
||||||
MAX_KG_EXTRACT_CHUNKS = 100
|
MAX_KG_EXTRACT_CHUNKS = 4000
|
||||||
CHUNK_SIZE = 900
|
CHUNK_SIZE = 900
|
||||||
CHUNK_OVERLAP = 120
|
CHUNK_OVERLAP = 120
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,18 @@ logger = get_logger(__name__)
|
||||||
MAX_SUMMARY_INPUT_CHARS = 10_000
|
MAX_SUMMARY_INPUT_CHARS = 10_000
|
||||||
|
|
||||||
|
|
||||||
|
def truncate_text_for_summary(text: str, max_chars: int = MAX_SUMMARY_INPUT_CHARS) -> str:
|
||||||
|
"""超长正文仅保留前 max_chars 字用于摘要生成。"""
|
||||||
|
text = text.strip()
|
||||||
|
if len(text) <= max_chars:
|
||||||
|
return text
|
||||||
|
logger.info(
|
||||||
|
f"摘要输入过长({len(text):,} 字),"
|
||||||
|
f"仅使用前 {max_chars:,} 字生成摘要"
|
||||||
|
)
|
||||||
|
return text[:max_chars]
|
||||||
|
|
||||||
|
|
||||||
# 摘要生成 Prompt - 优化版:强调全面覆盖
|
# 摘要生成 Prompt - 优化版:强调全面覆盖
|
||||||
GENERATE_SUMMARY_PROMPT = """
|
GENERATE_SUMMARY_PROMPT = """
|
||||||
你是一个精准的文件内容总结专家。你的任务是提取并总结用户提供的文件内容或片段的**所有核心内容**。
|
你是一个精准的文件内容总结专家。你的任务是提取并总结用户提供的文件内容或片段的**所有核心内容**。
|
||||||
|
|
@ -107,12 +119,7 @@ class SummaryService:
|
||||||
if not doc_content:
|
if not doc_content:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
if len(doc_content) > MAX_SUMMARY_INPUT_CHARS:
|
doc_content = truncate_text_for_summary(doc_content)
|
||||||
logger.info(
|
|
||||||
f"摘要输入过长({len(doc_content):,} 字),"
|
|
||||||
f"仅使用前 {MAX_SUMMARY_INPUT_CHARS:,} 字生成摘要"
|
|
||||||
)
|
|
||||||
doc_content = doc_content[:MAX_SUMMARY_INPUT_CHARS]
|
|
||||||
|
|
||||||
# 生成摘要
|
# 生成摘要
|
||||||
prompt = PromptTemplate(
|
prompt = PromptTemplate(
|
||||||
|
|
|
||||||
|
|
@ -216,7 +216,7 @@
|
||||||
ref="fileInput"
|
ref="fileInput"
|
||||||
>
|
>
|
||||||
</label>
|
</label>
|
||||||
<small class="upload-hint">支持 PDF、DOCX、Excel(xlsx/xls)、CSV、TXT、图片(PNG、JPG、BMP)格式,单文件不超过 15MB,提取正文不超过 100 万字(过长请拆分)</small>
|
<small class="upload-hint">支持 PDF、DOCX、Excel(xlsx/xls)、CSV、TXT、图片(PNG、JPG、BMP)格式,单文件不超过 15MB,提取正文不超过 300 万字(过长请拆分)</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- URL 上传 -->
|
<!-- URL 上传 -->
|
||||||
|
|
|
||||||
|
|
@ -219,7 +219,7 @@
|
||||||
class="form-control bg-dark text-white border-secondary"
|
class="form-control bg-dark text-white border-secondary"
|
||||||
@change="onFileSelect"
|
@change="onFileSelect"
|
||||||
/>
|
/>
|
||||||
<div class="mt-2 small text-muted">支持 .txt、.pdf、.docx 及常见图片;扫描件将尝试 OCR + 通义视觉。单文件不超过约 15MB,提取正文建议不超过 8 万字(过长请拆分或改用知识库)</div> </div>
|
<div class="mt-2 small text-muted">支持 .txt、.pdf、.docx 及常见图片;扫描件将尝试 OCR + 通义视觉。单文件不超过约 15MB,提取正文不超过 300 万字(过长请拆分)</div> </div>
|
||||||
<div v-if="uploadError" class="alert alert-danger py-2 small">{{ uploadError }}</div>
|
<div v-if="uploadError" class="alert alert-danger py-2 small">{{ uploadError }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer-custom">
|
<div class="modal-footer-custom">
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue