Compare commits
11 Commits
496e7ad590
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a36235d58e | |||
| 433aa3e751 | |||
| 7bf080b3e7 | |||
| 03c4759895 | |||
| 03ff6605a3 | |||
| 4b3b0f6aa8 | |||
| c798d37fdd | |||
| 43fd576da6 | |||
| 1bbb9c945e | |||
|
|
3ca6b16eaf | ||
|
|
f9d83f6a99 |
@@ -7,7 +7,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
REMOTE_DEPLOY_PATH: /workspace/Trinity/Litserve_LC_Prod/lc_stylist_agent
|
||||
REMOTE_DEPLOY_PATH: /workspace/LC_Workspace/LitServe_Server_Workspace/lc_stylist_agent
|
||||
|
||||
steps:
|
||||
- name: 1.检出代码
|
||||
|
||||
@@ -17,7 +17,11 @@ class Settings(BaseSettings):
|
||||
extra='ignore' # 忽略环境变量中多余的键
|
||||
)
|
||||
# 启动端口
|
||||
SERVE_PROD: int = Field(default=8000, description='')
|
||||
SERVE_PORT: int = Field(default=8000, description='')
|
||||
|
||||
# 换脸模型服务
|
||||
RE_FACE_MODEL_URL: str = Field(default="10.1.1.240:10071", description='')
|
||||
|
||||
# 调试配饰
|
||||
LOCAL: int = Field(default=0, description="是否在本地运行,1表示本地运行,0表示生产环境运行")
|
||||
|
||||
|
||||
@@ -27,4 +27,4 @@ if __name__ == "__main__":
|
||||
agent_api = LCAgent(enable_async=True, api_path='/api/v1/agent')
|
||||
reface_api = ReFace(api_path='/api/v1/reface')
|
||||
server = ls.LitServer([chat_boot_api, agent_api, reface_api])
|
||||
server.run(port=settings.SERVE_PROD)
|
||||
server.run(port=8000)
|
||||
|
||||
@@ -49,10 +49,18 @@ class LCChatBot(ls.LitAPI):
|
||||
user_msg = Message(role=Role.USER, content=user_message)
|
||||
chat_history = self.redis.get_history(session_id)
|
||||
chat_history.append(user_msg)
|
||||
|
||||
turn_count = sum(1 for msg in chat_history if msg.role == Role.USER)
|
||||
|
||||
if request.gender == 'male':
|
||||
prompt = BASIC_PROMPT.format(gender='men')
|
||||
system_instruction = BASIC_PROMPT.format(gender='men')
|
||||
else:
|
||||
prompt = BASIC_PROMPT.format(gender='women')
|
||||
system_instruction = BASIC_PROMPT.format(gender='women')
|
||||
|
||||
if turn_count >= 3:
|
||||
system_instruction += "\n\nCRITICAL: This is the final turn. Do not ask questions. Provide a brief summary and use the mandatory closing phrase."
|
||||
else:
|
||||
system_instruction += f"\n\nCURRENT STATE: This is turn {turn_count} of 3. Keep gathering info efficiently or provide a brief summary and use the mandatory closing phrase if you have sufficient information."
|
||||
|
||||
contents = []
|
||||
|
||||
@@ -68,7 +76,7 @@ class LCChatBot(ls.LitAPI):
|
||||
model='gemini-2.5-flash',
|
||||
contents=contents,
|
||||
config=types.GenerateContentConfig(
|
||||
system_instruction=prompt,
|
||||
system_instruction=system_instruction,
|
||||
# temperature=0.3,
|
||||
)
|
||||
)
|
||||
@@ -99,7 +107,7 @@ class LCChatBot(ls.LitAPI):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.stdout = open('permanent.log', 'w', encoding='utf-8')
|
||||
# sys.stdout = open('permanent.log', 'w', encoding='utf-8')
|
||||
|
||||
import asyncio
|
||||
|
||||
@@ -137,23 +145,67 @@ if __name__ == "__main__":
|
||||
print(chunk, end="", flush=True)
|
||||
|
||||
|
||||
text_list = [
|
||||
'我要去参加好朋友的婚礼,你能帮我挑一套衣服吗?',
|
||||
'I need something to wear for a big presentation at work tomorrow. I want to look powerful but still approachable.',
|
||||
'Who do you think is the best world leader right now?',
|
||||
'I’m going on a trip to Paris next week and need some outfits.',
|
||||
'Help me find a cool outfit for a rock concert. I hate wearing dresses.',
|
||||
'I want to look very cool, 或者是那种很有个性的风格 for a gallery opening.',
|
||||
"I'm going to a gala. Please list 5 different dress styles for me and use bold text for the names.",
|
||||
"I'm feeling really sad today and just want an outfit that matches my mood."
|
||||
]
|
||||
for text in text_list:
|
||||
asyncio.run(run_simple_test(text))
|
||||
# print("\n" + "=" * 50)
|
||||
# # 启动异步事件循环
|
||||
# try:
|
||||
# asyncio.run(run_simple_test())
|
||||
# except Exception as e:
|
||||
# print(f"\n发生致命错误: {e}")
|
||||
#
|
||||
sys.stdout.close()
|
||||
# text_list = [
|
||||
# '我要去参加好朋友的婚礼,你能帮我挑一套衣服吗?',
|
||||
# 'I need something to wear for a big presentation at work tomorrow. I want to look powerful but still approachable.',
|
||||
# 'Who do you think is the best world leader right now?',
|
||||
# 'I’m going on a trip to Paris next week and need some outfits.',
|
||||
# 'Help me find a cool outfit for a rock concert. I hate wearing dresses.',
|
||||
# 'I want to look very cool, 或者是那种很有个性的风格 for a gallery opening.',
|
||||
# "I'm going to a gala. Please list 5 different dress styles for me and use bold text for the names.",
|
||||
# "I'm feeling really sad today and just want an outfit that matches my mood."
|
||||
# ]
|
||||
# for text in text_list:
|
||||
# asyncio.run(run_simple_test(text))
|
||||
|
||||
|
||||
async def run_interactive_test():
|
||||
"""
|
||||
手动输入测试:模拟真实用户与 AI 的多轮对话
|
||||
"""
|
||||
# 1. 初始化
|
||||
chatbot_api = LCChatBot()
|
||||
chatbot_api.setup(device="cpu")
|
||||
|
||||
session_id = "manual_test_session"
|
||||
user_id = "test_user"
|
||||
|
||||
print("--- 👗 欢迎进入 AI 造型师测试 (输入 'quit' 退出) ---")
|
||||
|
||||
|
||||
# 清空旧的测试记录,开始新会话
|
||||
chatbot_api.redis.clear_history(session_id)
|
||||
print("✅ 已清空历史记录,开始新会话。")
|
||||
|
||||
|
||||
while True:
|
||||
# 2. 获取手动输入
|
||||
user_input = input("\nUser (你): ")
|
||||
if user_input.lower() in ['quit', 'exit', '退出']:
|
||||
break
|
||||
|
||||
# 3. 构造请求
|
||||
request_data = PredictRequest(
|
||||
user_id=user_id,
|
||||
session_id=session_id,
|
||||
user_message=user_input,
|
||||
gender="female" # 或者根据需要修改
|
||||
)
|
||||
|
||||
print("Agent (AI): ", end="")
|
||||
|
||||
# 4. 调用并流式打印
|
||||
# 注意:这里的 predict 内部现在会计算 turn_count
|
||||
response_generator = chatbot_api.predict(request_data)
|
||||
|
||||
full_response = ""
|
||||
async for chunk in response_generator:
|
||||
print(chunk, end="", flush=True)
|
||||
full_response += chunk
|
||||
|
||||
# 将 AI 的回复存入 Redis (如果你的 predict 函数里没存的话)
|
||||
# chatbot_api.redis.add_message(session_id, Role.ASSISTANT, full_response)
|
||||
|
||||
print() # 换行
|
||||
|
||||
asyncio.run(run_interactive_test())
|
||||
|
||||
@@ -7,6 +7,16 @@ CONVERSATION GOALS:
|
||||
3. **Vibe/Details:** Gather mood or constraints (e.g., comfort, specific colors).
|
||||
4. **Item Preference:** Identify preferences for silhouettes or specific items.
|
||||
|
||||
CONVERSATION FLOW:
|
||||
- You have a maximum of 3 turns (one turn = one user message and one assistant response) to gather information.
|
||||
- On the 3rd turn, or *once you have sufficient info*, do NOT ask further questions.
|
||||
- MANDATORY CLOSING: You must end your final response using the FINAL TURN CLOSING RULE below.
|
||||
|
||||
FINAL TURN CLOSING RULE:
|
||||
- Once requirements are gathered, do NOT ask any more questions.
|
||||
- End your final response with a creative and friendly variation of the closing phrase.
|
||||
- REQUIRED COMPONENTS: Every variation MUST mention the "**Generate button**" (this phrase must be bounded using double asterisks).
|
||||
|
||||
PERSONALITY AND COMMUNICATION RULES:
|
||||
- Always reply in English only. If the user speaks another language, state in English that you cannot speak that language and steer back to styling.
|
||||
- Keep responses extremely SHORT (maximum 2 sentences).
|
||||
@@ -24,7 +34,7 @@ OUTPUT FORMAT INSTRUCTION:
|
||||
- **ONLY** output the plain text response spoken by the AI Assistant.
|
||||
|
||||
EXAMPLE DIALOGUES:
|
||||
User: 我想找件衣服参加婚礼。 Response: I am so sorry, but I can only speak English! I would love to help you find the perfect wedding guest look if you can tell me the dress code or the venue vibe.
|
||||
User: 我想找件衣服参加婚礼。 Response: I would love to help you find the perfect wedding guest look if you can tell me the dress code or the venue vibe.
|
||||
|
||||
User: I need a chic outfit for dinner. Response: That sounds like a fabulous evening! Is this a romantic date or a casual night out with friends, and do you prefer a sleek dress or tailored separates?
|
||||
|
||||
|
||||
@@ -250,9 +250,20 @@ class AsyncStylistAgent:
|
||||
if occasion == "Bridal / Wedding":
|
||||
request_summary += "IMPORTANT: Strictly only recommend colorful or white items (clothing, shoes, and bags)."
|
||||
elif occasion == "Evening":
|
||||
request_summary += " **EVENING STYLE MANDATE:** Prioritize high textural contrast. Avoid flat/matte monochrome or total black looks. Ensure visual depth through layering (e.g., varying lengths or sheer panels). Use statement accessories to break simple silhouettes."
|
||||
request_summary += (" **EVENING STYLE MANDATE:** Prioritize high textural contrast. Avoid flat/matte monochrome or total black looks. Ensure visual depth through layering "
|
||||
"(e.g., varying lengths or sheer panels). Use statement accessories to break simple silhouettes.")
|
||||
elif occasion == "Business / workwear":
|
||||
request_summary += " **WORKWEAR STYLE MANDATE:** Focus on 'Power Dressing' silhouettes—prioritize sharp, oversized blazers paired with floor-length wide-leg trousers. Use tonal dressing (different shades of the same color) to create a sophisticated, elongated look. Balance masculine tailoring with polished, feminine textures. Select structured, architectural bags and pointed-toe or sleek loafers to maintain professional sharpness."
|
||||
request_summary += (" **WORKWEAR STYLE MANDATE:** Focus on 'Power Dressing' silhouettes—prioritize sharp, oversized blazers paired with floor-length wide-leg trousers. "
|
||||
"Use tonal dressing to create a sophisticated, elongated look. Balance masculine tailoring with polished, feminine textures. "
|
||||
"Select structured, architectural bags and pointed-toe or sleek loafers. MANDATORY: Include a complete gold or silver jewelry set "
|
||||
"(earrings, necklaces, bracelets, and rings).")
|
||||
elif occasion == "Outdoor":
|
||||
request_summary += " **OUTDOOR STYLE MANDATE:** No jeans allowed. Focus on functional yet polished alternatives like chinos, technical fabrics, or tailored shorts."
|
||||
elif occasion == "Festival / Concert":
|
||||
request_summary += " **FESTIVAL STYLE MANDATE:** No maxi dresses or maxi skirts. Prioritize shorter hemlines, sets, or trousers to ensure ease of movement."
|
||||
elif occasion == "Beach / Swim":
|
||||
request_summary += " **BEACH STYLE MANDATE:** No denim allowed. Focus on breathable, lightweight fabrics like linen, silk, or crochet."
|
||||
|
||||
sys_template = template.format(
|
||||
gender=self.gender,
|
||||
current_category=current_category.upper(),
|
||||
|
||||
@@ -4,6 +4,8 @@ import litserve as ls
|
||||
import requests
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.config import settings
|
||||
|
||||
|
||||
class PredictRequest(BaseModel):
|
||||
input_image_list: list[str] # 待换脸图片
|
||||
@@ -17,7 +19,7 @@ class ReFace(ls.LitAPI):
|
||||
|
||||
def predict(self, request):
|
||||
# 服务的 URL
|
||||
url = "http://10.1.1.240:10071/predict"
|
||||
url = f"http://{settings.RE_FACE_MODEL_URL}/predict"
|
||||
|
||||
# 请求头
|
||||
headers = {
|
||||
|
||||
@@ -163,7 +163,7 @@ OCCASION_CATEGORY_MAP = {
|
||||
"accessories": ["earrings", "necklaces", "bracelets", "rings"]
|
||||
},
|
||||
"Outdoor": {
|
||||
"clothing": ["jackets", "jeans", "sweaters"],
|
||||
"clothing": ["jackets", "sweaters", "pants", "joggers", "leggings", "shorts"],
|
||||
"shoes": ["boots"],
|
||||
"bags": ["backpacks", "travel bags"],
|
||||
"accessories": []
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
services:
|
||||
lc_agent_server:
|
||||
container_name: LC_Agent_Server
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
@@ -9,12 +10,12 @@ services:
|
||||
DEBUG: 0
|
||||
volumes:
|
||||
- ./app:/app/app
|
||||
- ./.prod_env:/app/.env
|
||||
- ./.env:/app/.env
|
||||
- ./data:/data
|
||||
- ./google_application_credentials.json:/google_application_credentials.json
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "10070:8000"
|
||||
- "${SERVE_PORT}:8000"
|
||||
deploy:
|
||||
resources:
|
||||
reservations:
|
||||
@@ -22,4 +23,10 @@ services:
|
||||
# 告诉 Docker 使用所有可用的 NVIDIA GPU
|
||||
- driver: nvidia
|
||||
device_ids: [ '0' ]
|
||||
capabilities: [ gpu ]
|
||||
capabilities: [ gpu ]
|
||||
networks:
|
||||
- lc_app_net
|
||||
networks:
|
||||
lc_app_net:
|
||||
external: true
|
||||
name: lc_app_net
|
||||
Reference in New Issue
Block a user