push gitignore

This commit is contained in:
zhh
2025-10-24 10:37:19 +08:00
parent ce00630bb2
commit 1adf29a3f6
36 changed files with 6089 additions and 334 deletions

2
.env_local Normal file
View File

@@ -0,0 +1,2 @@
GEMINI_API_KEY=AIzaSyAO4zXFke1bqyrXd9-RGfKJTLerwLSFKww
GOOGLE_APPLICATION_CREDENTIALS="/workspace/lc_stylist_agent/request.json"

4
.gitignore vendored
View File

@@ -1,4 +1,6 @@
.env
.vscode/
app/core/__pycache__/
app/core/data/
app/core/data/
.idea/
*.sqlite3

47
Dockerfile Normal file
View File

@@ -0,0 +1,47 @@
# Change CUDA and cuDNN version here
FROM nvidia/cuda:12.4.1-base-ubuntu22.04
ARG PYTHON_VERSION=3.10
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
software-properties-common \
wget \
&& add-apt-repository ppa:deadsnakes/ppa \
&& apt-get update && apt-get install -y --no-install-recommends \
python$PYTHON_VERSION \
python$PYTHON_VERSION-dev \
python$PYTHON_VERSION-venv \
&& wget https://bootstrap.pypa.io/get-pip.py -O get-pip.py \
&& python$PYTHON_VERSION get-pip.py \
&& rm get-pip.py \
&& ln -sf /usr/bin/python$PYTHON_VERSION /usr/bin/python \
&& ln -sf /usr/local/bin/pip$PYTHON_VERSION /usr/local/bin/pip \
&& python --version \
&& pip --version \
&& apt-get purge -y --auto-remove software-properties-common \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
####### Add your own installation commands here #######
# RUN pip install some-package
# RUN wget https://path/to/some/data/or/weights
# RUN apt-get update && apt-get install -y <package-name>
RUN apt-get update && \
apt-get install -y libcurl4-openssl-dev build-essential
RUN apt-get update
RUN apt-get -y install libgl1
RUN apt-get -y install libglib2.0-0
WORKDIR /app
COPY . /app
# Install litserve and requirements
RUN pip install --upgrade pip setuptools wheel
RUN pip install --no-cache-dir litserve==0.2.16 -r requirements.txt
RUN pip install torch torchvision
EXPOSE 8000
CMD ["python", "-m","app.main"]
#CMD ["tail", "-f","/dev/null"]

7
app/client.py Normal file
View File

@@ -0,0 +1,7 @@
# This file is auto-generated by LitServe.
# Disable auto-generation by setting `generate_client_file=False` in `LitServer.run()`.
import requests
response = requests.post("http://127.0.0.1:8000/predict", json={"input": 4.0})
print(f"Status: {response.status_code}\nResponse:\n {response.text}")

View File

@@ -1,14 +1,16 @@
import time
from typing import Dict, List
import asyncio
from app.core.data_structure import Message, Role
from app.core.llm_interface import AsyncLLMInterface, AsyncGeminiLLM
from app.core.redis_manager import RedisManager
from app.core.redis_manager import RedisManager
from app.core.system_prompt import BASIC_PROMPT, SUMMARY_PROMPT
from app.core.stylist_agent import AsyncStylistAgent
from app.core.vector_database import VectorDatabase
from app.core.config import settings
class ChatbotAgent:
def __init__(self, llm_model: AsyncLLMInterface = None):
self.llm = llm_model if llm_model else AsyncGeminiLLM(model_name=settings.LLM_MODEL_NAME)
@@ -27,7 +29,7 @@ class ChatbotAgent:
'local_db': self.vector_db,
'max_len': 5,
'outfits_root': settings.OUTFIT_OUTPUT_DIR,
'image_dir': settings.IMAGE_DIR,
'image_dir': settings.IMAGE_DIR,
'stylist_guide_dir': settings.STYLIST_GUIDE_DIR,
'gemini_model_name': settings.LLM_MODEL_NAME
}
@@ -54,7 +56,7 @@ class ChatbotAgent:
assistant_msg = Message(role=Role.ASSISTANT, content=response_text)
else:
assistant_msg = Message(role=Role.ASSISTANT, content="No response generated. Try again later.")
self.redis.save_message(user_id, user_msg)
self.redis.save_message(user_id, assistant_msg)
@@ -68,12 +70,12 @@ class ChatbotAgent:
"""
history_messages = self.redis.get_history(user_id)
input_message = "\n".join([f"{msg.role.value}: {msg.content}" for msg in history_messages])
# 临时调用 LLM 或使用本地逻辑生成总结
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
return summary
async def recommend_outfit(self, request_summary: str, stylist_name: str, start_outfit: List[Dict[str, str]] = [], num_outfits: int = 1):
"""
基于用户的对话历史和需求,推荐一套搭配。
@@ -111,25 +113,27 @@ class ChatbotAgent:
print(f"An unexpected error occurred during concurrent recommendation: {e}")
return {"error": str(e)}
if __name__ == "__main__":
async def test():
async def run():
start_time = time.time()
agent = ChatbotAgent()
user_id = "user123"
agent.redis.clear_history(user_id) # 清除历史,便于测试
print(await agent.process_query(user_id, "I want a chic outfit for a summer party."))
print(await agent.process_query(user_id, "I prefer something floral and light."))
user_id = "string"
# agent.redis.clear_history(user_id) # 清除历史,便于测试
# print(await agent.process_query(user_id, "I want a chic outfit for a summer party."))
# print(await agent.process_query(user_id, "I prefer something floral and light."))
request_summary = await agent.get_conversation_summary(user_id)
print(f"Conversation Summary:\n{request_summary}")
recommendation_results = await agent.recommend_outfit(request_summary, stylist_name="crystal", start_outfit=[], num_outfits=2)
recommendation_results = await agent.recommend_outfit(request_summary, stylist_name="crystal", start_outfit=[], num_outfits=4)
print("\n--- Final Recommendation Results ---")
for i, path in enumerate(recommendation_results.get("successful_outfits", [])):
print(f"✅ Outfit {i+1} saved to: {path}")
print(f"✅ Outfit {i + 1} saved to: {path}")
for error in recommendation_results.get("failed_outfits", []):
print(f"{error}")
print(time.time() - start_time)
asyncio.run(test())
asyncio.run(run())

View File

@@ -0,0 +1,163 @@
from google.genai import types
from typing import Dict, List
import asyncio
from google import genai
from app.core import system_prompt
from app.core.data_structure import Message, Role
from app.core.llm_interface_stream import AsyncLLMInterface, AsyncGeminiLLM
from app.core.redis_manager import RedisManager
from app.core.system_prompt import BASIC_PROMPT, SUMMARY_PROMPT
from app.core.stylist_agent import AsyncStylistAgent
from app.core.vector_database import VectorDatabase
from app.core.config import settings
class ChatbotAgent:
def __init__(self, llm_model: AsyncLLMInterface = None):
self.llm = llm_model if llm_model else AsyncGeminiLLM(model_name=settings.LLM_MODEL_NAME)
self.redis = RedisManager(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DB,
key_prefix=settings.REDIS_HISTORY_KEY_PREFIX
)
self.vector_db = VectorDatabase(
vector_db_dir=settings.VECTOR_DB_DIR,
collection_name=settings.COLLECTION_NAME,
embedding_model_name=settings.EMBEDDING_MODEL_NAME
)
self.stylist_agent_kwages = {
'local_db': self.vector_db,
'max_len': 5,
'outfits_root': settings.OUTFIT_OUTPUT_DIR,
'image_dir': settings.IMAGE_DIR,
'stylist_guide_dir': settings.STYLIST_GUIDE_DIR,
'gemini_model_name': settings.LLM_MODEL_NAME
}
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
async def process_query(self, user_id: str, user_message: str) -> str:
"""
处理用户的最新输入,调用 LLM, 并更新历史记录。
"""
# 添加用户消息到历史
user_msg = Message(role=Role.USER, content=user_message)
chat_history = self.redis.get_history(user_id)
chat_history.append(user_msg)
contents = []
for msg in chat_history:
gemini_role = "user" if msg.role == Role.USER else "model"
content = types.Content(
role=gemini_role,
parts=[types.Part.from_text(text=msg.content)]
)
contents.append(content)
response_parts = []
response_stream = await self.gemini_client.aio.models.generate_content_stream(
model='gemini-2.5-flash',
contents=contents,
config=types.GenerateContentConfig(
system_instruction=BASIC_PROMPT,
# temperature=0.3,
)
)
async for chunk in response_stream:
# 您可以在这里处理每一个文本块,例如发送给前端
print(chunk.text, end="", flush=True)
response_parts.append(chunk.text)
# 3. 将所有文本块合并成最终的字符串
response_text = "".join(response_parts)
# 添加助手消息到历史
if response_text:
assistant_msg = Message(role=Role.ASSISTANT, content=response_text)
else:
assistant_msg = Message(role=Role.ASSISTANT, content="No response generated. Try again later.")
self.redis.save_message(user_id, user_msg)
self.redis.save_message(user_id, assistant_msg)
return response_text
async def get_conversation_summary(self, user_id: str) -> str:
"""
分析用户的完整会话历史,并打包成一个简洁的需求总结。
这个总结可以直接作为输入 Prompt 传递给 Stylist Agent。`
"""
history_messages = self.redis.get_history(user_id)
input_message = "\n".join([f"{msg.role.value}: {msg.content}" for msg in history_messages])
# 临时调用 LLM 或使用本地逻辑生成总结
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
return summary
async def recommend_outfit(self, request_summary: str, stylist_name: str, start_outfit: List[Dict[str, str]] = [], num_outfits: int = 1):
"""
基于用户的对话历史和需求,推荐一套搭配。
Args:
request_summary: 用户的request
start_outfit: 可选的初始搭配列表,每个元素包含 'item_id''category'
"""
tasks = []
for _ in range(num_outfits):
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
task = agent.run_styling_process(request_summary, stylist_name, start_outfit)
tasks.append(task)
print(f"--- Starting {num_outfits} concurrent outfit generation tasks. ---")
try:
results = await asyncio.gather(*tasks, return_exceptions=True)
successful_outfits = []
failed_outfits = []
for result in results:
if isinstance(result, Exception):
# 任务执行中发生异常
failed_outfits.append(f"Failed: {result}")
else:
# 任务成功result 是 run_styling_process 返回的图片路径
successful_outfits.append(result)
return {
"successful_outfits": successful_outfits,
"failed_outfits": failed_outfits
}
except Exception as e:
print(f"An unexpected error occurred during concurrent recommendation: {e}")
return {"error": str(e)}
if __name__ == "__main__":
async def run():
# 阶段一:用户对话
agent = ChatbotAgent()
user_id = "string"
# agent.redis.clear_history(user_id) # 清除历史,便于测试
# await agent.process_query(user_id, "I want a chic outfit for a summer party.")
# print(await agent.process_query(user_id, "I prefer something floral and light."))
# 阶段二:读取聊天记录,生成推荐搭配
request_summary = await agent.get_conversation_summary(user_id)
print(f"Conversation Summary:\n{request_summary}")
recommendation_results = await agent.recommend_outfit(request_summary, stylist_name="crystal", start_outfit=[], num_outfits=1)
print("\n--- Final Recommendation Results ---")
for i, path in enumerate(recommendation_results.get("successful_outfits", [])):
print(f"✅ Outfit {i + 1} saved to: {path}")
for error in recommendation_results.get("failed_outfits", []):
print(f"{error}")
asyncio.run(run())

View File

