优化agent sketch 生成逻辑,新增prompt 生成工具

This commit is contained in:
zcr
2026-04-21 14:20:27 +08:00
parent 88e2c8cfb8
commit 22d9ef0e1f
4 changed files with 223 additions and 73 deletions

View File

@@ -1,3 +1,5 @@
import asyncio
import httpx
import uuid
import logging
@@ -6,6 +8,7 @@ from langchain_core.runnables import RunnableConfig
from minio import Minio
from langgraph.prebuilt import ToolRuntime
from src.core.config import settings
from src.server.utils.new_oss_client import oss_get_image
logger = logging.getLogger(__name__)
minio_client = Minio(settings.MINIO_URL, access_key=settings.MINIO_ACCESS, secret_key=settings.MINIO_SECRET, secure=settings.MINIO_SECURE)
@@ -381,3 +384,11 @@ async def generate_or_edit_image(input_path=None, bucket_name="fida-public-bucke
result = resp.json()
image_url = result.get("output_path", None)
return image_url
if __name__ == '__main__':
prompt = "A classic professional hand-drawn furniture concept sketch by an experienced senior furniture designer, strictly monochrome black and white. Centered is a modern minimalist three-seater sofa with slim solid oak legs and generously proportioned soft fabric cushions. Precise pencil linework with masterful varying line weights, elegant cross-hatching and fine marker shading to define volume, depth and comfortable silhouette. Light visible construction lines. Drawn on clean A3 white sketching paper with natural subtle paper grain and slight scan texture. Soft diffused studio light from the top left creates gentle grayscale shadows that emphasize the sofa's elegant proportions and relaxed form. Highly refined, technical yet artistic traditional furniture design sketch, clean and sophisticated."
url = asyncio.run(generate_or_edit_image(prompt=prompt))
img = oss_get_image(oss_client=minio_client, bucket=url.split('/')[0], object_name=url[url.find('/') + 1:])
img.show()

View File

@@ -0,0 +1,112 @@
import logging
from typing import List
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.tools import tool
from langchain_qwq import ChatQwen
from pydantic import BaseModel, Field
from src.core.config import settings
logger = logging.getLogger(__name__)
# 输入
class FurnitureSketchPromptInput(BaseModel):
user_description: str = Field(..., description="用户对家具的描述,例如:'一张工业风的皮革沙发带有金属X型腿和宽扶手'")
num_variants: int = Field(default=12, description="要生成的变种数量默认12个")
# 输出
class FurniturePromptsOutput(BaseModel):
prompts: List[str] = Field(..., description="12个或指定数量明显不同的黑白家具线稿 image prompt 列表")
PROMPT_GEN_SYSTEM = """你是一位顶级家具设计 prompt 工程师专门为黑白线稿furniture sketch生成高质量 image prompt。
核心强制规则所有12个 prompt 都必须严格遵守):
- 必须是 clean black and white line drawing only
- pure white background
- 焦点只在家具本身的物理形态silhouette, proportions, structure, legs, base, frame, joints, armrests, backrest, seat shape 和所有设计细节
- 使用 refined linework with subtle line weight variation
- 只允许 minimal soft shading for depth only
- 严格禁止no color, no fill, no heavy shadows, no hatching, no texture rendering, no environment, no background elements, no lighting effects, no atmosphere
- 视角默认 3/4 front view, eye-level perspective
- 构图centered composition
- 整体风格architectural line art style + modern industrial design sketch style
任务:
根据用户提供的家具描述,生成 **12 个明显不同的** image prompt 变种。
每个变种必须在以下家具设计细节维度上有清晰、可感知的差异:
- 线条特性(极细精确、粗细强烈对比、手绘流动、动态表现力等)
- 结构侧重(整体比例、机械连接、关节细节、腿部与底部、金属框架、曲线轮廓等)
- 阴影与深度处理(几乎无阴影、轻微结构暗示、适度体积感等)
- 艺术调性(极简技术制图、粗犷工业、手绘艺术、精确建筑、高细节精致、柔和形态等)
- 微调视角或构图标准3/4、略低角度强调腿部、略强调对称等
确保12个 prompt 各有特色,不要相似。用户描述要自然放在 prompt 开头,然后自然衔接风格描述。
整个 prompt 要简洁有力、适合 Flux2 klein模型直接使用。
输出要求:
必须以 JSON 格式返回严格遵循以下结构不要添加任何解释、markdown 或额外文字。
{{
"prompts": [
"第一个完整 prompt",
"第二个完整 prompt",
...
]
}}
"""
prompt_gen_llm = ChatQwen(
model="qwen-plus",
max_tokens=3_000,
timeout=None,
max_retries=2,
streaming=False,
temperature=0.25,
top_p=0.8,
api_key=settings.QWEN_API_KEY
)
prompt_template = ChatPromptTemplate.from_messages([
("system", PROMPT_GEN_SYSTEM),
("human", "家具描述: {user_description}\n生成数量: {num_variants}\n请严格以 JSON 格式输出。")
])
prompt_chain = prompt_template | prompt_gen_llm
# 你可以把之前我给你的 3 个经典 Prompt 作为 reference_examples 放进去few-shot
@tool(args_schema=FurnitureSketchPromptInput)
def generate_furniture_sketch_prompts(user_description: str, num_variants: int = 12) -> List[str]:
"""
生成12个明显不同的家具黑白线稿 prompt。
成功时返回 List[str](长度为 num_variants
失败时返回 [user_description],保证至少有一个可用 prompt。
"""
try:
# 使用结构化输出
structured_llm = prompt_gen_llm.with_structured_output(schema=FurniturePromptsOutput, method="json_mode")
chain = prompt_template | structured_llm
result: FurniturePromptsOutput = chain.invoke({
"user_description": user_description,
"num_variants": num_variants
})
if isinstance(result.prompts, list) and len(result.prompts) > 0:
return result.prompts[:num_variants] # 防止意外多返回
# 如果返回的 list 为空,进入兜底
logger.warning("Structured output returned empty list, falling back to user description.")
return [user_description]
except Exception as e:
# 失败兜底:返回用户的原始描述
logger.error(f"Failed to generate structured furniture prompts: {e}. Falling back to user description.")
return [user_description]