kgrag/generate_summary.py

143 lines
4.7 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.

"""
文件概述生成工具
把 wiki_engine 的文档概述能力独立出来
输入markdown 格式的文件内容
输出文件概述SUMMARY 行 + markdown 正文)
支持并发
"""
import asyncio
from typing import List, Optional
from config import LLM_CONFIG
from openai import AsyncOpenAI
# ==================== 配置 ====================
_MAX_CONCURRENCY = 8 # 最大并发数
_client: Optional[AsyncOpenAI] = None
_semaphore: Optional[asyncio.Semaphore] = None
def _get_client() -> AsyncOpenAI:
"""获取或创建 AsyncOpenAI 单例客户端"""
global _client
if _client is None:
_client = AsyncOpenAI(api_key=LLM_CONFIG['api_key'], base_url=LLM_CONFIG['base_url'])
return _client
def _get_semaphore() -> asyncio.Semaphore:
"""获取或创建并发信号量"""
global _semaphore
if _semaphore is None:
_semaphore = asyncio.Semaphore(_MAX_CONCURRENCY)
return _semaphore
# ==================== Prompt与 wiki_builder.py 的 WIKI_SUMMARY_PROMPT 一致,仅去掉 extracted_slugs 相关部分) ====================
SUMMARY_PROMPT = """You are a wiki editor. Given the following document content, create a structured wiki summary page in Markdown format.
<document>
<content>
{content}
</content>
</document>
<instructions>
1. The FIRST line of your output MUST be: SUMMARY: {{one sentence, 15-40 words, describing what this document is about for wiki index listing}}
2. Create a concise but useful document-level summary.
3. Include the document's main subject, scope, important procedures, standards, systems, equipment, tables, fields.
4. Do NOT invent facts. Stay grounded in the document content.
5. Write in Chinese.
6. If the content is empty or has no substantive information, output exactly: "SUMMARY: No textual content was extractable from this document." followed by a brief note.
</instructions>
Output the SUMMARY line first, then the Markdown content. Do not include any other preamble."""
async def generate_summary(content: str) -> str:
"""
从 markdown 内容生成文件概述
Args:
content: markdown 格式的文件内容
Returns:
文件概述SUMMARY 行 + markdown 正文)
"""
if not content or not content.strip():
return ""
prompt = SUMMARY_PROMPT.format(content=content)
client = _get_client()
async with _get_semaphore():
try:
response = await client.chat.completions.create(
model=LLM_CONFIG['model'],
messages=[
{"role": "system", "content": "You are a grounded wiki editor. Do not invent facts."},
{"role": "user", "content": prompt},
],
temperature=0.1,
max_tokens=LLM_CONFIG['max_tokens'],
stream=False,
extra_body={"chat_template_kwargs": {"enable_thinking": False}},
)
return (response.choices[0].message.content or "").strip()
except Exception as exc:
print(f"[generate_summary] 概述生成失败: {exc}")
return ""
async def generate_summaries(contents: List[str]) -> List[str]:
"""
并发生成多个文件的概述
Args:
contents: markdown 格式的文件内容列表
Returns:
文件概述列表,顺序与输入一致
"""
return await asyncio.gather(*(generate_summary(c) for c in contents))
if __name__ == "__main__":
# import sys
from pathlib import Path
# if len(sys.argv) > 1:
# with open(sys.argv[1], "r", encoding="utf-8") as f:
# test_content = f.read()
# else:
# test_content = """
# # 船舶动力系统维护规程
# ## 概述
# 本文档详细介绍了船舶动力系统的日常维护和故障处理流程。
# ## 发动机日常检查
# - 润滑油位检查:每日检查发动机润滑油位,保持在标尺正常范围
# - 冷却液位检查:确保冷却系统液位正常,无泄漏
# - 皮带张紧度:检查传动皮带张紧度,过松或过紧均需调整
# ## 冷却系统维护
# 定期清洗热交换器,检查水泵密封性,更换老化管路。
# ## 故障诊断流程
# 1. 现象观察:记录故障现象和发生条件
# 2. 数据采集:收集运行参数和报警信息
# 3. 原因分析:对照标准参数分析故障原因
# 4. 处理方案:制定维修方案并执行
# ## 安全注意事项
# 所有维护操作必须在停机状态下进行,操作人员需佩戴防护装备。
# """
md_path = Path(r"E:\ZKYNLP\Hjunproject\project0506\kgrag\船舶主机燃油泵自动控制系统故障树分析.md")
with open(md_path, "r", encoding="utf-8") as f:
test_content = f.read()
result = asyncio.run(generate_summary(test_content))
print(result)