@@ -1,6 +1,7 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field
# ⚠️ 注意: 您需要安装 pydantic-settings: pip install pydantic-settings
class Settings(BaseSettings):
@@ -8,31 +9,32 @@ class Settings(BaseSettings):
应用配置类。Pydantic Settings 会自动从环境变量和 .env 文件中加载这些值。
"""
model_config = SettingsConfigDict(
env_file='.env',
env_file_encoding='utf-8',
extra='ignore' # 忽略环境变量中多余的键
env_file='.env',
env_file_encoding='utf-8',
extra='ignore' # 忽略环境变量中多余的键
)
# Redis 配置
REDIS_HOST: str = Field(default='localhost', description="Redis服务器地址")
REDIS_HOST: str = Field(default='10.1.1.240', description="Redis服务器地址")
REDIS_PORT: int = Field(default=6379, description="Redis服务器端口")
REDIS_DB: int = Field(default=0, description="Redis数据库编号")
REDIS_DB: int = Field(default=3, description="Redis数据库编号")
REDIS_HISTORY_KEY_PREFIX: str = Field(default="chat:history:", description="Redis会话历史键的前缀")
# LLM 配置
GEMINI_API_KEY: str = Field(..., description="Google Gemini API 密钥。必须设置。")
# GEMINI_API_KEY: str = Field(..., description="Google Gemini API 密钥。必须设置。")
LLM_MODEL_NAME: str = Field(default="gemini-2.5-flash", description="使用的 LLM 模型名称")
# 路径配置参数
DATA_ROOT: str = Field(default="./data", description="数据根目录")
IMAGE_DIR: str = Field(default="./data/image_data", description="图片数据目录")
OUTFIT_OUTPUT_DIR: str = Field(default="./data/outfit_output", description="生成的搭配图片输出目录")
STYLIST_GUIDE_DIR: str = Field(default="./data/stylist_guide", description="风格指南文本目录")
DATA_ROOT: str = Field(default="/workspace/lc_stylist_agent/app/core/data", description="数据根目录")
IMAGE_DIR: str = Field(default="/workspace/lc_stylist_agent/app/core/data/image_data", description="图片数据目录")
OUTFIT_OUTPUT_DIR: str = Field(default="/workspace/lc_stylist_agent/app/core/data/outfit_output", description="生成的搭配图片输出目录")
STYLIST_GUIDE_DIR: str = Field(default="/workspace/lc_stylist_agent/app/core/data/stylist_guide", description="风格指南文本目录")
# 向量数据库配置参数
VECTOR_DB_DIR: str = Field(default="./data/db", description="向量数据库目录")
VECTOR_DB_DIR: str = Field(default="./app/core/data/db", description="向量数据库目录")
COLLECTION_NAME: str = Field(default="lc_clothing_embedding", description="向量数据库集合名称")
EMBEDDING_MODEL_NAME: str = Field(default="openai/clip-vit-base-patch32", description="CLIP嵌入模型名称")
# 创建配置实例,供应用其他部分使用
settings = Settings()

View File

@@ -24,13 +24,15 @@ class AsyncGeminiLLM(AsyncLLMInterface):
def __init__(self, model_name: str = "gemini-2.5-flash"):
self.model_name = model_name
try:
self.gemini_client = genai.Client()
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
except Exception as e:
raise type(e)(f"Failed to initialize Gemini Client. Check if GEMINI_API_KEY is set. Original error: {e}")
async def generate_response(self, history: List[Message], system_prompt: str) -> str:
contents = []
for msg in history:
gemini_role = "user" if msg.role == Role.USER else "model"
content = types.Content(
@@ -52,4 +54,3 @@ class AsyncGeminiLLM(AsyncLLMInterface):
except Exception as e:
raise type(e)(f"Gemini API call failed: {e}")

View File

@@ -0,0 +1,61 @@
from abc import ABC, abstractmethod
from typing import List
from google import genai
from google.genai import types
from app.core.data_structure import Message, Role
class AsyncLLMInterface(ABC):
@abstractmethod
async def generate_response(self, history: List[Message], system_prompt: str) -> str:
"""
根据对话历史和系统指令生成回复.
Args:
history: 包含多条 Message 的列表。
Returns:
LLM 生成的回复字符串。
"""
raise NotImplementedError("Subclasses must implement this method")
class AsyncGeminiLLM(AsyncLLMInterface):
def __init__(self, model_name: str = "gemini-2.5-flash"):
self.model_name = model_name
try:
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
except Exception as e:
raise type(e)(f"Failed to initialize Gemini Client. Check if GEMINI_API_KEY is set. Original error: {e}")
async def generate_response(self, history: List[Message], system_prompt: str):
contents = []
for msg in history:
gemini_role = "user" if msg.role == Role.USER else "model"
content = types.Content(
role=gemini_role,
parts=[types.Part.from_text(text=msg.content)]
)
contents.append(content)
return contents
# response_stream = await self.gemini_client.aio.models.generate_content_stream(
# model=self.model_name,
# contents=contents,
# config=types.GenerateContentConfig(
# system_instruction=system_prompt,
# # temperature=0.3,
# )
# )
#
# # 3. 异步迭代流,并 yield 每个块的文本
# async for chunk in response_stream:
# # 确保 chunk 中有可用的文本
# if chunk.text:
# print(chunk.text)
# yield chunk.text

View File

@@ -1,12 +1,17 @@
import logging
import redis
from typing import List, Optional
from app.core.data_structure import Message, Role
logger = logging.getLogger(__name__)
# 这是一个同步 Redis 客户端,用于演示如何替换内存存储。
# 在生产环境和异步 Web 框架中,应替换为 aioredis 等异步客户端。
class RedisManager:
"""同步管理器,用于在 Redis 中存储和检索对话历史。"""
def __init__(self, host: str = 'localhost', port: int = 6379, db: int = 0, key_prefix: str = "chat:history:"):
self.r: Optional[redis.Redis] = None
self.key_prefix = key_prefix
@@ -14,10 +19,10 @@ class RedisManager:
# 尝试连接 Redis
self.r = redis.Redis(host=host, port=port, db=db, decode_responses=True)
self.r.ping()
print("Successfully connected to Redis at {}:{}".format(host, port))
logger.info("Successfully connected to Redis at {}:{}".format(host, port))
except Exception as e:
print(f"⚠️ Failed to connect to Redis: {e}. Falling back to No-Op.")
self.r = None # 连接失败时设置为 None避免后续操作报错
logger.error(f"⚠️ Failed to connect to Redis: {e}. Falling back to No-Op.")
self.r = None # 连接失败时设置为 None避免后续操作报错
def _get_key(self, user_id: str) -> str:
"""生成用户历史记录的 Redis 键名。"""
@@ -32,32 +37,32 @@ class RedisManager:
try:
return Message.model_validate_json(data)
except Exception as e:
print(f"Error deserializing message data: {data[:50]}... Error: {e}")
logger.error(f"Error deserializing message data: {data[:50]}... Error: {e}")
return Message(role=Role.ASSISTANT, content="[Deserialization Error]")
def save_message(self, user_id: str, message: Message):
"""将单条消息保存到用户历史记录列表的末尾。"""
if not self.r:
return
message_json = self._message_to_json(message)
# RPUSH将元素添加到列表的尾部
self.r.rpush(self._get_key(user_id), message_json)
def get_history(self, user_id: str) -> List[Message]:
"""检索用户的完整会话历史记录。"""
if not self.r:
return []
# LRANGE获取列表的所有元素 (0 到 -1)
raw_history = self.r.lrange(self._get_key(user_id), 0, -1)
# 将 JSON 字符串列表转换为 Message 对象列表
messages = [self._json_to_message(data) for data in raw_history]
return messages
def clear_history(self, user_id: str):
"""删除用户的完整历史记录。"""
if self.r:
self.r.delete(self._get_key(user_id))
print(f"History cleared for {user_id}")
logger.info(f"History cleared for {user_id}")

View File

@@ -15,7 +15,9 @@ class AsyncStylistAgent:
def __init__(self, local_db, max_len: int, outfits_root: str, image_dir: str, stylist_guide_dir: str, gemini_model_name: str):
# self.outfit_items: List[Dict[str, str]] = []
self.outfit_id = str(uuid.uuid4())
self.gemini_client = genai.Client()
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
self.local_db = local_db
self.max_len = max_len
self.output_outfit_path = os.path.join(outfits_root, f"{self.outfit_id}.jpg")
@@ -108,15 +110,15 @@ class AsyncStylistAgent:
模型的响应文本(预期为 JSON 字符串)。
"""
content_parts = []
self._clear_uploaded_files()
# self._clear_uploaded_files()
# 1. 添加图片内容
if self.outfit_items:
merged_image_path = merge_images_to_square(self.outfit_items, max_len=self.max_len, output_path=self.output_outfit_path)
try:
myfile = await self.gemini_client.aio.files.upload(file=merged_image_path)
content_parts.append(myfile)
except Exception as e:
print(f"Error loading image {merged_image_path}: {e}")
# if self.outfit_items:
# merged_image_path = merge_images_to_square(self.outfit_items, max_len=self.max_len, output_path=self.output_outfit_path)
# try:
# myfile = await self.gemini_client.aio.files.upload(file=merged_image_path)
# content_parts.append(myfile)
# except Exception as e:
# print(f"Error loading image {merged_image_path}: {e}")
# 2. 添加文本内容
content_parts.append(user_input)

View File

