小功能添加,模型切换问题修复
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
"""Agent Loop 主循环:LLM 对话 -> 工具调用 -> 结果回传 -> 继续。"""
|
||||
|
||||
import json
|
||||
import re
|
||||
import os
|
||||
from typing import AsyncGenerator, Optional
|
||||
|
||||
from openai import AsyncOpenAI
|
||||
|
||||
from app.agent.tools import TOOL_DEFINITIONS, execute_tool
|
||||
from app.config import get_llm_model, get_llm_max_iterations
|
||||
from app.config import get_llm_model, get_llm_max_iterations, get_image_model_config
|
||||
from app.services.image_gen import to_data_uri
|
||||
|
||||
|
||||
@@ -44,12 +45,13 @@ SYSTEM_PROMPT = """\
|
||||
- 尽量详细描述:主体内容、颜色方案、光照、构图、材质等
|
||||
- 如果用户要求游戏 UI 元素,添加相关关键词如 "game UI", "icon", "button" 等
|
||||
- 如果你能直接看到参考图(图片内容),可以在 prompt 中描述参考图的风格特征
|
||||
- 如果你无法看到参考图(只收到了文字提示说有参考图),参考图会由生图工具的 IP-Adapter 自动处理风格融合。此时你的 prompt 中**绝对不要猜测或指定任何画风/艺术风格关键词**(如 pixel art、watercolor、oil painting 等),只描述画面内容(主体、构图、光照等),把风格完全交给参考图来决定
|
||||
- 如果你无法看到参考图(只收到了文字提示说有参考图),参考图会由生图工具的 IP-Adapter 自动处理风格融合。此时你不要自行猜测画风/艺术风格关键词(如 pixel art、watercolor、oil painting 等),把风格交给参考图来决定。但如果用户在消息中明确指定了风格(如"赛博朋克风"、"水彩风"等),应保留并翻译到 prompt 中——尊重用户的主动意图
|
||||
|
||||
## 注意事项
|
||||
- 用中文和用户交流
|
||||
- 生成图片后简要说明你使用的 prompt 思路
|
||||
- 主动建议迭代方向
|
||||
- **禁止模拟工具调用**:生成图片时必须实际调用 generate_image 工具,绝不能用文字描述"已生成"或假装工具已执行。如果需要生成多张图片,每张都必须单独调用工具
|
||||
"""
|
||||
|
||||
|
||||
@@ -68,8 +70,18 @@ async def run_agent_loop(
|
||||
- done: 完成
|
||||
- error: 错误
|
||||
"""
|
||||
# 构建消息列表
|
||||
api_messages = [{"role": "system", "content": SYSTEM_PROMPT}]
|
||||
# 构建消息列表:将当前生图模型信息注入 system prompt,避免 LLM 猜测模型名
|
||||
model_config = get_image_model_config(image_model)
|
||||
current_model_name = model_config.get('name', '未知')
|
||||
current_model_id = model_config.get('id', '未知')
|
||||
model_hint = (
|
||||
f"\n\n## 当前生图模型(重要)\n"
|
||||
f"本次对话用户选择的生图模型是 **{current_model_name}**"
|
||||
f"(model_id: {current_model_id})。\n"
|
||||
f"**注意**:对话历史中可能包含之前使用其他模型的记录,忽略那些旧模型名。"
|
||||
f"本次生成使用的是 {current_model_name},在回复中只能使用这个名称。"
|
||||
)
|
||||
api_messages = [{"role": "system", "content": SYSTEM_PROMPT + model_hint}]
|
||||
|
||||
# 检测当前 LLM 是否支持 vision(多模态图片输入)
|
||||
llm_model = get_llm_model().lower()
|
||||
@@ -96,9 +108,9 @@ async def run_agent_loop(
|
||||
"【系统提示:用户上传了一张参考图,已自动传递给图片生成工具的 IP-Adapter。"
|
||||
"IP-Adapter 会从参考图中提取风格并融合到生成结果中。"
|
||||
"你无法看到这张参考图,因此在生成 prompt 时:\n"
|
||||
"1. 只描述画面内容(主体、构图、光照、材质等)\n"
|
||||
"2. 不要猜测或添加任何画风/艺术风格关键词(如 pixel art、watercolor、cartoon 等)\n"
|
||||
"3. 风格完全由参考图通过 IP-Adapter 决定】"
|
||||
"1. 描述画面内容(主体、构图、光照、材质等)\n"
|
||||
"2. 不要自行猜测画风/艺术风格——但如果用户明确指定了风格,保留到 prompt 中\n"
|
||||
"3. 用户未指定风格时,风格完全由参考图通过 IP-Adapter 决定】"
|
||||
)
|
||||
api_messages.append({"role": "user", "content": hint})
|
||||
continue
|
||||
@@ -150,8 +162,25 @@ async def run_agent_loop(
|
||||
|
||||
finish_reason = chunk.choices[0].finish_reason if chunk.choices else None
|
||||
|
||||
# 如果没有工具调用,对话结束
|
||||
# 如果没有工具调用:检测 LLM 是否在用文字模拟生图
|
||||
if not tool_calls_data:
|
||||
if _looks_like_fake_generation(collected_text):
|
||||
# LLM 用文字假装调用了工具,丢弃这段文字,注入纠正消息强制重试
|
||||
yield {
|
||||
"type": "text_delta",
|
||||
"data": {"text": "\n\n[系统:检测到未调用生图工具,正在重试...]\n"},
|
||||
}
|
||||
api_messages.append({"role": "assistant", "content": collected_text})
|
||||
api_messages.append({
|
||||
"role": "user",
|
||||
"content": (
|
||||
"你刚才没有调用 generate_image 工具,只是用文字描述了生成过程。"
|
||||
"请立即调用 generate_image 工具来实际生成图片。"
|
||||
"不要解释,直接调用工具。"
|
||||
f"当前使用的生图模型是 {model_config.get('name', '未知')}。"
|
||||
),
|
||||
})
|
||||
continue
|
||||
yield {"type": "done", "data": {}}
|
||||
return
|
||||
|
||||
@@ -225,3 +254,19 @@ async def run_agent_loop(
|
||||
# 后续工具调用仍需参考图(InstantStyle 等模型必须有 style_image)
|
||||
|
||||
yield {"type": "done", "data": {}}
|
||||
|
||||
|
||||
# ─── 假生成检测 ──────────────────────────────────────────
|
||||
|
||||
_FAKE_GEN_PATTERNS = re.compile(
|
||||
r"已生成|生成完成|开始生成|正在生成|图片已|prompt.*?设计思路",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
def _looks_like_fake_generation(text: str) -> bool:
|
||||
"""判断 LLM 的纯文字回复是否在假装已经调用了生图工具。"""
|
||||
if not text or len(text) < 50:
|
||||
return False
|
||||
matches = _FAKE_GEN_PATTERNS.findall(text)
|
||||
return len(matches) >= 2
|
||||
|
||||
@@ -59,7 +59,7 @@ IMAGE_MODELS: dict[str, dict[str, Any]] = {
|
||||
"id": "sdxl",
|
||||
"name": "Stable Diffusion XL",
|
||||
"provider": "replicate",
|
||||
"model_id": "stability-ai/sdxl",
|
||||
"model_id": "stability-ai/sdxl:39ed52f2a78e934b3ba6e2a89f5b1c712de7dfea535525255b1aa35c5565e08b",
|
||||
"description": "经典 SDXL,支持 negative prompt",
|
||||
"supports_ref_image": False,
|
||||
"num_images_param": "num_outputs",
|
||||
|
||||
Reference in New Issue
Block a user