update:1.优化世界观生成提示词 2.修复章节分析页面内容重复问题 3.限制mcp调用最大并发数

This commit is contained in:
xiamuceer
2025-11-24 20:42:09 +08:00
parent 187d62f315
commit 4354e74fff
7 changed files with 251 additions and 274 deletions
+6 -6
View File
@@ -95,15 +95,15 @@ async def world_building_generator(
3. 相关领域的专业知识
4. 类似作品的设定参考
根据题材特点,有针对性地查询2-3个关键问题"""
查询最关键的1个问题(不要超过1个)"""
# 调用MCP增强的AI(非流式,最多2轮工具调用)
# 调用MCP增强的AI(非流式,最多1轮工具调用,避免超时
planning_result = await user_ai_service.generate_text_with_mcp(
prompt=planning_prompt,
user_id=user_id,
db_session=db,
enable_mcp=True,
max_tool_rounds=2,
max_tool_rounds=1,
tool_choice="auto",
provider=None,
model=None
@@ -365,15 +365,15 @@ async def characters_generator(
3. 职业特点和生活方式
4. 相关领域的人物原型
根据题材特点,有针对性地查询1-2个关键问题"""
查询最关键的1个问题(不要超过1个)"""
# 调用MCP增强的AI(非流式,最多2轮工具调用)
# 调用MCP增强的AI(非流式,最多1轮工具调用,避免超时
planning_result = await user_ai_service.generate_text_with_mcp(
prompt=planning_prompt,
user_id=user_id,
db_session=db,
enable_mcp=True,
max_tool_rounds=2,
max_tool_rounds=1, # ✅ 优化: 从2轮减少到1轮
tool_choice="auto",
provider=None,
model=None
+5 -5
View File
@@ -73,10 +73,10 @@ def _get_or_create_http_client(
client = httpx.AsyncClient(
timeout=httpx.Timeout(
connect=60.0, # 连接超时
read=180.0, # 读取超时
write=60.0, # 写入超时
pool=60.0 # 连接池超时
connect=90.0, # 连接超时
read=300.0, # 读取超时
write=90.0, # 写入超时
pool=90.0 # 连接池超时
),
limits=limits,
headers={
@@ -959,7 +959,7 @@ class AIService:
else:
# 达到最大轮次
logger.warning(f"达到MCP最大调用轮次 {max_tool_rounds}")
logger.info(f"达到MCP最大调用轮次 {max_tool_rounds}")
result["content"] = conversation_history[-1].get("content", "")
result["finish_reason"] = "max_rounds"
+49 -34
View File
@@ -291,16 +291,18 @@ class MCPToolService:
user_id: str,
tool_calls: List[Dict[str, Any]],
db_session: AsyncSession,
timeout: Optional[float] = None
timeout: Optional[float] = None,
max_concurrent: int = 2
) -> List[Dict[str, Any]]:
"""
批量执行AI请求的工具调用(并行执行
批量执行AI请求的工具调用(限制并发数,避免超时
Args:
user_id: 用户ID
tool_calls: AI返回的工具调用列表
db_session: 数据库会话
timeout: 单个工具调用的超时时间(秒,默认使用配置)
max_concurrent: 最大并发工具调用数(默认2)
Returns:
工具调用结果列表
@@ -311,41 +313,54 @@ class MCPToolService:
# 使用配置的默认超时
actual_timeout = timeout or mcp_config.TOOL_CALL_TIMEOUT_SECONDS
logger.info(f"开始执行 {len(tool_calls)} 个工具调用 (超时={actual_timeout}s)")
logger.info(f"开始执行 {len(tool_calls)} 个工具调用 (超时={actual_timeout}s, 最大并发={max_concurrent})")
# 创建异步任务列表
tasks = [
self._execute_single_tool(
user_id=user_id,
tool_call=tool_call,
db_session=db_session,
timeout=actual_timeout
)
for tool_call in tool_calls
]
# 并行执行所有工具调用
results = await asyncio.gather(*tasks, return_exceptions=True)
# 处理结果
formatted_results = []
for i, result in enumerate(results):
tool_call = tool_calls[i]
# ✅ 分批执行,每批最多max_concurrent个
all_results = []
for i in range(0, len(tool_calls), max_concurrent):
batch = tool_calls[i:i+max_concurrent]
batch_num = i // max_concurrent + 1
total_batches = (len(tool_calls) + max_concurrent - 1) // max_concurrent
if isinstance(result, Exception):
# 工具调用异常
formatted_results.append({
"tool_call_id": tool_call.get("id", f"call_{i}"),
"role": "tool",
"name": tool_call["function"]["name"],
"content": f"工具调用失败: {str(result)}",
"success": False,
"error": str(result)
})
else:
formatted_results.append(result)
logger.info(f"执行工具批次 {batch_num}/{total_batches}, 数量: {len(batch)}")
# 创建当前批次的异步任务
tasks = [
self._execute_single_tool(
user_id=user_id,
tool_call=tool_call,
db_session=db_session,
timeout=actual_timeout
)
for tool_call in batch
]
# 并行执行当前批次
batch_results = await asyncio.gather(*tasks, return_exceptions=True)
# 处理批次结果
for j, result in enumerate(batch_results):
tool_call = batch[j]
if isinstance(result, Exception):
# 工具调用异常
all_results.append({
"tool_call_id": tool_call.get("id", f"call_{i+j}"),
"role": "tool",
"name": tool_call["function"]["name"],
"content": f"工具调用失败: {str(result)}",
"success": False,
"error": str(result)
})
else:
all_results.append(result)
# 批次间增加短暂延迟,避免API限流
if i + max_concurrent < len(tool_calls):
await asyncio.sleep(0.5)
logger.debug(f"批次间延迟 0.5 秒...")
return formatted_results
return all_results
async def _execute_single_tool(
self,
+36 -24
View File
@@ -119,27 +119,38 @@ class PromptService:
主题:{theme}
类型:{genre}
# 2. 世界构建框架
请生成包含以下四个核心板块的世界构建框架。请确保所有板块都围绕【核心概念】展开,并且板块之间【互为因果】
# 2. 核心指令(CRITICAL
* **去标签化**:严禁使用通用的“XX纪元”、“XX时代”、“XX年”作为时间背景的开头或核心描述。请直接描述世界所处的状态、技术水平或生存现状
* **动态演绎**:所有设定必须直接由输入的主题衍生而来。例如,如果是赛博朋克,不要只写“高科技”,要写“义体技术如何导致了贫民窟的特定生活方式”。
* **拒绝陈词滥调**:避免使用宏大的空洞词汇,专注于具体的、可感知的细节。
1. **时间背景 (time_period)**
* 具体的时代设定(例如:星际航行晚期、黑铁时代)
* 重要的【历史转折事件】(是什么导致了当前的世界面貌?)。
* 当前的主要【社会矛盾】或【时代议题】。
2. **地理/空间 (location)**
* 主要舞台(如城市、星球、位面)的【地理环境特征】。
* 这些特征如何影响了【文明】的形态和【资源】分布?
* 独特的【空间布局】或【奇观】。
3. **氛围基调 (atmosphere)**
* 整体的【情感色彩】(例如:压抑、荒诞、史诗、诡异)。
* 【视觉风格】(例如:赛博霓虹、蒸汽朋克、哥特式)。
* 普通居民在日常生活中最常【感受】到什么?
4. **世界规则 (rules)**
* 【物理法则】或【超自然力量】(如魔法、科技)的【具体运作方式】和【代价】。
* 【社会规则】和【权力结构】(谁在统治?基于什么?)。
* 最严重的【社会禁忌】是什么?违反了会怎样?
# 3. 世界构建框架
请生成包含以下四个核心板块的JSON。请确保所有板块互为因果,逻辑严密
# 3. 严格格式要求
**重要说明:每个字段的value必须是一个完整的文本字符串,将以下所有要点整合成连贯的段落描述,不要使用嵌套的JSON对象或数组。**
1. **time_period (时间线与文明阶段)**
请将以下内容整合为一段完整的文字描述(300-500字):
* 描述当前世界处于什么**发展阶段**(是毁灭边缘、新生萌芽、还是停滞不前?),**不要给这个阶段起名字**,而是描述其**特征**。
* **历史转折点**:具体的事件(战争、发明、灾难),它如何直接导致了现在的局面?
* **当下的核心矛盾**:时间流逝带来的具体焦虑是什么?(例如:资源枯竭的倒计时、某种信仰的崩塌)。
2. **location (空间与生态环境)**
请将以下内容整合为一段完整的文字描述(300-500字):
* **舞台特征**:描述主要故事发生的地理或空间环境(如:悬浮的破碎岛屿、被真菌覆盖的地铁网络)。
* **环境与生存**:地理环境如何强迫居民改变了生活方式?(例如:因为引力失衡,建筑都是倒挂的)。
* **标志性奇观**:一个能代表这个世界独特性的具体场景或建筑。
3. **atmosphere (感官体验与基调)**
请将以下内容整合为一段完整的文字描述(300-500字):
* **感官细节**:如果站在这个世界的街头,会**闻**到什么?**听**到什么?(不要只写"压抑",要写"空气中弥漫着铁锈和合成营养膏的酸味")。
* **视觉美学**:描述具体的色彩倾向和光影质感。
* **居民心态**:普通人普遍的心理状态(是麻木、狂热、还是某种特定的恐惧)。
4. **rules (运作逻辑与禁忌)**
请将以下内容整合为一段完整的文字描述(300-500字):
* **核心法则**:这个世界运行的底层逻辑(物理、魔法或科技)。**重点描述代价**(使用力量需要支付什么?)。
* **权力架构**:谁掌握资源?他们通过什么手段维持控制(暴力、技术垄断、宗教洗脑)?
* **红线禁忌**:这个社会绝对不能触碰的具体底线,以及违反后的直接后果。
# 4. 严格格式要求
1. **绝对纯净JSON**:你的[唯一]输出必须是一个完整的JSON对象。输出必须以左花括号开始,并以右花括号结束。
2. **禁止额外字符**:不要在JSON对象之前或之后包含任何说明文字、Markdown标记(如三个反引号加json)、注释或任何其他非JSON字符。
3. **JSON内部文本规则**:在JSON的value字符串内部:
@@ -147,13 +158,14 @@ class PromptService:
* 所有【专有名词】(如地点、人物、组织)应使用【】包裹。
* 所有《作品》或《特殊概念》的标题应使用《》包裹。
4. **JSON结构**:严格遵守`"key": "value"`的英文双引号结构,并使用下面指定的key。
5. **内容密度**:每个字段的描述都必须【深入且详实】,提供至少5-7个具体的设定点或细节。
5. **内容密度**:每个字段的描述都必须【深入且详实】,提供至少5-7个具体的设定点或细节,整合为连贯的段落文本
6. **禁止嵌套结构**:value必须是纯文本字符串,绝对不能是JSON对象或数组,所有信息都要整合在一个字符串中。
{{
"time_period": "(此处填写时间背景的详细描述",
"location": "(此处填写地理/空间的详细描述",
"atmosphere": "(此处填写氛围基调的详细描述",
"rules": "(此处填写世界规则的详细描述"
"time_period": "(此处填写一段完整的文字描述,包含发展阶段特征、历史转折点、核心矛盾等内容,300-500字",
"location": "(此处填写一段完整的文字描述,包含舞台特征、环境与生存、标志性奇观等内容,300-500字",
"atmosphere": "(此处填写一段完整的文字描述,包含感官细节、视觉美学、居民心态等内容,300-500字",
"rules": "(此处填写一段完整的文字描述,包含核心法则、权力架构、红线禁忌等内容,300-500字"
}}"""
# 批量角色生成提示词