@@ -0,0 +1,436 @@
import asyncio
import io
import json
import logging
import os
import random
import uuid
from typing import List, Dict, Any, Optional
from google import genai
from google.cloud import storage
from google.oauth2 import service_account
from app.core.utils_litserve import merge_images_to_square
from app.server.utils.minio_client import minio_client, oss_upload_image
from app.server.utils.request_post import post_request
logger = logging.getLogger(__name__)
class AsyncStylistAgent:
CATEGORY_SET = {'Activewear', 'Watches', 'Shopping Totes', 'Underwear', 'Sunglasses', 'Dresses', 'Outerwear', 'Handbags', 'Backpacks', 'Belts', 'Hats', 'Skirts', 'Swimwear', 'Jewelry', 'Briefcases', 'Socks', 'Neckties', 'Pants', 'Suits', 'Shoes', 'Shirts & Tops', 'Scarves & Shawls'}
def __init__(self, local_db, max_len: int, gemini_model_name: str):
# self.outfit_items: List[Dict[str, str]] = []
self.outfit_id = str(uuid.uuid4())
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
self.local_db = local_db
self.max_len = max_len
self.gemini_model_name = gemini_model_name
self.stop_reason = ""
# 存储桶配置
try:
# TODO 目前写死路径 生产环境切换路径
self.credentials = service_account.Credentials.from_service_account_file(os.getenv("GOOGLE_APPLICATION_CREDENTIALS"))
except Exception as e:
# 这里的异常处理应根据实际情况调整
raise RuntimeError(f"Failed to load credentials from file {os.getenv('GOOGLE_APPLICATION_CREDENTIALS')}: {e}")
self.gcs_client = storage.Client(
project=self.credentials.project_id,
credentials=self.credentials
)
self.gcs_bucket = "lc_stylist_agent_outfit_items"
self.minio_bucket = "lanecarford"
def _load_style_guide(self, path: str) -> str:
"""加载 markdown 风格指南内容。"""
parts = path.split('/', 1)
if len(parts) != 2:
raise ValueError("MinIO path must be in 'bucket_name/object_name' format.")
bucket_name, object_name = parts
try:
# 1. 获取对象
response = minio_client.get_object(bucket_name, object_name)
# 2. 读取内容
content_bytes = response.read()
# 3. 关闭连接
response.close()
response.release_conn()
# 4. 解码并返回
return content_bytes.decode('utf-8')
except Exception as e:
raise Exception(f"Failed to load style guide from {path}: {e}")
def _build_system_prompt(self, request_summary: str = "") -> str:
"""Constructs the complete System Prompt."""
# Insert the style_guide content into the template
template = f"""
You are a professional fashion stylist Agent, specialized in creating complete outfits for the user.
Your task is to **create a cohesive and complete outfit**, strictly adhering to **BOTH** the user's explicit **Request Summary** and the **Outfit Style Guide**. You must decide the next logical item to add to the outfit based on the currently selected items (if any).
---
## Request from the User:
{request_summary}
## Core Guidance Document: Outfit Style Guide
{self.style_guide}
---
## Your Workflow and Constraints
1. **Style Adherence**: You must strictly observe all rules in the Style Guide concerning **color palette, fit, layering principles, pattern restrictions, accessory stacking, and shoe/bag coordination**.
2. **Step Planning**: The styling sequence must follow a **top-down, inside-out** approach: First major garments (tops/outerwear/bottoms/dresses), then shoes and bags, and finally accessories.
3. **Structured Output**: Every response must recommend the **next single item**. You must strictly use the **JSON format** for your output, as follows:
```json
{{
"action": "recommend_item",
"category": "YOUR_ITEM_CATEGORY",
"description": "YOUR_DETAILED_DESCRIPTION"
}}
```
* `action`: Must always be `"recommend_item"` until the outfit is complete.
* `category`: Must be the category of the item you are recommending, strictly selected from the following list: {list(self.CATEGORY_SET)}.
* `description`: This must be an **extremely detailed and precise** description of the item. This description is used for **high-accuracy vector search** in the database and must include:
* **Color** (e.g., milk tea, pure white, dark gray)
* **Fit/Silhouette** (e.g., Oversize, loose, slim-fit)
* **Material/Detail** (e.g., 100% cotton, linen, gold clasp, thin stripe, checkered pattern)
* **Role in the Outfit** (e.g., serves as the innermost base layer for layering; acts as the crucial tie accent for the smart casual look)
* **[CRITICAL FOR JEWELRY] If recommending 'Jewelry' (especially Necklaces), the description must specify its distinction (length, thickness, pendant style) from all previously selected necklaces to ensure layered variety.**
4. **Termination Condition**: Only when you deem the entire outfit complete and **all mandatory elements stipulated in the Style Guide are met**, you must output the following JSON format to terminate the process:
```json
{{
"action": "stop",
"reason": "OUTFIT_COMPLETE_AND_MEETS_ALL_MINI_GUIDELINES"
}}
```
Normally, five or six items are totally enough for an outfit.
5. **Context Dependency**: The user's next input (if not `Start`) will contain the **image and description of the selected item**. When recommending the next item, you must consider the coordination between the **already selected items** and the Style Guide.
**Now, please start building an outfit and output the JSON for the first item.**
"""
return template.strip()
def _clear_uploaded_files(self):
for f in self.gemini_client.files.list():
self.gemini_client.files.delete(name=f.name)
async def _call_gemini(self, user_input: str, user_id: str):
"""
实际调用 Gemini API 的函数,接受文本和可选的图片路径列表。
Args:
user_input: 发送给模型的主文本内容。
image_paths: 待发送图片的本地路径列表。
Returns:
模型的响应文本(预期为 JSON 字符串)。
"""
minio_path = ""
content_parts = []
# self._clear_uploaded_files()
# 1. 添加图片内容
if self.outfit_items:
merged_image = merge_images_to_square(self.outfit_items, max_len=self.max_len)
image_bytes_io = io.BytesIO()
image_format = 'JPEG'
mime_type = 'image/jpeg'
merged_image.save(image_bytes_io, format=image_format)
image_bytes = image_bytes_io.getvalue()
file_name = uuid.uuid4()
blob_name = f"lc_stylist_agent_outfit_items/{user_id}/{file_name}.jpg"
gcs_path = self._upload_to_gcs(bucket_name=self.gcs_bucket, blob_name=blob_name, mime_type=mime_type, image_bytes=image_bytes)
responses = oss_upload_image(oss_client=minio_client, bucket=self.minio_bucket, object_name=blob_name, image_bytes=image_bytes)
minio_path = f"{responses.bucket_name}/{responses.object_name}"
content_parts.append(gcs_path)
# 2. 添加文本内容
content_parts.append(user_input)
# print(f"\n--- Calling Gemini with {len(self.outfit_items) if self.outfit_items else 0} images and query:\n{user_input}")
try:
# 3. 实际 API 调用
response = await self.gemini_client.aio.models.generate_content(
model=self.gemini_model_name,
contents=content_parts,
config={
"system_instruction": self.system_prompt,
# 确保模型返回 JSON 格式
"response_mime_type": "application/json",
"response_schema": {
"type": "object",
"properties": {
"action": {"type": "string", "enum": ["recommend_item", "stop"]},
"category": {"type": "string"},
"description": {"type": "string"},
"reason": {"type": "string"}
},
"required": ["action"]
}
}
)
# response.text 将包含一个 JSON 字符串
return response.text, minio_path
except Exception as e:
print(f"Gemini API Call failed: {e}")
# 返回一个停止信号以防止循环继续
return json.dumps({"action": "stop", "reason": f"API_ERROR: {str(e)}"})
def _parse_gemini_response(self, response_text: str) -> Optional[Dict[str, Any]]:
"""安全解析 Gemini 的 JSON 响应。"""
try:
# 有时 Gemini 可能会在 JSON 外面添加文字,尝试清理
response_text = response_text.strip().replace('```json', '').replace('```', '')
data = json.loads(response_text)
# print(f"The agent response is: {data}")
return data
except json.JSONDecodeError as e:
print(f"Error parsing JSON from Gemini: {e}")
print(f"Raw response: {response_text}")
return None
def _get_next_item(self, item_description: str, category: str) -> Optional[Dict[str, str]]:
"""
1. 根据描述生成嵌入。
2. 查询本地数据库以找到最佳匹配项。
3. 模拟 Agent 审核匹配项(这里简化为总是通过)。
"""
try:
# 1. 生成查询嵌入
query_embedding = self.local_db.get_clip_embedding(item_description, is_image=False)
# 2. 执行查询,并过滤类别
results = self.local_db.query_local_db(query_embedding, category, n_results=1)
if not results:
print(f"❌ 数据库中未找到符合 '{category}' 和描述的单品。")
return None
# 3. 模拟 Agent 审核(实际应用中,你需要将图片发回给 Agent进行审核)
best_meta = results['metadatas'][0][0] # 第一个 batch 的第一个 metadata
return {
"item_id": best_meta['item_id'], # 从 metadata 字典中安全获取
"category": category,
"gpt_description": item_description,
'description': best_meta['description'],
# 假设 'item_path' 存储在 metadata 中,或从 'item_id' 推导
# 这里假设 item_id 就是文件名的一部分
"image_path": os.path.join(f"{best_meta['item_id']}.jpg")
}
except Exception as e:
print(f"An error occurred during item retrieval: {e}")
return None
def _build_user_input(self) -> str:
"""构建发送给 Gemini 的用户输入,包含已选单品信息。"""
if not self.outfit_items:
return "Start"
# 将已选单品的信息作为上下文发回给 Agent
context = "Selected fashion items:\n"
for ii, item in enumerate(self.outfit_items):
context += f"{ii + 1}. Category: {item['category']}. Description: {item['description']}\n"
context += "\nPlease recommend the next single item based on the selected items, user's request, and style guide."
return context
async def run_styling_process(self, request_summary, stylist_path, start_outfit=None, user_id="test"):
if start_outfit is None:
start_outfit = []
self.outfit_items = start_outfit if start_outfit else []
"""主流程控制循环。"""
print(f"--- Starting Agent (Outfit ID: {self.outfit_id}) ---")
self.style_guide = self._load_style_guide(stylist_path)
self.system_prompt = self._build_system_prompt(request_summary)
response_data = {"status": "",
"message": "",
"path": "",
"outfit_id": self.outfit_id,
"items": []
}
logger.info(response_data)
item_id = ""
while True:
# 1. 准备用户输入(上下文)
user_input = self._build_user_input()
# 2. 调用 Gemini Agent
gemini_response_text, minio_path = await self._call_gemini(user_input, user_id)
gemini_data = self._parse_gemini_response(gemini_response_text)
response_data['path'] = minio_path
if item_id:
response_data['items'].append(item_id)
if not gemini_data:
print("🚨 Agent 返回无效响应,终止流程。")
self.stop_reason = "Agent failed to return response"
response_data['status'] = "failed"
response_data['message'] = self.stop_reason
break
# 3. 检查终止条件
if gemini_data.get('action') == 'stop':
print(f"🛑 搭配完成,终止原因: {gemini_data.get('reason')}")
self.stop_reason = "Finish reason: " + gemini_data.get('reason', 'No reason provided')
response_data['status'] = "stop"
response_data['message'] = self.stop_reason
break
# 4. 处理推荐单品
if gemini_data.get('action') == 'recommend_item':
category = gemini_data.get('category')
description = gemini_data.get('description')
# 4a. 检查类别是否有效 (重要步骤)
if category not in self.CATEGORY_SET:
print(f"❌ Agent 推荐了无效类别: {category}。要求 Agent 重新输出。")
# 在实际应用中,这里需要将错误信息发回给 Agent,要求它更正
# 这里简化为跳过本次循环
response_data['status'] = "continue"
response_data['message'] = f"❌ Agent 推荐了无效类别: {category}。要求 Agent 重新输出。",
continue
# 4b. 在本地 DB 中查询单品
new_item = self._get_next_item(description, category)
item_id = new_item.get('item_id')
if new_item:
# 4c. (实际步骤) 将选中的单品图片和描述发回给 Agent 进行最终审核
# 这里的代码框架省略了图片回传和二次审核的步骤,直接视为通过
# 实际你需要: new_user_input = f"Check this item: {new_item['description']}, path: {new_item['image_path']}"
# call_gemini_agent(...) -> 如果返回"pass",则添加到outfit_items
if new_item['item_id'] in [x['item_id'] for x in self.outfit_items]:
print("This item exists. Stop here.")
self.stop_reason = "Finish reason: Duplicate item selected."
response_data['status'] = "stop"
response_data['message'] = self.stop_reason
break
if new_item['item_id'] == "ELG383":
if random.random() < 0.70:
self.stop_reason = "Finish reason: ELG383 is seleced repeatly."
response_data['status'] = "stop"
response_data['message'] = self.stop_reason
break
self.outfit_items.append(new_item)
# print(f" 成功添加单品: {new_item['category']} ({new_item['item_id']}). 当前搭配数量: {len(self.outfit_items)}")
response_data['status'] = "ok"
response_data['message'] = self.stop_reason
else:
print("⚠️ 未找到匹配单品,无法继续搭配。终止。")
self.stop_reason = "Finish reason: No matching item found in local database."
response_data['status'] = "stop"
response_data['message'] = self.stop_reason
break
if len(self.outfit_items) >= self.max_len: # 设置一个最大循环限制,防止无限循环
print("🚨 达到最大搭配数量限制,强制终止。")
self.stop_reason = "Finish reason: Reached max outfit length."
response_data['status'] = "stop"
response_data['message'] = self.stop_reason
logger.info(response_data)
break
logger.info(response_data)
headers = {
'Accept': "*/*",
'Accept-Encoding': "gzip, deflate, br",
'User-Agent': "PostmanRuntime-ApipostRuntime/1.1.0",
'Connection': "keep-alive",
'Content-Type': "application/json"
}
url = 'https://83aa2db8e006.ngrok-free.app/api/style/callback'
response = post_request(url=url, data=json.dumps(response_data), headers=headers)
logger.info(response.text)
return response_data
# def _save_outfit_results(self, user_id):
# """保存最终的 JSON 列表和图片到指定文件夹。"""
# if not self.outfit_items:
# raise ValueError("No outfit items to save.")
#
# # 1. 保存 JSON 文件
# results_list = [{'item_id': item['item_id'], 'category': item['category'], 'description': item['description'], 'gpt_description': item['gpt_description']} for item in self.outfit_items]
# results_list.append({'stop_reason': self.stop_reason})
#
# return upload_json_to_minio_sync(
# minio_client=minio_client,
# bucket_name=f"lanecarford",
# object_name=f"lc_stylist_agent_outfit_items/{user_id}/{uuid.uuid4()}.json",
# data=results_list
# )
def _upload_to_gcs(self, bucket_name: str, blob_name: str, mime_type, image_bytes) -> str:
"""同步方法:将文件上传到 GCS 并返回 GCS URI。"""
bucket = self.gcs_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
blob.upload_from_string(
data=image_bytes,
content_type=mime_type
)
gcs_uri = f"gs://{bucket_name}/{blob_name}"
return gcs_uri
async def recommend_outfit(self, request_summary: str, stylist_name: str, start_outfit: List[Dict[str, str]] = [], num_outfits: int = 1):
"""
基于用户的对话历史和需求,推荐一套搭配。
Args:
request_summary: 用户的request
start_outfit: 可选的初始搭配列表,每个元素包含 'item_id''category'
"""
tasks = []
for _ in range(num_outfits):
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
task = agent.run_styling_process(request_summary, stylist_name, start_outfit)
tasks.append(task)
print(f"--- Starting {num_outfits} concurrent outfit generation tasks. ---")
try:
results = await asyncio.gather(*tasks, return_exceptions=True)
successful_outfits = []
failed_outfits = []
for result in results:
if isinstance(result, Exception):
# 任务执行中发生异常
failed_outfits.append(f"Failed: {result}")
else:
# 任务成功result 是 run_styling_process 返回的图片路径
successful_outfits.append(result)
return {
"successful_outfits": successful_outfits,
"failed_outfits": failed_outfits
}
except Exception as e:
print(f"An unexpected error occurred during concurrent recommendation: {e}")
return {"error": str(e)}

View File

@@ -7,20 +7,21 @@ from PIL import Image, ImageDraw, ImageFont
# 布局顺序: 从上到下,从左到右 (1 -> 9)
ALL_9_CELLS = [
# Top Row (Y=0, H=341)
(0, 0, 341, 341), # 1. Top-Left (341x341)
(0, 0, 341, 341), # 1. Top-Left (341x341)
(341, 0, 341, 341), # 2. Top-Middle (341x341)
(682, 0, 342, 341), # 3. Top-Right (342x341)
# Middle Row (Y=341, H=341)
(0, 341, 341, 341), # 4. Mid-Left (341x341)
(341, 341, 341, 341),# 5. Center (341x341)
(682, 341, 342, 341),# 6. Mid-Right (342x341)
(341, 341, 341, 341), # 5. Center (341x341)
(682, 341, 342, 341), # 6. Mid-Right (342x341)
# Bottom Row (Y=682, H=342)
(0, 682, 341, 342), # 7. Bottom-Left (341x342)
(341, 682, 341, 342),# 8. Bottom-Middle (341x342)
(682, 682, 342, 342) # 9. Bottom-Right (342x342)
(341, 682, 341, 342), # 8. Bottom-Middle (341x342)
(682, 682, 342, 342) # 9. Bottom-Right (342x342)
]
def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output_path="temp.jpg", add_text=True) -> str:
def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output_path="temp.jpg", add_text=True):
"""
Loads up to 4 images from the given paths, resizes them while maintaining
aspect ratio, and merges them onto a 1024x1024 white background JPG.
@@ -37,31 +38,30 @@ def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output
Returns:
The file path of the temporary merged JPG image.
"""
# Define the final canvas size
CANVAS_SIZE = 1024
# 1. Create the final white canvas
# Using 'RGB' mode for JPG output
canvas = Image.new('RGB', (CANVAS_SIZE, CANVAS_SIZE), 'white')
draw = ImageDraw.Draw(canvas)
font = ImageFont.load_default()
# 2. Define the quadrants/target areas (x, y, w, h)
# The positions are based on a 512x512 quadrant size
quadrants = {
1: [(0, 0, CANVAS_SIZE, CANVAS_SIZE)], # Single full-size placement
2: [(0, 0, 512, CANVAS_SIZE), (512, 0, 512, CANVAS_SIZE)], # Left, Right
3: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512)], # Top-Left, Top-Right, Bottom-Left
4: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512), (512, 512, 512, 512)], # All Four
5: ALL_9_CELLS[:5], # 布局前5个单元格 (1-5)
6: ALL_9_CELLS[:6], # 布局前6个单元格 (1-6)
7: ALL_9_CELLS[:7], # 布局前7个单元格 (1-7)
8: ALL_9_CELLS[:8], # 布局前8个单元格 (1-8)
1: [(0, 0, CANVAS_SIZE, CANVAS_SIZE)], # Single full-size placement
2: [(0, 0, 512, CANVAS_SIZE), (512, 0, 512, CANVAS_SIZE)], # Left, Right
3: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512)], # Top-Left, Top-Right, Bottom-Left
4: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512), (512, 512, 512, 512)], # All Four
5: ALL_9_CELLS[:5], # 布局前5个单元格 (1-5)
6: ALL_9_CELLS[:6], # 布局前6个单元格 (1-6)
7: ALL_9_CELLS[:7], # 布局前7个单元格 (1-7)
8: ALL_9_CELLS[:8], # 布局前8个单元格 (1-8)
9: ALL_9_CELLS[:9] # 布局全部9个单元格 (1-9)
}
# 3. Load and Filter Images
valid_images = []
image_paths = [item['image_path'] for item in outfit_items]
@@ -75,17 +75,16 @@ def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output
print(f"Error loading image {path}. Skipping: {e}")
num_images = len(valid_images)
if num_images == 0:
raise ValueError("No valid images were loaded.")
if num_images > max_len:
raise ValueError(f"Valid item number {num_images} exceed max limit {max_len}")
# Get the correct list of target areas based on the number of valid images
target_areas = quadrants.get(num_images, [])
# 4. Resize and Paste
for i, (img, item) in enumerate(zip(valid_images, outfit_items)):
item_id = item['item_id']
@@ -93,40 +92,40 @@ def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output
if i >= len(target_areas):
# This should not happen if num_images <= 4
break
# Target area dimensions (x_start, y_start, width, height)
x_start, y_start, target_w, target_h = target_areas[i]
# Calculate new size while maintaining aspect ratio
original_w, original_h = img.size
# Calculate the ratio needed to fit within the target area
ratio_w = target_w / original_w
ratio_h = target_h / original_h
# Use the *smaller* of the two ratios to ensure the image fits entirely
resize_ratio = min(ratio_w, ratio_h)
# Calculate the new dimensions
new_w = int(original_w * resize_ratio)
new_h = int(original_h * resize_ratio)
# Resize the image. Image.Resampling.LANCZOS provides high-quality scaling.
# Pillow documentation recommends ANTIALIAS or BICUBIC for downscaling,
# but LANCZOS is a good general high-quality filter.
# Note: In Pillow versions > 9.0.0, Image.LANCZOS is now Image.Resampling.LANCZOS
resized_img = img.resize((new_w, new_h), Image.Resampling.LANCZOS)
# Calculate the paste position to center the resized image within its target area
# Center X: (Target Width - New Width) / 2 + X Start
paste_x = (target_w - new_w) // 2 + x_start
# Center Y: (Target Height - New Height) / 2 + Y Start
# paste_y = (target_h - new_h) // 2 + y_start
TEXT_RESERVE_HEIGHT = 30
paste_y = (target_h - new_h - TEXT_RESERVE_HEIGHT) // 2 + y_start
paste_y = max(paste_y, y_start)
TEXT_RESERVE_HEIGHT = 30
paste_y = (target_h - new_h - TEXT_RESERVE_HEIGHT) // 2 + y_start
paste_y = max(paste_y, y_start)
# Paste the resized image onto the canvas
canvas.paste(resized_img, (paste_x, paste_y))
@@ -140,24 +139,22 @@ def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, output
# 兼容旧版本 Pillow
text_w, text_h = draw.textsize(full_text, font=font)
# 计算 X 轴起始位置:使其在目标区域 (target_w) 中居中
text_x_center = x_start + target_w // 2
text_x_start = text_x_center - text_w // 2
# 计算 Y 轴起始位置:将其放在目标区域的底部
# (目标区域的起始Y + 目标区域的高度 - 文本行的高度)
text_y_start = y_start + target_h - text_h - 5 # 减去 5 像素作为边距
text_y_start = y_start + target_h - text_h - 5 # 减去 5 像素作为边距
# 3. 绘制合并后的文本
if add_text:
draw.text((text_x_start, text_y_start),
full_text,
fill='black',
font=font)
draw.text((text_x_start, text_y_start),
full_text,
fill='black',
font=font)
# Save as a high-quality JPG (quality=90 is a good balance)
canvas.save(output_path, 'JPEG', quality=90)
return output_path
# canvas.save(output_path, 'JPEG', quality=90)
return canvas

