push gitignore
This commit is contained in:
2
.env_local
Normal file
2
.env_local
Normal file
@@ -0,0 +1,2 @@
|
||||
GEMINI_API_KEY=AIzaSyAO4zXFke1bqyrXd9-RGfKJTLerwLSFKww
|
||||
GOOGLE_APPLICATION_CREDENTIALS="/workspace/lc_stylist_agent/request.json"
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
.env
|
||||
.vscode/
|
||||
app/core/__pycache__/
|
||||
app/core/data/
|
||||
app/core/data/
|
||||
.idea/
|
||||
*.sqlite3
|
||||
47
Dockerfile
Normal file
47
Dockerfile
Normal 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
7
app/client.py
Normal 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}")
|
||||
@@ -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())
|
||||
|
||||
163
app/core/chatbot_agent_stream.py
Normal file
163
app/core/chatbot_agent_stream.py
Normal 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())
|
||||
@@ -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()
|
||||
|
||||
@@ -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}")
|
||||
|
||||
|
||||
61
app/core/llm_interface_stream.py
Normal file
61
app/core/llm_interface_stream.py
Normal 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
|
||||
@@ -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}")
|
||||
|
||||
@@ -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)
|
||||
|
||||
436
app/core/stylist_agent_server.py
Normal file
436
app/core/stylist_agent_server.py
Normal 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)}
|
||||
@@ -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
163
app/core/utils_litserve.py
Normal 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
|
||||
@@ -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
1230
app/logs/debug.log
Normal file
File diff suppressed because it is too large
Load Diff
124
app/logs/error.log
Normal file
124
app/logs/error.log
Normal 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
1230
app/logs/info.log
Normal file
File diff suppressed because it is too large
Load Diff
26
app/main.py
Normal file
26
app/main.py
Normal 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)
|
||||
129
app/server/ChatbotAgent/agent_server.py
Normal file
129
app/server/ChatbotAgent/agent_server.py
Normal 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)}
|
||||
188
app/server/ChatbotAgent/chatbot_server.py
Normal file
188
app/server/ChatbotAgent/chatbot_server.py
Normal 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)}
|
||||
125
app/server/utils/minio_client.py
Normal file
125
app/server/utils/minio_client.py
Normal 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")
|
||||
6
app/server/utils/minio_config.py
Normal file
6
app/server/utils/minio_config.py
Normal 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"
|
||||
57
app/server/utils/request_post.py
Normal file
57
app/server/utils/request_post.py
Normal 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
116
app/test/google_oss.py
Normal 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
7
client.py
Normal 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
13
docker-compose.yml
Normal 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
10
get_token.py
Normal 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
50
logging_env.py
Normal 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
554
logs/debug.log
Normal 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
395
logs/error.log
Normal 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
554
logs/info.log
Normal 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
13
new_.json
Normal 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
13
request.json
Normal 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"
|
||||
}
|
||||
238
requirements.txt
238
requirements.txt
@@ -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
236
requirements_all.txt
Normal 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
|
||||
Reference in New Issue
Block a user