Files
crawl4zeroerr/zeroerr_crawler/extract_abstract.py
Oo d257cbaed3 优化摘要配置加载与文档输出兼容性,并补充本地配置忽略规则。
通过引入 config.yaml.example 和环境变量覆盖提升可配置性,同时统一 Word 默认中文字体并忽略本地 config.yaml,避免敏感信息误提交。

Made-with: Cursor
2026-03-26 09:39:07 +08:00

141 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
摘要提取模块
使用大模型生成文档摘要
"""
import os
import re
from openai import OpenAI
def _load_llm_config() -> dict:
"""从 config.yaml 加载 LLM 配置,环境变量可覆盖。"""
config = {
"base_url": "https://yiming.zeroerr.team/v1",
"api_key": "",
"model": "minimax-2.5",
"max_tokens": 40960,
}
# 尝试从项目根目录 config.yaml 读取(与 0209 一致)
config_path = os.path.join(os.path.dirname(__file__), "..", "config.yaml")
if os.path.exists(config_path):
try:
import yaml
with open(config_path, "r", encoding="utf-8") as f:
data = yaml.safe_load(f) or {}
llm = data.get("llm", {})
config.update({k: v for k, v in llm.items() if v})
except Exception:
# 保持静默降级,继续使用默认值/环境变量
pass
# 环境变量优先级更高
config["base_url"] = os.environ.get("ZEROERR_LLM_BASE_URL", config["base_url"])
config["api_key"] = os.environ.get("ZEROERR_LLM_API_KEY", config["api_key"])
config["model"] = os.environ.get("ZEROERR_LLM_MODEL", config["model"])
config["max_tokens"] = int(
os.environ.get("ZEROERR_LLM_MAX_TOKENS", config["max_tokens"])
)
return config
_LLM_CONFIG = _load_llm_config()
API_BASE_URL = _LLM_CONFIG["base_url"]
API_KEY = _LLM_CONFIG["api_key"]
MODEL = _LLM_CONFIG["model"]
MAX_TOKENS = _LLM_CONFIG["max_tokens"]
def generate_abstract(all_pages: list[dict], category_name: str, index_url: str = None) -> str:
"""
使用大模型生成文档摘要
Args:
all_pages: 所有页面数据列表,每个元素包含 'title', 'url', 'markdown' 等字段
category_name: 文档类别名称(如"应用案例"
index_url: 索引页完整URL可选如果提供则会在摘要前添加原文链接
Returns:
摘要文本Markdown格式包含摘要内容和链接列表
"""
if not all_pages:
return ""
if not API_KEY:
print(" 警告: 未设置 ZEROERR_LLM_API_KEY跳过摘要生成")
return ""
try:
# 构建文档内容(用于生成摘要)
# 只使用标题和部分内容,避免内容过长
content_parts = []
for page in all_pages:
title = page.get('title', '')
markdown = page.get('markdown', '')
# 只取前500字符的内容避免输入过长
content_preview = markdown[:500] if len(markdown) > 500 else markdown
content_parts.append(f"标题:{title}\n内容预览:{content_preview}")
document_content = "\n\n".join(content_parts)
# 构建提示词
prompt = f"""面向客户售前咨询,请为以下"{category_name}"类别的文档集合生成一个简洁的摘要。
文档内容:
{document_content}
要求:
1. 摘要应概括该页面的主题和主要内容
2. 摘要长度控制在100-200字之间
3. 使用简洁、专业的语言
4. 突出该页面主题的价值和特点
请直接输出摘要内容,不要包含其他说明文字。"""
# 调用大模型API
client = OpenAI(
base_url=API_BASE_URL,
api_key=API_KEY
)
response = client.chat.completions.create(
model=MODEL,
temperature=0.3, # 使用较低的温度值,保证摘要的准确性
max_tokens=MAX_TOKENS,
messages=[{"role": "user", "content": prompt}],
)
abstract_text = response.choices[0].message.content.strip()
# 过滤掉 <think>...</think> 推理过程
abstract_text = re.sub(r"<think>.*?</think>\s*", "", abstract_text, flags=re.DOTALL).strip()
# 构建链接列表
links_section = "\n\n**相关链接:**\n\n"
for i, page in enumerate(all_pages, 1):
title = page.get('title', '未命名')
url = page.get('url', '')
links_section += f"{i}. [{title}]({url})\n"
# 组合摘要和链接如果提供了索引页URL则在摘要前添加原文链接
if index_url:
result = f"原文链接: {index_url}\n\n{abstract_text}{links_section}"
else:
result = f"{abstract_text}{links_section}"
return result
except Exception as e:
print(f" 警告: 生成摘要失败: {e}")
# 如果生成摘要失败,至少返回链接列表
links_section = "\n\n**相关链接:**\n\n"
for i, page in enumerate(all_pages, 1):
title = page.get('title', '未命名')
url = page.get('url', '')
links_section += f"{i}. [{title}]({url})\n"
# 如果提供了索引页URL在链接列表前添加原文链接
if index_url:
return f"原文链接: {index_url}{links_section}"
return links_section