163
app/core/utils_litserve.py Normal file
View File

@@ -0,0 +1,163 @@
import logging
from typing import List, Dict
from PIL import Image, ImageDraw, ImageFont
from app.server.utils.minio_client import oss_get_image, minio_client
from app.server.utils.minio_config import MINIO_LC_DATA_PATH
logger = logging.getLogger(__name__)
# 9个 341x341 左右的单元格 (ALL_9_CELLS)
# 布局顺序: 从上到下,从左到右 (1 -> 9)
ALL_9_CELLS = [
# Top Row (Y=0, H=341)
(0, 0, 341, 341), # 1. Top-Left (341x341)
(341, 0, 341, 341), # 2. Top-Middle (341x341)
(682, 0, 342, 341), # 3. Top-Right (342x341)
# Middle Row (Y=341, H=341)
(0, 341, 341, 341), # 4. Mid-Left (341x341)
(341, 341, 341, 341), # 5. Center (341x341)
(682, 341, 342, 341), # 6. Mid-Right (342x341)
# Bottom Row (Y=682, H=342)
(0, 682, 341, 342), # 7. Bottom-Left (341x342)
(341, 682, 341, 342), # 8. Bottom-Middle (341x342)
(682, 682, 342, 342) # 9. Bottom-Right (342x342)
]
def merge_images_to_square(outfit_items: List[Dict[str, str]], max_len=9, add_text=True):
"""
Loads up to 4 images from the given paths, resizes them while maintaining
aspect ratio, and merges them onto a 1024x1024 white background JPG.
The layout depends on the number of images:
1: Center the single image on the 1024x1024 canvas.
2: Place side-by-side, each scaled to fit a 512x1024 half.
3: Place in top-left (512x512), top-right (512x512), and bottom-left (512x512).
4: Place in all four 512x512 quadrants.
Args:
outfit_items: A list of item metadata (max length 9).
Returns:
The file path of the temporary merged JPG image.
"""
# Define the final canvas size
CANVAS_SIZE = 1024
# 1. Create the final white canvas
# Using 'RGB' mode for JPG output
canvas = Image.new('RGB', (CANVAS_SIZE, CANVAS_SIZE), 'white')
draw = ImageDraw.Draw(canvas)
font = ImageFont.load_default()
# 2. Define the quadrants/target areas (x, y, w, h)
# The positions are based on a 512x512 quadrant size
quadrants = {
1: [(0, 0, CANVAS_SIZE, CANVAS_SIZE)], # Single full-size placement
2: [(0, 0, 512, CANVAS_SIZE), (512, 0, 512, CANVAS_SIZE)], # Left, Right
3: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512)], # Top-Left, Top-Right, Bottom-Left
4: [(0, 0, 512, 512), (512, 0, 512, 512), (0, 512, 512, 512), (512, 512, 512, 512)], # All Four
5: ALL_9_CELLS[:5], # 布局前5个单元格 (1-5)
6: ALL_9_CELLS[:6], # 布局前6个单元格 (1-6)
7: ALL_9_CELLS[:7], # 布局前7个单元格 (1-7)
8: ALL_9_CELLS[:8], # 布局前8个单元格 (1-8)
9: ALL_9_CELLS[:9] # 布局全部9个单元格 (1-9)
}
# 3. Load and Filter Images
valid_images = []
image_paths = [item['image_path'] for item in outfit_items]
for path in image_paths:
try:
# We use Image.open() and convert to 'RGB' to handle potential transparency (RGBA)
# and ensure compatibility with the final 'RGB' canvas and JPG output.
img = oss_get_image(oss_client=minio_client, path=f"{MINIO_LC_DATA_PATH}/{path}", data_type="PIL").convert('RGB')
# img = Image.open(path).convert('RGB')
valid_images.append(img)
except Exception as e:
logger.error(f"Error loading image {path}. Skipping: {e}")
num_images = len(valid_images)
if num_images == 0:
raise ValueError("No valid images were loaded.")
if num_images > max_len:
raise ValueError(f"Valid item number {num_images} exceed max limit {max_len}")
# Get the correct list of target areas based on the number of valid images
target_areas = quadrants.get(num_images, [])
# 4. Resize and Paste
for i, (img, item) in enumerate(zip(valid_images, outfit_items)):
item_id = item['item_id']
category = item['category']
if i >= len(target_areas):
# This should not happen if num_images <= 4
break
# Target area dimensions (x_start, y_start, width, height)
x_start, y_start, target_w, target_h = target_areas[i]
# Calculate new size while maintaining aspect ratio
original_w, original_h = img.size
# Calculate the ratio needed to fit within the target area
ratio_w = target_w / original_w
ratio_h = target_h / original_h
# Use the *smaller* of the two ratios to ensure the image fits entirely
resize_ratio = min(ratio_w, ratio_h)
# Calculate the new dimensions
new_w = int(original_w * resize_ratio)
new_h = int(original_h * resize_ratio)
# Resize the image. Image.Resampling.LANCZOS provides high-quality scaling.
# Pillow documentation recommends ANTIALIAS or BICUBIC for downscaling,
# but LANCZOS is a good general high-quality filter.
# Note: In Pillow versions > 9.0.0, Image.LANCZOS is now Image.Resampling.LANCZOS
resized_img = img.resize((new_w, new_h), Image.Resampling.LANCZOS)
# Calculate the paste position to center the resized image within its target area
# Center X: (Target Width - New Width) / 2 + X Start
paste_x = (target_w - new_w) // 2 + x_start
# Center Y: (Target Height - New Height) / 2 + Y Start
# paste_y = (target_h - new_h) // 2 + y_start
TEXT_RESERVE_HEIGHT = 30
paste_y = (target_h - new_h - TEXT_RESERVE_HEIGHT) // 2 + y_start
paste_y = max(paste_y, y_start)
# Paste the resized image onto the canvas
canvas.paste(resized_img, (paste_x, paste_y))
full_text = f"ID: {item_id}, Category: {category}"
try:
# 推荐使用:计算文本的实际尺寸 (width, height)
bbox = draw.textbbox((0, 0), full_text, font=font)
text_w = bbox[2] - bbox[0]
text_h = bbox[3] - bbox[1]
except AttributeError:
# 兼容旧版本 Pillow
text_w, text_h = draw.textsize(full_text, font=font)
# 计算 X 轴起始位置:使其在目标区域 (target_w) 中居中
text_x_center = x_start + target_w // 2
text_x_start = text_x_center - text_w // 2
# 计算 Y 轴起始位置:将其放在目标区域的底部
# (目标区域的起始Y + 目标区域的高度 - 文本行的高度)
text_y_start = y_start + target_h - text_h - 5 # 减去 5 像素作为边距
# 3. 绘制合并后的文本
if add_text:
draw.text((text_x_start, text_y_start),
full_text,
fill='black',
font=font)
# Save as a high-quality JPG (quality=90 is a good balance)
# canvas.save(output_path, 'JPEG', quality=90)
return canvas

View File

@@ -9,9 +9,9 @@ from PIL import Image
class VectorDatabase():
def __init__(self, vector_db_dir: str, collection_name: str, embedding_model_name: str):
print(vector_db_dir)
self.client = chromadb.PersistentClient(path=vector_db_dir)
self.collection = self.client.get_collection(name=collection_name)
self.collection = self.client.get_or_create_collection(name=collection_name)
self.device = "cuda" if torch.cuda.is_available() else "cpu"
@@ -20,7 +20,7 @@ class VectorDatabase():
def get_clip_embedding(self, data: str | Image.Image, is_image: bool) -> List[float]:
"""生成图像或文本的 CLIP 嵌入,并进行 L2 归一化。"""
if is_image:
inputs = self.processor(images=data, return_tensors="pt").to(self.device)
with torch.no_grad():
@@ -28,25 +28,24 @@ class VectorDatabase():
else:
# 强制截断,解决序列长度问题
inputs = self.processor(
text=[data],
return_tensors="pt",
text=[data],
return_tensors="pt",
padding=True,
truncation=True
truncation=True
).to(self.device)
with torch.no_grad():
features = self.model.get_text_features(**inputs)
# L2 归一化
features = features / features.norm(p=2, dim=-1, keepdim=True)
return features.cpu().numpy().flatten().tolist()
def query_local_db(self, embedding: List[float], category: str, n_results: int = 3) -> List[Dict[str, Any]]:
"""
基于嵌入向量在本地数据库中查询相似单品。
实际应执行 ChromaDB 查询,并根据 category 进行过滤(metadatas)。
"""
print(f"--- Querying DB for Category: {category} ---")
# 实际应执行向量查询
# 为了演示流程,返回一个模拟结果
results = self.collection.query(
@@ -60,4 +59,4 @@ class VectorDatabase():
},
include=['documents', 'metadatas', 'distances']
)
return results
return results

1230
app/logs/debug.log Normal file

File diff suppressed because it is too large Load Diff

124
app/logs/error.log Normal file
View File

@@ -0,0 +1,124 @@
2025-10-23 21:43:04,108 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /app/request.json was not found.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/test/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /app/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /app/request.json was not found.
2025-10-23 21:43:39,697 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-5' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /app/request.json was not found.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/test/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/test/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/home/user/miniconda3/envs/test/lib/python3.10/site-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /app/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /app/request.json was not found.
2025-10-23 21:44:09,080 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 09:59:19,870 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 09:59:51,131 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 10:15:04,724 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 10:15:11,944 base_events.py [line:1758] ERROR Unclosed client session
client_session: <aiohttp.client.ClientSession object at 0x7c7cc2989ff0>

1230
app/logs/info.log Normal file

File diff suppressed because it is too large Load Diff

26
app/main.py Normal file
View File

@@ -0,0 +1,26 @@
import logging.config
import os
import litserve as ls
from app.server.ChatbotAgent.agent_server import LCAgent
from app.server.ChatbotAgent.chatbot_server import LCChatBot
from logging_env import LOGGER_CONFIG_DICT
logger = logging.getLogger(__name__)
# 判断目录是否存在
logs = 'logs'
if not os.path.exists(logs):
# 不存在则创建目录parents=True 允许创建多级目录exist_ok=True 避免目录已存在时报错)
os.makedirs(logs, exist_ok=True)
logger.info(f"目录 {logs} 创建成功")
else:
logger.info(f"目录 {logs} 已存在")
logging.config.dictConfig(LOGGER_CONFIG_DICT)
# STEP 2: START THE SERVER
if __name__ == "__main__":
chat_boot_api = LCChatBot(enable_async=True, stream=True, api_path='/api/v1/chatbot')
agent_api = LCAgent(enable_async=True, api_path='/api/v1/agent')
server = ls.LitServer([chat_boot_api, agent_api])
server.run(port=8001)

View File

@@ -0,0 +1,129 @@
import asyncio
import json
import logging
import uuid
from typing import List, Dict
import litserve as ls
from pydantic import BaseModel
from app.core.config import settings
from app.core.data_structure import Message, Role
from app.core.llm_interface import AsyncGeminiLLM
from app.core.redis_manager import RedisManager
from app.core.stylist_agent_server import AsyncStylistAgent
from app.core.system_prompt import SUMMARY_PROMPT
from app.core.vector_database import VectorDatabase
logger = logging.getLogger(__name__)
class AgentRequestModel(BaseModel):
user_id: str
num_outfits: int
stylist_path: str
class LCAgent(ls.LitAPI):
def setup(self, device):
self.llm = AsyncGeminiLLM(model_name=settings.LLM_MODEL_NAME)
self.redis = RedisManager(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DB,
key_prefix=settings.REDIS_HISTORY_KEY_PREFIX
)
self.vector_db = VectorDatabase(
vector_db_dir=settings.VECTOR_DB_DIR,
collection_name=settings.COLLECTION_NAME,
embedding_model_name=settings.EMBEDDING_MODEL_NAME
)
self.stylist_agent_kwages = {
'local_db': self.vector_db,
'max_len': 5,
'gemini_model_name': settings.LLM_MODEL_NAME
}
async def decode_request(self, request: AgentRequestModel):
logger.info(f"request: {request.model_dump()}")
return request
async def predict(self, request):
asyncio.create_task(self.background_run(request))
return {"status": "Task initiated in background."}
async def encode_response(self, output):
return output
async def background_run(self, request: AgentRequestModel):
# 1. 根据用户ID查询对话历史总结对话内容
request_summary = await self.get_conversation_summary(request.user_id)
logger.info(f"request_summary: {request_summary}")
# 2.根据对话总结推荐搭配
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
stylist_name=request.stylist_path,
start_outfit=[],
num_outfits=request.num_outfits,
user_id=request.user_id)
logger.info("\n--- Final Recommendation Results ---")
for i, path in enumerate(recommendation_results.get("successful_outfits", [])):
logger.info(f"✅ Outfit {i + 1} saved to: {path}")
for error in recommendation_results.get("failed_outfits", []):
logger.error(f"{error}")
async def get_conversation_summary(self, user_id: str) -> str:
"""
分析用户的完整会话历史,并打包成一个简洁的需求总结。
这个总结可以直接作为输入 Prompt 传递给 Stylist Agent。`
"""
history_messages = self.redis.get_history(user_id)
input_message = "\n".join([f"{msg.role.value}: {msg.content}" for msg in history_messages])
# 临时调用 LLM 或使用本地逻辑生成总结
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
return summary
async def recommend_outfit(self, request_summary: str, stylist_name: str, start_outfit=None, num_outfits: int = 1, user_id: str = "test"):
"""
基于用户的对话历史和需求,推荐一套搭配。
Args:
request_summary: 用户的request
start_outfit: 可选的初始搭配列表,每个元素包含 'item_id''category'
"""
if start_outfit is None:
start_outfit = []
tasks = []
for _ in range(num_outfits):
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
task = agent.run_styling_process(
request_summary=request_summary,
stylist_path=stylist_name,
start_outfit=start_outfit,
user_id=user_id
)
tasks.append(task)
print(f"--- Starting {num_outfits} concurrent outfit generation tasks. ---")
try:
results = await asyncio.gather(*tasks, return_exceptions=True)
successful_outfits = []
failed_outfits = []
for result in results:
if isinstance(result, Exception):
# 任务执行中发生异常
failed_outfits.append(f"Failed: {result}")
else:
# 任务成功result 是 run_styling_process 返回的图片路径
successful_outfits.append(result)
return {
"successful_outfits": successful_outfits,
"failed_outfits": failed_outfits
}
except Exception as e:
print(f"An unexpected error occurred during concurrent recommendation: {e}")
return {"error": str(e)}

View File

@@ -0,0 +1,188 @@
# server.py
import asyncio
import logging
import time
from typing import AsyncGenerator
from google import genai
import litserve as ls
from pydantic import BaseModel
from app.core.config import settings
from app.core.data_structure import Role, Message
from app.core.llm_interface import AsyncGeminiLLM
from app.core.redis_manager import RedisManager
from app.core.stylist_agent import AsyncStylistAgent
from app.core.system_prompt import BASIC_PROMPT, SUMMARY_PROMPT
from app.core.vector_database import VectorDatabase
from google.genai import types
logger = logging.getLogger(__name__)
class PredictRequest(BaseModel):
user_id: str # 用戶ID
user_message: str # 用戶輸入
class LCChatBot(ls.LitAPI):
def setup(self, device):
self.llm = AsyncGeminiLLM(model_name=settings.LLM_MODEL_NAME)
self.redis = RedisManager(
host=settings.REDIS_HOST,
port=settings.REDIS_PORT,
db=settings.REDIS_DB,
key_prefix=settings.REDIS_HISTORY_KEY_PREFIX
)
self.vector_db = VectorDatabase(
vector_db_dir=settings.VECTOR_DB_DIR,
collection_name=settings.COLLECTION_NAME,
embedding_model_name=settings.EMBEDDING_MODEL_NAME
)
self.stylist_agent_kwages = {
'local_db': self.vector_db,
'max_len': 5,
'outfits_root': settings.OUTFIT_OUTPUT_DIR,
'image_dir': settings.IMAGE_DIR,
'stylist_guide_dir': settings.STYLIST_GUIDE_DIR,
'gemini_model_name': settings.LLM_MODEL_NAME
}
self.gemini_client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
async def decode_request(self, request: PredictRequest):
return request
async def predict(self, request) -> AsyncGenerator[str, None]:
# 添加用户消息到历史
user_message = request.user_message
user_id = request.user_id
user_msg = Message(role=Role.USER, content=user_message)
chat_history = self.redis.get_history(user_id)
chat_history.append(user_msg)
contents = []
for msg in chat_history:
gemini_role = "user" if msg.role == Role.USER else "model"
content = types.Content(
role=gemini_role,
parts=[types.Part.from_text(text=msg.content)]
)
contents.append(content)
response_stream = await self.gemini_client.aio.models.generate_content_stream(
model='gemini-2.5-flash',
contents=contents,
config=types.GenerateContentConfig(
system_instruction=BASIC_PROMPT,
# temperature=0.3,
)
)
full_response_text = ""
# 异步迭代流
async for chunk in response_stream:
if chunk:
logger.info(chunk.text)
# 2. 实时 yield 文本块给 encode_response
yield chunk.text
# 3. 累加文本块以保存完整的历史记录
full_response_text += chunk.text
# 添加助手消息到历史
if full_response_text:
assistant_msg = Message(role=Role.ASSISTANT, content=full_response_text)
else:
assistant_msg = Message(role=Role.ASSISTANT, content="No response generated. Try again later.")
self.redis.save_message(user_id, user_msg)
self.redis.save_message(user_id, assistant_msg)
async def encode_response(self, output):
# The for-loop must have async keyword here since output is an AsyncGenerator
async for out in output:
yield {"output": out}
async def process_query(self, user_id: str, user_message: str) -> str:
"""
处理用户的最新输入,调用 LLM, 并更新历史记录。
"""
# 添加用户消息到历史
user_msg = Message(role=Role.USER, content=user_message)
chat_history = self.redis.get_history(user_id)
chat_history.append(user_msg)
# 生成 LLM 回复
try:
response_text = await self.llm.generate_response(chat_history, system_prompt=BASIC_PROMPT)
except Exception as e:
logger("\n--- Final Recommendation Results ---")
logger.error(f"LLM 调用失败: {e}")
response_text = "抱歉,系统暂时无法响应,请稍后再试。"
# 添加助手消息到历史
if response_text:
assistant_msg = Message(role=Role.ASSISTANT, content=response_text)
else:
assistant_msg = Message(role=Role.ASSISTANT, content="No response generated. Try again later.")
self.redis.save_message(user_id, user_msg)
self.redis.save_message(user_id, assistant_msg)
return response_text
async def get_conversation_summary(self, user_id: str) -> str:
"""
分析用户的完整会话历史,并打包成一个简洁的需求总结。
这个总结可以直接作为输入 Prompt 传递给 Stylist Agent。`
"""
history_messages = self.redis.get_history(user_id)
input_message = "\n".join([f"{msg.role.value}: {msg.content}" for msg in history_messages])
# 临时调用 LLM 或使用本地逻辑生成总结
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
return summary
async def recommend_outfit(self, request_summary: str, stylist_name: str, start_outfit=None, num_outfits: int = 1):
"""
基于用户的对话历史和需求,推荐一套搭配。
Args:
request_summary: 用户的request
start_outfit: 可选的初始搭配列表,每个元素包含 'item_id''category'
"""
if start_outfit is None:
start_outfit = []
tasks = []
for _ in range(num_outfits):
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
task = agent.run_styling_process(request_summary, stylist_name, start_outfit)
tasks.append(task)
logger.info(f"--- Starting {num_outfits} concurrent outfit generation tasks. ---")
try:
results = await asyncio.gather(*tasks, return_exceptions=True)
successful_outfits = []
failed_outfits = []
for result in results:
if isinstance(result, Exception):
# 任务执行中发生异常
failed_outfits.append(f"Failed: {result}")
else:
# 任务成功result 是 run_styling_process 返回的图片路径
successful_outfits.append(result)
return {
"successful_outfits": successful_outfits,
"failed_outfits": failed_outfits
}
except Exception as e:
logger.error(f"An unexpected error occurred during concurrent recommendation: {e}")
return {"error": str(e)}

View File

@@ -0,0 +1,125 @@
import io
import json
import logging
from io import BytesIO
import cv2
import numpy as np
import urllib3
from PIL import Image
from minio import Minio
from app.server.utils.minio_config import MINIO_ACCESS, MINIO_SECRET, MINIO_URL, MINIO_SECURE
minio_client = Minio(MINIO_URL, access_key=MINIO_ACCESS, secret_key=MINIO_SECRET, secure=MINIO_SECURE)
# 自定义 Retry 类
class CustomRetry(urllib3.Retry):
def increment(self, method=None, url=None, response=None, error=None, **kwargs):
# 调用父类的 increment 方法
new_retry = super(CustomRetry, self).increment(method, url, response, error, **kwargs)
# 打印重试信息
logger.info(f"重试连接: {method} {url},错误: {error},重试次数: {self.total - new_retry.total}")
return new_retry
logger = logging.getLogger()
timeout = urllib3.Timeout(connect=1, read=10.0) # 连接超时 5 秒,读取超时 10 秒
http_client = urllib3.PoolManager(
num_pools=10, # 设置连接池大小
maxsize=10,
timeout=timeout,
cert_reqs='CERT_REQUIRED', # 需要证书验证
retries=CustomRetry(
total=5,
backoff_factor=0.2,
status_forcelist=[500, 502, 503, 504],
),
)
# 获取图片
def oss_get_image(oss_client, path, data_type):
# cv2 默认全通道读取
bucket = path.split("/", 1)[0]
object_name = path.split("/", 1)[1]
image_object = None
try:
image_data = oss_client.get_object(bucket_name=bucket, object_name=object_name)
if data_type == "cv2":
image_bytes = image_data.read()
image_array = np.frombuffer(image_bytes, np.uint8) # 转成8位无符号整型
image_object = cv2.imdecode(image_array, cv2.IMREAD_UNCHANGED)
if image_object.dtype == np.uint16:
image_object = (image_object / 256).astype('uint8')
else:
data_bytes = BytesIO(image_data.read())
image_object = Image.open(data_bytes)
except Exception as e:
logger.warning(f"获取图片出现异常 ######: {e}")
return image_object
def oss_upload_image(oss_client, bucket, object_name, image_bytes):
req = None
try:
req = oss_client.put_object(bucket_name=bucket, object_name=object_name, data=io.BytesIO(image_bytes), length=len(image_bytes), content_type='image/png')
except Exception as e:
logger.warning(f"上传图片出现异常 ######: {e}")
return req
# def upload_json_to_minio_sync(
# minio_client: Minio,
# bucket_name: str,
# object_name: str,
# data: list
# ) -> str:
# """
# 将 Python 字典转换为 JSON 字符串,并上传到 MinIO。
#
# :param minio_client: 已初始化的 MinIO 客户端实例。
# :param bucket_name: 目标 Bucket 名称。
# :param object_name: 目标文件路径/名称 (e.g., 'data/report.json')。
# :param data: 要上传的 Python 字典数据。
# :return: 成功返回 True失败返回 False。
# """
# try:
# # 1. 将 Python 字典序列化为 JSON 字符串
# json_string = json.dumps(data, ensure_ascii=False, indent=2)
# # 2. 将 JSON 字符串编码为字节流 (bytes)
# json_bytes = json_string.encode('utf-8')
#
# # 3. 创建 BytesIO 对象,用于从内存读取数据
# data_stream = io.BytesIO(json_bytes)
#
# # 4. 使用 put_object 上传数据流
# minio_client.put_object(
# bucket_name,
# object_name,
# data_stream,
# length=len(json_bytes),
# content_type='application/json; charset=utf-8' # 设置正确的 MIME 类型
# )
# logger.info(f"✅ JSON file uploaded successfully to {bucket_name}/{object_name}")
# return f'{bucket_name}/{object_name}'
#
# except Exception as e:
# logger.error(f"❌ An unexpected error occurred: {e}")
# return False
if __name__ == '__main__':
# url = "lanecarford/lc_stylist_agent_outfit_items/string/7fed1c7b-9efd-41fa-a335-182c310ea611.jpg"
# url = "lanecarford/lc_stylist_agent_outfit_items/string/5de155d0-56a6-43e8-a2f1-7538fce86220.jpg"
# url = "lanecarford/lc_stylist_agent_outfit_items/string/1cd1803c-5f51-4961-a4f2-2acd3e0d8294.jpg"
url = 'lanecarford/lc_stylist_agent_outfit_items/string/99cd8cc0-856a-487d-bb21-5684855ef48f.jpg'
read_type = "1"
img = oss_get_image(oss_client=minio_client, path=url, data_type=read_type)
if read_type == "cv2":
cv2.imshow("", img)
cv2.waitKey(0)
else:
img.show()
img.save("4.png")

View File

@@ -0,0 +1,6 @@
# minio 配置
MINIO_URL = "www.minio-api.aida.com.hk"
MINIO_ACCESS = 'vXKFLSJkYeEq2DrSZvkB'
MINIO_SECRET = 'uKTZT3x7C43WvPN9QTc99DiRkwddWZrG9Uh3JVlR'
MINIO_SECURE = True
MINIO_LC_DATA_PATH = "lanecarford/lc_image_data"

View File

@@ -0,0 +1,57 @@
import json
import time
import requests
def post_request(url, data=None, json_data=None, headers=None, auth=None, timeout=5):
"""
发送POST请求的封装函数
:param url: 接口的URL地址
:param data: 要发送的数据(字典形式,用于表单数据等,会自动编码)
:param json_data: 要发送的JSON数据字典形式会自动转换为JSON字符串
:param headers: 请求头字典
:param auth: 认证信息(如 ('username', 'password') 形式用于基本认证)
:param timeout: 超时时间,单位为秒
:return: 返回接口的响应对象
"""
try:
response = requests.post(
url,
data=data,
json=json_data,
headers=headers,
auth=auth,
timeout=timeout
)
response.raise_for_status() # 如果请求失败,抛出异常
return response
except requests.RequestException as e:
print(f"POST请求出错: {e}")
return None
if __name__ == '__main__':
url = 'https://83aa2db8e006.ngrok-free.app/api/style/callback'
object_data = {
'outfit_id': "test",
"status": "test",
"path": "test",
"items": [
"test"
]
}
headers = {
'Accept': "*/*",
'Accept-Encoding': "gzip, deflate, br",
'User-Agent': "PostmanRuntime-ApipostRuntime/1.1.0",
'Connection': "keep-alive",
'Content-Type': "application/json"
}
start_time = time.time()
X = post_request(url=url, data=json.dumps(object_data), headers=headers)
print(time.time() - start_time)
print(X)

116
app/test/google_oss.py Normal file
View File

@@ -0,0 +1,116 @@
import asyncio
from google.cloud import storage
from google.oauth2 import service_account
from vertexai.generative_models import Part
import os
import mimetypes
from typing import List
from google.cloud import aiplatform
# 替换为您的 GCS Bucket 名称和目标文件夹
GCS_BUCKET_NAME = "aida-test-vertex-ai-bucket"
GCS_BLOB_FOLDER = "user_456/"
KEY_FILE_PATH = "/workspace/lc_stylist_agent/request.json"
# 1. 从 JSON 文件加载凭证
aiplatform.init(
project='aida-461108',
location='us-central1'
)
class MyVertexAIClient:
def __init__(self):
try:
self.credentials = service_account.Credentials.from_service_account_file(KEY_FILE_PATH)
except Exception as e:
# 这里的异常处理应根据实际情况调整
raise RuntimeError(f"Failed to load credentials from file {KEY_FILE_PATH}: {e}")
# 初始化 GCS 客户端 (可以在 setup 或 __init__ 中完成)
self.gcs_client = storage.Client(
project=self.credentials.project_id,
credentials=self.credentials
)
self.uploaded_gcs_uris: List[str] = [] # 用于记录和后续清理
# --- 辅助方法:安全地执行同步 GCS 上传 ---
def _upload_to_gcs_sync(self, bucket_name: str, blob_name: str, local_file_path: str) -> str:
"""同步方法:将文件上传到 GCS 并返回 GCS URI。"""
bucket = self.gcs_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
blob.upload_from_filename(local_file_path)
gcs_uri = f"gs://{bucket_name}/{blob_name}"
return gcs_uri
# --- 目标方法:改写 gemini_client.aio.files.upload ---
async def upload_file_to_vertex_part(self, merged_image_path: str) -> Part:
"""
[改写目标] 异步地将本地文件上传到 GCS并返回 Vertex AI Part 对象。
:param merged_image_path: 本地文件的路径。
:return: 包含 GCS URI 的 Vertex AI Part 对象。
"""
# 1. 确定 GCS 路径
file_name = os.path.basename(merged_image_path)
# 使用唯一标识符以防冲突,这里简化为文件名
blob_name = GCS_BLOB_FOLDER + file_name
# 2. 异步执行 GCS 上传 (将同步 I/O 放入线程池)
loop = asyncio.get_event_loop()
gcs_uri = await loop.run_in_executor(
None, # 使用默认线程池
self._upload_to_gcs_sync,
GCS_BUCKET_NAME,
blob_name,
merged_image_path
)
# 3. 记录 GCS URI 以供后续清理
self.uploaded_gcs_uris.append(gcs_uri)
# 4. 确定 MIME 类型
mime_type, _ = mimetypes.guess_type(merged_image_path)
if not mime_type:
mime_type = 'application/octet-stream' # 提供默认值
# 5. 创建 Vertex AI Part 对象
# 这是 Vertex AI SDK 传递文件的标准方式
vertex_part = Part.from_uri(
uri=gcs_uri,
mime_type=mime_type
)
return vertex_part
def _list_clear_object(self, bucket_name: str, prefix: str, delimiter=None):
blobs = self.gcs_client.list_blobs(
bucket_name, prefix=prefix, delimiter=delimiter
)
for blob in blobs:
blob.delete()
print(f" ✅ 已删除: {blob.name}")
# --- 原始代码的调用改写 ---
# 假设 self.vertex_client 是 MyVertexAIClient 的实例
# original: myfile = await self.gemini_client.aio.files.upload(file=merged_image_path)
# original: content_parts.append(myfile)
# 改写后:
merged_image_path = "/workspace/lc_stylist_agent/app/core/data/outfit_output/35e8626c-943f-4a3f-a0cc-1280d8bcf84d.jpg"
async def run():
vertex_ai_server = MyVertexAIClient()
# file_name = os.path.basename(merged_image_path)
# blob_name = GCS_BLOB_FOLDER + file_name
# vertex_part = vertex_ai_server._upload_to_gcs_sync(GCS_BUCKET_NAME, blob_name, merged_image_path)
# print(vertex_part)
vertex_ai_server._list_clear_object(GCS_BUCKET_NAME, "user_456")
# content_parts.append(vertex_part)
asyncio.run(run())

7
client.py Normal file
View File

@@ -0,0 +1,7 @@
# This file is auto-generated by LitServe.
# Disable auto-generation by setting `generate_client_file=False` in `LitServer.run()`.
import requests
response = requests.post("http://127.0.0.1:8000/predict", json={"input": 4.0})
print(f"Status: {response.status_code}\nResponse:\n {response.text}")

13
docker-compose.yml Normal file
View File

@@ -0,0 +1,13 @@
services:
lc_agent_server:
build:
context: .
dockerfile: Dockerfile
working_dir: /app
environment:
GOOGLE_APPLICATION_CREDENTIALS: /app/request.json
volumes:
- ./app:/app/app
- ./logs:/app/logs
ports:
- "10200:8000"

10
get_token.py Normal file
View File

@@ -0,0 +1,10 @@
from google import genai
client = genai.Client(
vertexai=True, project='aida-461108', location='us-central1'
)
response = client.models.generate_content(
model="gemini-2.0-flash", contents="三句话总结人工智能在当代的作用"
)
print(response.text)

50
logging_env.py Normal file
View File

@@ -0,0 +1,50 @@
LOGS_PATH = 'logs/'
LOGGER_CONFIG_DICT = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'simple': {'format': '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s %(message)s'}
},
'handlers': {
'console': {
'class': 'logging.StreamHandler',
'level': 'INFO',
'formatter': 'simple',
'stream': 'ext://sys.stdout',
},
'info_file_handler': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'INFO',
'formatter': 'simple',
'filename': f'{LOGS_PATH}info.log',
'maxBytes': 10485760,
'backupCount': 50,
'encoding': 'utf8',
},
'error_file_handler': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'ERROR',
'formatter': 'simple',
'filename': f'{LOGS_PATH}error.log',
'maxBytes': 10485760,
'backupCount': 20,
'encoding': 'utf8',
},
'debug_file_handler': {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'simple',
'filename': f'{LOGS_PATH}debug.log',
'maxBytes': 10485760,
'backupCount': 50,
'encoding': 'utf8',
},
},
'loggers': {
'my_module': {'level': 'INFO', 'handlers': ['console'], 'propagate': 'no'}
},
'root': {
'level': 'INFO',
'handlers': ['error_file_handler', 'info_file_handler', 'debug_file_handler', 'console'],
},
}

554
logs/debug.log Normal file
View File

@@ -0,0 +1,554 @@
2025-10-23 17:37:26,690 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:37:26,690 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:37:26,697 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:37:26,697 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:41:56,921 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:41:56,921 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:41:56,928 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:41:56,928 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:03,207 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:03,207 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:03,216 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:03,216 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:46,495 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:46,495 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:46,504 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:46,504 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:40:54,138 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:40:54,138 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:40:54,147 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:40:54,147 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:42:28,155 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:42:28,157 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:42:40,052 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:45:35,306 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:35,306 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:35,372 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:45:35,372 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:45:35,381 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:45:35,381 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:45:48,288 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:52,803 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:45:52,805 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:45:52,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /workspace/lc_stylist_agent/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.
2025-10-23 12:49:03,747 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:03,747 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:03,814 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:49:03,814 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:49:03,823 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:49:03,823 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:49:22,244 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:29,263 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:49:29,264 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:49:29,266 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /app/app/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /app/app/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /app/app/request.json was not found.
2025-10-23 12:50:15,661 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:50:15,662 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:50:15,728 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:50:15,728 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:50:15,736 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:50:15,736 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:50:32,193 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:51:03,012 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:51:03,014 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:51:11,954 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 12:51:11,961 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Outdoor garden wedding",
"style": "Elegant bohemian, flowy",
"color_preference": "['Pale Blue', 'Mint Green'] (soft pastels preferred), avoid bright reds and oranges",
"clothing_type": "Flowy, light, and airy maxi dress",
"vibe_or_details": "Comfortable for walking"
}
```
2025-10-23 12:51:11,962 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:51:11,997 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 12:55:03,968 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:55:03,976 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:55:03,992 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:55:04,000 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:55:30,861 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:55:30,863 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:55:42,692 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:59:02,989 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:59:02,990 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:59:03,003 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:59:03,003 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:59:20,848 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:59:20,849 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:59:28,106 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 12:59:28,114 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "",
"style": "No preference",
"color_preference": "No preference",
"clothing_type": "No preference",
"vibe_or_details": "No preference"
}
```
2025-10-23 12:59:28,150 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:01:05,230 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:05,230 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:05,238 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:05,238 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:31,178 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:31,178 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:31,187 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:31,187 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:02:07,048 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:02:07,049 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:02:14,759 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:02:14,766 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Romantic date dinner",
"style": "Classic elegance",
"color_preference": [
"Cream",
"Pale Blue"
],
"clothing_type": "Lightweight maxi dress",
"vibe_or_details": "Needs to be comfortable and breathable"
}
```
2025-10-23 13:02:14,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:04:34,790 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:04:34,798 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:04:34,822 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:04:34,831 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:04:49,159 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:04:49,161 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:04:52,924 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:04:52,930 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Outdoor summer wedding",
"style": "Elegant and comfortable",
"color_preference": "Light, pastel colors",
"clothing_type": "Lightweight maxi dress",
"vibe_or_details": "Needs to be breathable for hot weather, not too formal but elegant enough for a wedding, no specific pattern preference but open to subtle designs."
}
```
2025-10-23 13:04:53,112 stylist_agent_server.py [line:276] INFO {'status': '', 'message': '', 'path': '', 'outfit_id': 'd62c593f-ddcb-491d-ad83-6a1080dc4c35', 'items': []}
2025-10-23 13:04:53,115 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:04:57,361 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:04:57,425 agent_server.py [line:69] INFO
--- Final Recommendation Results ---
2025-10-23 13:04:57,425 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-23 13:08:18,434 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:08:18,434 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:08:18,442 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:08:18,442 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:08:59,356 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:08:59,357 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:09:11,912 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:09:11,919 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "",
"style": "",
"color_preference": "No preference",
"clothing_type": "",
"vibe_or_details": ""
}
```
2025-10-23 13:09:12,017 stylist_agent_server.py [line:276] INFO {'status': '', 'message': '', 'path': '', 'outfit_id': '4249f4c2-e7e1-432a-9f00-917cab8c3697', 'items': []}
2025-10-23 13:09:12,017 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:09:15,082 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:09:15,866 agent_server.py [line:69] INFO
--- Final Recommendation Results ---
2025-10-23 13:09:15,866 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 10:22:10,296 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:22:10,297 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:22:10,305 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:22:10,305 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:22:16,926 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-24 10:22:16,928 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-24 10:22:29,130 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-24 10:35:27,496 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:35:27,500 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:35:27,503 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:35:27,507 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:35:32,549 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-24 10:35:32,550 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-24 10:35:44,514 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/test2/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.

395
logs/error.log Normal file
View File

@@ -0,0 +1,395 @@
2025-10-23 12:42:40,052 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:45:52,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /workspace/lc_stylist_agent/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.
2025-10-23 12:49:29,266 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /app/app/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /app/app/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /app/app/request.json was not found.
2025-10-23 12:51:11,997 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 12:55:42,692 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:59:28,150 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:02:14,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:04:57,425 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-23 13:09:15,866 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 10:22:29,130 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-24 10:35:44,514 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/test2/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.

554
logs/info.log Normal file
View File

@@ -0,0 +1,554 @@
2025-10-23 17:37:26,690 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:37:26,690 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:37:26,697 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:37:26,697 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:41:56,921 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:41:56,921 redis_manager.py [line:22] INFO Successfully connected to Redis at localhost:6379
2025-10-23 17:41:56,928 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 17:41:56,928 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:03,207 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:03,207 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:03,216 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:03,216 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:46,495 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:46,495 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:38:46,504 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:38:46,504 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:40:54,138 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:40:54,138 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:40:54,147 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:40:54,147 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:42:28,155 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:42:28,157 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:42:40,052 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:45:35,306 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:35,306 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:35,372 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:45:35,372 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:45:35,381 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:45:35,381 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:45:48,288 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:45:52,803 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:45:52,805 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:45:52,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /workspace/lc_stylist_agent/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /workspace/lc_stylist_agent/request.json was not found.
2025-10-23 12:49:03,747 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:03,747 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:03,814 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:49:03,814 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:49:03,823 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:49:03,823 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:49:22,244 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:49:29,263 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:49:29,264 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:49:29,266 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: File /app/app/request.json was not found.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 705, in default
credentials, project_id = checker()
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 698, in <lambda>
lambda: _get_explicit_environ_credentials(quota_project_id=quota_project_id),
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 346, in _get_explicit_environ_credentials
credentials, project_id = load_credentials_from_file(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 173, in load_credentials_from_file
raise exceptions.DefaultCredentialsError(
google.auth.exceptions.DefaultCredentialsError: File /app/app/request.json was not found.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: File /app/app/request.json was not found.
2025-10-23 12:50:15,661 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:50:15,662 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:50:15,728 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:50:15,728 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:50:15,736 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:50:15,736 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:50:32,193 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:51:03,012 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:51:03,014 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:51:11,954 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 12:51:11,961 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Outdoor garden wedding",
"style": "Elegant bohemian, flowy",
"color_preference": "['Pale Blue', 'Mint Green'] (soft pastels preferred), avoid bright reds and oranges",
"clothing_type": "Flowy, light, and airy maxi dress",
"vibe_or_details": "Comfortable for walking"
}
```
2025-10-23 12:51:11,962 _api_client.py [line:619] INFO The user provided project/location will take precedence over the Vertex AI API key from the environment variable.
2025-10-23 12:51:11,997 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 12:55:03,968 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:55:03,976 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:55:03,992 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:55:04,000 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:55:30,861 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:55:30,863 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:55:42,692 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/app/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/usr/local/lib/python3.10/dist-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 111, in __call__
do = await self.iter(retry_state=retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 153, in iter
result = await action(retry_state)
File "/usr/local/lib/python3.10/dist-packages/tenacity/_utils.py", line 99, in inner
return call(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 420, in exc_check
raise retry_exc.reraise()
File "/usr/local/lib/python3.10/dist-packages/tenacity/__init__.py", line 187, in reraise
raise self.last_attempt.result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/usr/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/usr/local/lib/python3.10/dist-packages/tenacity/asyncio/__init__.py", line 114, in __call__
result = await fn(*args, **kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/usr/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/dist-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/usr/local/lib/python3.10/dist-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/app/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/app/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-23 12:59:02,989 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:59:02,990 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 12:59:03,003 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:59:03,003 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 12:59:20,848 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 12:59:20,849 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 12:59:28,106 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 12:59:28,114 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "",
"style": "No preference",
"color_preference": "No preference",
"clothing_type": "No preference",
"vibe_or_details": "No preference"
}
```
2025-10-23 12:59:28,150 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:01:05,230 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:05,230 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:05,238 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:05,238 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:31,178 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:31,178 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:01:31,187 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:01:31,187 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:02:07,048 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:02:07,049 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:02:14,759 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:02:14,766 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Romantic date dinner",
"style": "Classic elegance",
"color_preference": [
"Cream",
"Pale Blue"
],
"clothing_type": "Lightweight maxi dress",
"vibe_or_details": "Needs to be comfortable and breathable"
}
```
2025-10-23 13:02:14,806 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /app/app/server/ChatbotAgent/agent_server.py:57> exception=RuntimeError("Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'")>
Traceback (most recent call last):
File "/app/app/core/stylist_agent_server.py", line 38, in __init__
self.credentials = service_account.Credentials.from_service_account_file('/workspace/lc_stylist_agent/request.json')
File "/usr/local/lib/python3.10/dist-packages/google/oauth2/service_account.py", line 264, in from_service_account_file
info, signer = _service_account_info.from_filename(
File "/usr/local/lib/python3.10/dist-packages/google/auth/_service_account_info.py", line 78, in from_filename
with io.open(filename, "r", encoding="utf-8") as json_file:
FileNotFoundError: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/app/app/server/ChatbotAgent/agent_server.py", line 63, in background_run
recommendation_results = await self.recommend_outfit(request_summary=request_summary,
File "/app/app/server/ChatbotAgent/agent_server.py", line 99, in recommend_outfit
agent = AsyncStylistAgent(**self.stylist_agent_kwages)
File "/app/app/core/stylist_agent_server.py", line 41, in __init__
raise RuntimeError(f"Failed to load credentials from file {'/workspace/lc_stylist_agent/request.json'}: {e}")
RuntimeError: Failed to load credentials from file /workspace/lc_stylist_agent/request.json: [Errno 2] No such file or directory: '/workspace/lc_stylist_agent/request.json'
2025-10-23 13:04:34,790 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:04:34,798 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:04:34,822 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:04:34,831 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:04:49,159 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:04:49,161 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:04:52,924 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:04:52,930 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "Outdoor summer wedding",
"style": "Elegant and comfortable",
"color_preference": "Light, pastel colors",
"clothing_type": "Lightweight maxi dress",
"vibe_or_details": "Needs to be breathable for hot weather, not too formal but elegant enough for a wedding, no specific pattern preference but open to subtle designs."
}
```
2025-10-23 13:04:53,112 stylist_agent_server.py [line:276] INFO {'status': '', 'message': '', 'path': '', 'outfit_id': 'd62c593f-ddcb-491d-ad83-6a1080dc4c35', 'items': []}
2025-10-23 13:04:53,115 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:04:57,361 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:04:57,425 agent_server.py [line:69] INFO
--- Final Recommendation Results ---
2025-10-23 13:04:57,425 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-23 13:08:18,434 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:08:18,434 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-23 13:08:18,442 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:08:18,442 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-23 13:08:59,356 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-23 13:08:59,357 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:09:11,912 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:09:11,919 agent_server.py [line:60] INFO request_summary: ```json
{
"occasion": "",
"style": "",
"color_preference": "No preference",
"clothing_type": "",
"vibe_or_details": ""
}
```
2025-10-23 13:09:12,017 stylist_agent_server.py [line:276] INFO {'status': '', 'message': '', 'path': '', 'outfit_id': '4249f4c2-e7e1-432a-9f00-917cab8c3697', 'items': []}
2025-10-23 13:09:12,017 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-23 13:09:15,082 _client.py [line:1740] INFO HTTP Request: POST https://us-central1-aiplatform.googleapis.com/v1beta1/projects/aida-461108/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2025-10-23 13:09:15,866 agent_server.py [line:69] INFO
--- Final Recommendation Results ---
2025-10-23 13:09:15,866 agent_server.py [line:73] ERROR ❌ Failed: 'NoneType' object has no attribute 'get'
2025-10-24 10:22:10,296 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:22:10,297 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:22:10,305 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:22:10,305 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:22:16,926 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-24 10:22:16,928 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-24 10:22:29,130 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/lc_stylist_agent/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
2025-10-24 10:35:27,496 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:35:27,500 redis_manager.py [line:22] INFO Successfully connected to Redis at 10.1.1.240:6379
2025-10-24 10:35:27,503 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:35:27,507 posthog.py [line:22] INFO Anonymized telemetry enabled. See https://docs.trychroma.com/telemetry for more information.
2025-10-24 10:35:32,549 agent_server.py [line:47] INFO request: {'user_id': 'string', 'num_outfits': 1, 'stylist_path': 'lanecarford/stylist_guide/crystal_en.md'}
2025-10-24 10:35:32,550 models.py [line:6751] INFO AFC is enabled with max remote calls: 10.
2025-10-24 10:35:44,514 base_events.py [line:1758] ERROR Task exception was never retrieved
future: <Task finished name='Task-3' coro=<LCAgent.background_run() done, defined at /workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py:57> exception=DefaultCredentialsError('Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.')>
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 45, in generate_response
response = await self.gemini_client.aio.models.generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 6757, in generate_content
response = await self._generate_content(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/models.py", line 5592, in _generate_content
response = await self._api_client.async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1341, in async_request
result = await self._async_request(
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1286, in _async_request
return await self._async_retry( # type: ignore[no-any-return]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 58, in __call__
do = await self.iter(retry_state=retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 110, in iter
result = await action(retry_state)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 78, in inner
return fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 410, in exc_check
raise retry_exc.reraise()
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/__init__.py", line 183, in reraise
raise self.last_attempt.result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 451, in result
return self.__get_result()
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
raise self._exception
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/tenacity/_asyncio.py", line 61, in __call__
result = await fn(*args, **kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 1153, in _async_request_once
f'Bearer {await self._async_access_token()}'
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 970, in _async_access_token
self._credentials, project = await asyncio.to_thread(
File "/home/user/miniconda3/envs/test2/lib/python3.10/asyncio/threads.py", line 25, in to_thread
return await loop.run_in_executor(None, func_call)
File "/home/user/miniconda3/envs/test2/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/genai/_api_client.py", line 184, in load_auth
credentials, loaded_project_id = google.auth.default( # type: ignore[no-untyped-call]
File "/home/user/miniconda3/envs/test2/lib/python3.10/site-packages/google/auth/_default.py", line 739, in default
raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 59, in background_run
request_summary = await self.get_conversation_summary(request.user_id)
File "/workspace/lc_stylist_agent/app/server/ChatbotAgent/agent_server.py", line 84, in get_conversation_summary
summary = await self.llm.generate_response(history=[Message(role=Role.USER, content=input_message)], system_prompt=SUMMARY_PROMPT)
File "/workspace/lc_stylist_agent/app/core/llm_interface.py", line 55, in generate_response
raise type(e)(f"Gemini API call failed: {e}")
google.auth.exceptions.DefaultCredentialsError: Gemini API call failed: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.

13
new_.json Normal file
View File

@@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "aida-461108",
"private_key_id": "e0fa4eb8743342ee0d9af77296ec71101bf09706",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDi/0QP9zvdmw/M\nff8koRw1lAEyC/zneayGmB5zHZYE9g+iZZ6U53Df6jgF5maMXoEhb7b62hSbY/Pv\niYcrUYsx1Za0BOp2H7S+WoZg87pYmBkBKY2aoazhnQyaOCB+YBp9E+ZL+yDVJ3JH\nvC1YTWl6CV13V+iPVo4z8kkWFDZWizPZm295JHbQyCHDWjS7hXzDhkXzRswqzsCF\n8f9C+uYCOxjhOZp8YQ7SirsbKFAHf1PCQMyF0zQvCmZ6NaTNZKMEga0kaxHsfwbA\n4YYH3QRXjjPvKI7dRLmjYuoVkVbyQTqOru/wSh0kTqUbhHHYqWAgqkODY4oagTAg\nE73fYqZPAgMBAAECggEAB+ayY/Xgl72X0VqKC33aIVlLU1vMdp2AbleUKRXyDK59\n69KqsEHVZs3ccQQh31KYybpS6FdimT1jlnEMi0BK3otciVvpx1PM3ZqsC8A1ZR5i\nMcKpraS2rkxiTb8/Y6FiZVEl1nuMGy9E0I9nFVLt0B7MVI+dm4OmmSieok3wzZaj\nr3oRRqX+YAtDEweZSB46HVUgeujkhNtizCCwu8agl7QX4cUjLBp/KzkgvCTRl118\n/BedCyrg+y+LtAT2raXuMrIiE/WdqFesQtt7rLIWCEqcpn0DSKrQ++LQvE9epz7y\nKdNVLeFiUmxSBHvTQRuR0jRMOZJreQnKSb6vJzodtQKBgQD8f3hCE9OIPs5xIxpz\nIRWHfghaPuvLMBZprxUqDe+QjN9EOVu5wFmpiMJybKA9kOybuW5GkbXg4U/kINEP\n5TogDjufWgggVUnfmovBpr3ld+EgRzmVDbY7Od0hBOoobYf34crVPSpMonKmMvjU\nZnhN9peQlO8/vw8Bkq/ebIGKxQKBgQDmJUB6BSEVsctA7lsQ/uBODVWdvh1Oxzhj\nKeP5fxvKDwcS5hxuG9k9x5a5LH8DAwfEEhtvNy05yMdCTL/CdP57L4uQbUG/+VQY\nodP6MGf3H38Iy+bFjPWlvhFlbyIbk8AdwsZm6a0n23jtjfFWYPwz/NVu2GLaea3s\nPj0JTJ5OAwKBgQCUkOgQcRv4wYO0nAP3E9NYGrcNapJQxqWZX3Qjf3mi4tCHkvw+\nikf3ccl/jByovPoLEospKJkMjWX1g72fDbAqplU8iLvZUnWaBJQQyGxZdTTYSjA+\nXIgJxx0uTXb9fJ0RJCC1YTzfRIIS+lDgoL5OmTZK0ucG6gMJWOb0B4IdRQKBgA6S\n0VBovr2W8p37+fxLh3ypz4Abp9NzPhjZcDw+Vk4nQXVq6OX4EXueBedX7/sK2BUM\naHxUbCK6mhOStJnluq+mRRoyMPWtHiwpIzk2k37Mmci+0LA1yuBh9swLi4dfhczc\npp+hsHtTpIa2dE/Z+F56ZjGMtkXLar4I+uh515RtAoGAQSLWfzsXoAdUsf16hE8s\nVTWmK7TiJH2UBH6Qa7OqEl4367BQjRm1EGRO3oUwyK/TmM2LSdA9G7fVpFydhkWR\nFJwuvWAsf3QT6FDup9jofgmQxvGS0fpJNENel5k1l5687gmkK6ulVSTfiRQFMYM0\nxJjMu9TnfDjmd2gG5GkWVqM=\n-----END PRIVATE KEY-----\n",
"client_email": "aida-gcs-test@aida-461108.iam.gserviceaccount.com",
"client_id": "117280364971550320059",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/aida-gcs-test%40aida-461108.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

13
request.json Normal file
View File

@@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "aida-461108",
"private_key_id": "b4afaabebb84da24502b318a5fa175f1dc5c096a",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCmk7LKrp8g9yD1\nWmF+mY2qHCEZ/5aIx6QRh0QoVPBL7Yi7ce009QxaE8fu8+QMgg8l3xMreXvgpt56\noFnVwpFusLjSdjgoFluElM2hYxXlO9q8cbBoU2nehOBLLJzGzkodT7xu/BOjNvKC\n//aTbjtJyk8Kj+ENa0/dPaUZs/PCtQqpAu8ag5nXrordVWfO0K25EjeYyoba35zk\nPp2fBi8KALZZI5Xfd2z9++K0K2mWWIMJic30idHvquj0WxlTRK2Pq8BmJXCQpJIi\nQ5E4egue16BfKjrF0Kxkpqd1RmdlEmaSKbbkZXe2z4jg0qknESRFOmRy8C3LnaB2\nHHJWLYM3AgMBAAECggEACUdroOQJSTTQSS/iWRhZ+S0yoC10nTnsZxg527qfiBs7\nOqB7WNqC+Ew8dDsca6CdvLuoaGDkCFJDTQwRn66u8JOM4sG4bxiPuzBEJBv45EQT\n8zCsuvhVNWgBdoPjAnq19jFdixvPnDqQrRYaY4FdxsaA5f24c57pW/xLGMYawLBt\n9RJZSuWmJdzKG1i5W8a8+4f/seNtuo2MtXU3mPJZPqRWPXTAZeaQPM/57ZQ+kzig\nOkAbQZNRmt1yPCjPCQD8vc8yCBMmjus/rlHXD/L7okYUlVZkob5I3FBrLl+ZyIXS\nqxEsBLBwRW3w8WbX+ZSVciQ72JK68W7LnOHSAENmAQKBgQDgBTCqp87KGLWVPb8w\nK+s1Sfh+nM3M4AlbLdcGBs1JCoddF6pAeY4wpf/ow1Tm4rqEuCYzMClPwxvkue+D\nY7lCQgy2FK3ahUzn8oVmvEPD/YPAojDSY3bH0lquHuS6oVKk834JUykButaAU3XY\nvUGNQuKdLKAeQRT8Q6um4m+EYQKBgQC+Wz6nYESKH6GiNnuFTH8hIkThPlbi4wua\nU1kGnPKe3ouE4zRLfPwQ6RRf1slQ/2hFLOatiTLYUgZWZQeBPSWp2EjYcOSzob+7\n11+KqeIRCD5DKxgf0cjJdihK9AM639OKlH2NvZ2507TksdeTPDzdaOMLwLWKexP5\nlYrdob0ulwKBgD81t7Gvf83Ogw4FSjkRa2Cx6ofvPrKcVIeBu7ZbnPkLG37M+qEO\nq2xWqorG8uHi/7YLL9wprr5u0yQKwuZT8SYc9PE7jIKoMjcQW0vNu2FF2zMzkIsM\nvatMU4Hl/awbcPJSMjH3YQ635WZ4Jjxtyl1NjhvDR7rBqmYzwe9o3QaBAoGANhPB\n1tbYYczepDCKIrI6o3US0FJfaJFLqInpDqHjoxJh3FyXbKKTEVLFwPxJsML+IjjB\nR6dkVGPo/P4yhZqTao7REvvvXMCksX5b3A6q9F+9IGPLtK5qNiFlDPYJPN59QC8z\nA+NMPZBRIW8MaP2B5Px5E8upRy/z2sGK86+RCP0CgYATGs75F97q+Zf8q+Pe3Nsb\ngqmhLoI3PZUSWgBcQgNF4nyCZceUrEl72wKO/NWLgxqQPtlra187ce69g7qARHLb\ntHq80nb0f7lil74B6+OlyNNO1htWA90fmGR2s16Mt0BwJRT+/EFuNqbJIUSLxKiW\nqlXBUbmHHzamo5DPYL8S/w==\n-----END PRIVATE KEY-----\n",
"client_email": "aida-239@aida-461108.iam.gserviceaccount.com",
"client_id": "103102077955178349079",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/aida-239%40aida-461108.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

View File

@@ -1,231 +1,19 @@
accelerate==0.21.0
aiohttp==3.9.5
aiosignal==1.3.1
albumentations==0.3.2
annotated-types==0.7.0
antlr4-python3-runtime==4.9.3
anykeystore==0.2
asn1crypto==1.5.1
asttokens==2.4.1
async-timeout==4.0.3
attrs==21.2.0
bidict==0.23.1
blessed==1.20.0
boto3==1.34.113
botocore==1.34.113
braceexpand==0.1.7
cachetools==5.3.3
certifi==2024.2.2
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.2
click==8.1.7
clip==0.2.0
clip-openai==1.0.post20230121
cmake==3.29.3
cramjam==2.8.3
crcmod==1.7
cryptacular==1.6.2
cryptography==39.0.2
cycler==0.12.1
datasets==2.2.1
diffusers==0.30.1
decorator==5.1.1
decord==0.6.0
deepspeed==0.14.2
defusedxml==0.7.1
Deprecated==1.2.14
descartes==1.1.0
dill==0.3.8
distlib==0.3.8
distro-info==1.0
dnspython==2.6.1
docker-pycreds==0.4.0
docstring_parser==0.16
ecdsa==0.19.0
einops==0.6.0
exceptiongroup==1.2.1
executing==2.0.1
fairscale==0.4.13
fastparquet==2024.5.0
ffmpegcv==0.3.13
filelock==3.14.0
fire==0.6.0
fonttools==4.51.0
frozenlist==1.4.1
fsspec==2023.6.0
ftfy==6.2.0
gitdb==4.0.11
GitPython==3.1.43
gpustat==1.1.1
greenlet==3.0.3
grpcio==1.64.0
h11==0.14.0
hjson==3.1.0
hupper==1.12.1
idna==3.7
imageio==2.34.1
imgaug==0.2.6
iniconfig==2.0.0
ipaddress==1.0.23
ipdb==0.13.13
ipython==8.18.1
jaxtyping==0.2.28
jedi==0.19.1
Jinja2==3.1.4
jmespath==1.0.1
joblib==1.4.2
jsonargparse==4.14.1
jsonlines==4.0.0
kiwisolver==1.4.5
kornia==0.7.2
kornia_rs==0.1.3
lazy_loader==0.4
lightning==2.2.3
lightning-utilities==0.11.2
lit==18.1.6
MarkupSafe==2.1.5
matplotlib==3.5.3
matplotlib-inline==0.1.7
miscreant==0.3.0
mpmath==1.3.0
msgpack==1.0.8
multidict==6.0.5
multiprocess==0.70.16
natsort==8.4.0
networkx==3.2.1
ninja==1.11.1.1
numpy==1.24.4
nuscenes-devkit==1.1.11
oauthlib==3.2.2
omegaconf==2.3.0
open-clip-torch==2.24.0
openai-clip
opencv-python==4.9.0.80
opencv-python-headless==3.4.18.65
packaging==22.0
pandas==1.5.3
parquet==1.3.1
parso==0.8.4
PasteDeploy==3.1.0
pathlib2==2.3.7.post1
pathtools==0.1.2
pbkdf2==1.3
pexpect==4.9.0
pillow==10.3.0
plaster==1.1.2
plaster-pastedeploy==1.0.1
platformdirs==4.2.2
plotly==5.22.0
pluggy==1.5.0
ply==3.11
promise==2.3
prompt-toolkit==3.0.43
protobuf==3.20.3
psutil==5.9.8
ptyprocess==0.7.0
pure-eval==0.2.2
py==1.11.0
py-cpuinfo==9.0.0
py-spy==0.3.14
pyarrow==11.0.0
pyarrow-hotfix==0.6
pyasn1==0.6.0
pycocotools==2.0.7
pycparser==2.22
pycryptodomex==3.20.0
pycurl==7.43.0.6
ollama==0.4.4
pydantic==2.9.2
pydantic_core==2.23.4
Pygments==2.18.0
PyJWT==2.8.0
pynvml==11.5.0
pyope==0.2.2
pyOpenSSL==23.2.0
pyparsing==3.1.2
pyquaternion==0.9.9
pyramid==2.0.2
pyramid-mailer==0.15.1
pytest==6.2.5
python-consul==1.1.0
python-dateutil==2.9.0.post0
python-engineio==4.9.1
python-etcd==0.4.5
python-jose==3.3.0
python-socketio==5.11.2
python3-openid==3.2.0
pytorch-extension==0.2
pytorch-lightning==2.2.3
pytz==2024.1
PyYAML==6.0.1
regex==2024.5.15
repoze.sendmail==4.4.1
requests==2.31.0
requests-oauthlib==2.0.0
rsa==4.9
s3transfer==0.10.1
safetensors==0.4.3
schedule==1.2.2
scikit-image==0.22.0
scikit-learn==1.5.0
scipy==1.13.1
sentencepiece==0.2.0
sentry-sdk==2.3.1
setproctitle==1.3.3
Shapely==1.8.5.post1
shortuuid==1.0.13
simple-websocket==1.0.0
six==1.16.0
smmap==5.0.1
SQLAlchemy==2.0.30
stack-data==0.6.3
sympy==1.12
taming-transformers-rom1504==0.0.6
tenacity==8.3.0
tensorboardX==2.6.2.2
termcolor==2.4.0
threadpoolctl==3.5.0
thriftpy2==0.5.0
tifffile==2024.5.22
timm==1.0.3
tokenizers==0.19.1
toml==0.10.2
tomli==2.0.1
numpy==1.24.4
setuptools==80.9.0
pydantic_settings== 2.11.0
google-genai==1.45.0
redis==6.4.0
google-cloud-storage==2.19.0
minio==7.2.18
chromadb==1.1.1
transformers==4.41.1
torch==2.2.1
torch-fidelity==0.3.0
torchmetrics==1.4.0.post0
torchvision==0.17.1
tox==3.28.0
tqdm==4.66.4
traitlets==5.14.3
transaction==4.0
transformers==4.41.1
translationstring==1.4
triton==2.2.0
typeguard==2.13.3
typing_extensions==4.12.0
tzdata==2024.1
urllib3==1.26.18
velruse==1.1.1
venusian==3.1.0
virtualenv==20.26.2
wandb==0.17.2
watchdog==4.0.1
wcwidth==0.2.13
webdataset==0.2.86
WebOb==1.8.7
websocket-client==1.8.0
wrapt==1.16.0
wsproto==1.2.0
WTForms==3.1.2
wtforms-recaptcha==0.3.2
xformers==0.0.25
xxhash==3.4.1
yarl==1.9.4
zope.deprecation==5.0
zope.interface==6.4.post2
zope.sqlalchemy==3.1
pytorch-fid==0.3.0
lpips==0.1.4
huggingface_hub==0.24.6
open-clip-torch==2.24.0
pytorch-fid==0.3.0
# pip install git+https://github.com/openai/CLIP.git

236
requirements_all.txt Normal file
View File

@@ -0,0 +1,236 @@
accelerate==0.21.0
aiohttp==3.9.5
aiosignal==1.3.1
albumentations==0.3.2
annotated-types==0.7.0
antlr4-python3-runtime==4.9.3
anykeystore==0.2
asn1crypto==1.5.1
asttokens==2.4.1
async-timeout==4.0.3
attrs==23.1.0
bidict==0.23.1
blessed==1.20.0
boto3==1.34.113
botocore==1.34.113
braceexpand==0.1.7
cachetools==5.3.3
certifi==2024.2.2
cffi==1.16.0
chardet==5.2.0
charset-normalizer==3.3.2
click==8.1.7
cmake==3.29.3
cramjam==2.8.3
crcmod==1.7
cryptacular==1.6.2
cryptography==39.0.2
cycler==0.12.1
datasets==2.2.1
diffusers==0.30.1
decorator==5.1.1
decord==0.6.0
deepspeed==0.14.2
defusedxml==0.7.1
Deprecated==1.2.14
descartes==1.1.0
dill==0.3.8
distlib==0.3.8
distro-info==1.0
dnspython==2.6.1
docker-pycreds==0.4.0
docstring_parser==0.16
ecdsa==0.19.0
einops==0.6.0
exceptiongroup==1.2.1
executing==2.0.1
fairscale==0.4.13
fastparquet==2024.5.0
ffmpegcv==0.3.13
filelock==3.14.0
fire==0.6.0
fonttools==4.51.0
frozenlist==1.4.1
fsspec==2023.6.0
ftfy==6.2.0
gitdb==4.0.11
GitPython==3.1.43
gpustat==1.1.1
greenlet==3.0.3
grpcio==1.64.0
h11==0.14.0
hjson==3.1.0
hupper==1.12.1
idna==3.7
imageio==2.34.1
imgaug==0.2.6
iniconfig==2.0.0
ipaddress==1.0.23
ipdb==0.13.13
ipython==8.18.1
jaxtyping==0.2.28
jedi==0.19.1
Jinja2==3.1.4
jmespath==1.0.1
joblib==1.4.2
jsonargparse==4.14.1
jsonlines==4.0.0
kiwisolver==1.4.5
kornia==0.7.2
kornia_rs==0.1.3
lazy_loader==0.4
lightning==2.2.3
lightning-utilities==0.11.2
lit==18.1.6
MarkupSafe==2.1.5
matplotlib==3.5.3
matplotlib-inline==0.1.7
miscreant==0.3.0
mpmath==1.3.0
msgpack==1.0.8
multidict==6.0.5
multiprocess==0.70.16
natsort==8.4.0
networkx==3.2.1
ninja==1.11.1.1
numpy==1.24.4
nuscenes-devkit==1.1.11
oauthlib==3.2.2
omegaconf==2.3.0
opencv-python==4.9.0.80
opencv-python-headless==3.4.18.65
packaging==22.0
pandas==1.5.3
parquet==1.3.1
parso==0.8.4
PasteDeploy==3.1.0
pathlib2==2.3.7.post1
pathtools==0.1.2
pbkdf2==1.3
pexpect==4.9.0
pillow==10.3.0
plaster==1.1.2
plaster-pastedeploy==1.0.1
platformdirs==4.2.2
plotly==5.22.0
pluggy==1.5.0
ply==3.11
promise==2.3
prompt-toolkit==3.0.43
protobuf==3.20.3
psutil==5.9.8
ptyprocess==0.7.0
pure-eval==0.2.2
py==1.11.0
py-cpuinfo==9.0.0
py-spy==0.3.14
pyarrow==11.0.0
pyarrow-hotfix==0.6
pyasn1==0.6.0
pycocotools==2.0.7
pycparser==2.22
pycryptodomex==3.20.0
pycurl==7.43.0.6
pydantic==2.9.2
pydantic_core==2.23.4
Pygments==2.18.0
PyJWT==2.8.0
pynvml==11.5.0
pyope==0.2.2
pyOpenSSL==23.2.0
pyparsing==3.1.2
pyquaternion==0.9.9
pyramid==2.0.2
pyramid-mailer==0.15.1
pytest==6.2.5
python-consul==1.1.0
python-dateutil==2.9.0.post0
python-engineio==4.9.1
python-etcd==0.4.5
python-jose==3.3.0
python-socketio==5.11.2
python3-openid==3.2.0
pytorch-extension==0.2
pytorch-lightning==2.2.3
pytz==2024.1
PyYAML==6.0.1
regex==2024.5.15
repoze.sendmail==4.4.1
requests==2.31.0
requests-oauthlib==2.0.0
rsa==4.9
s3transfer==0.10.1
safetensors==0.4.3
schedule==1.2.2
scikit-image==0.22.0
scikit-learn==1.5.0
scipy==1.13.1
sentencepiece==0.2.0
sentry-sdk==2.3.1
setproctitle==1.3.3
Shapely==1.8.5.post1
shortuuid==1.0.13
simple-websocket==1.0.0
six==1.16.0
smmap==5.0.1
SQLAlchemy==2.0.30
stack-data==0.6.3
sympy==1.12
taming-transformers-rom1504==0.0.6
tenacity==8.3.0
tensorboardX==2.6.2.2
termcolor==2.4.0
threadpoolctl==3.5.0
thriftpy2==0.5.0
tifffile==2024.5.22
timm==1.0.3
tokenizers==0.19.1
toml==0.10.2
tomli==2.0.1
torch==2.2.1
torch-fidelity==0.3.0
torchmetrics==1.4.0.post0
torchvision==0.17.1
tox==3.28.0
tqdm==4.66.4
traitlets==5.14.3
transaction==4.0
transformers==4.41.1
translationstring==1.4
triton==2.2.0
typeguard==2.13.3
typing_extensions==4.12.0
tzdata==2024.1
urllib3==1.26.18
velruse==1.1.1
venusian==3.1.0
virtualenv==20.26.2
wandb==0.17.2
watchdog==4.0.1
wcwidth==0.2.13
webdataset==0.2.86
WebOb==1.8.7
websocket-client==1.8.0
wrapt==1.16.0
wsproto==1.2.0
WTForms==3.1.2
wtforms-recaptcha==0.3.2
xformers==0.0.25
xxhash==3.4.1
yarl==1.9.4
zope.deprecation==5.0
zope.interface==6.4.post2
zope.sqlalchemy==3.1
pytorch-fid==0.3.0
lpips==0.1.4
huggingface_hub==0.24.6
setuptools==80.9.0
pydantic_settings== 2.11.0
google-genai==1.45.0
redis==6.4.0
google-cloud-storage==2.19.0
minio==7.2.18
chromadb==1.1.1
transformers==4.41.1