diff --git a/README.md b/README.md index b2ef532..19a0174 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# OmniShopAgent +# ShopAgent An autonomous multi-modal fashion shopping agent powered by **LangGraph** and **ReAct pattern**. @@ -8,7 +8,7 @@ An autonomous multi-modal fashion shopping agent powered by **LangGraph** and ** ## Overview -OmniShopAgent autonomously decides which tools to call, maintains conversation state, and determines when to respond. Built with **LangGraph**, it uses agentic patterns for intelligent product discovery. +ShopAgent autonomously decides which tools to call, maintains conversation state, and determines when to respond. Built with **LangGraph**, it uses agentic patterns for intelligent product discovery. **Key Features:** - Autonomous tool selection and execution @@ -98,7 +98,7 @@ Agent: analyze_image_style(path) → Extracts shirt details ```bash # Clone and install dependencies git clone -cd OmniShopAgent +cd ShopAgent python -m venv venv source venv/bin/activate # Windows: venv\Scripts\activate pip install -r requirements.txt diff --git a/app.py b/app.py index e9eb877..342861a 100644 --- a/app.py +++ b/app.py @@ -1,5 +1,5 @@ """ -OmniShopAgent - Streamlit UI +ShopAgent - Streamlit UI Multi-modal fashion shopping assistant with conversational AI """ @@ -23,7 +23,7 @@ logger = logging.getLogger(__name__) # Page config st.set_page_config( - page_title="OmniShopAgent", + page_title="ShopAgent", page_icon="👗", layout="centered", initial_sidebar_state="collapsed", @@ -541,7 +541,7 @@ def main(): st.markdown( """
-
👗 OmniShopAgent
+
👗 ShopAgent
AI Fashion Shopping Assistant
""", diff --git a/app/__init__.py b/app/__init__.py index 88cb718..14bd4b2 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,5 +1,5 @@ """ -OmniShopAgent - Multi-modal E-commerce Search Agent +ShopAgent - Multi-modal E-commerce Search Agent """ __version__ = "0.1.0" diff --git a/app/agents/shopping_agent.py b/app/agents/shopping_agent.py index ebdfae9..481fd74 100644 --- a/app/agents/shopping_agent.py +++ b/app/agents/shopping_agent.py @@ -44,7 +44,7 @@ class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages] current_image_path: Optional[str] # Track uploaded image - +print("settings") class ShoppingAgent: """True ReAct agent with autonomous decision making""" @@ -59,6 +59,10 @@ class ShoppingAgent: ) if settings.openai_api_base_url: llm_kwargs["base_url"] = settings.openai_api_base_url + + print("llm_kwargs") + print(llm_kwargs) + self.llm = ChatOpenAI(**llm_kwargs) # Get tools and bind to model diff --git a/app/config.py b/app/config.py index 40a5a67..902f9eb 100644 --- a/app/config.py +++ b/app/config.py @@ -1,20 +1,31 @@ """ -Configuration management for OmniShopAgent +Configuration management for ShopAgent Loads environment variables and provides configuration objects """ -import os +from pathlib import Path from typing import Optional -from pydantic_settings import BaseSettings +from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict + +# config.py sits at app/config.py → parent.parent = project root +PROJECT_ROOT = Path(__file__).resolve().parent.parent class Settings(BaseSettings): """Application settings loaded from environment variables All settings can be configured via .env file or environment variables. + Priority (high → low): init kwargs > .env file > env vars > defaults """ + model_config = SettingsConfigDict( + env_file=str(PROJECT_ROOT / ".env"), + env_file_encoding="utf-8", + case_sensitive=False, + extra="ignore", + ) + # OpenAI Configuration openai_api_key: str openai_model: str = "gpt-4o-mini" @@ -30,7 +41,7 @@ class Settings(BaseSettings): # Search API (see docs/搜索API对接指南.md) search_api_base_url: str = "http://120.76.41.98:6002" - search_api_tenant_id: str = "162" + search_api_tenant_id: str = "170" # Application Configuration app_host: str = "0.0.0.0" @@ -43,19 +54,27 @@ class Settings(BaseSettings): processed_data_path: str = "./data/processed" image_data_path: str = "./data/images" - class Config: - env_file = ".env" - env_file_encoding = "utf-8" - case_sensitive = False - extra = "ignore" + @classmethod + def settings_customise_sources( + cls, + settings_cls: type[BaseSettings], + init_settings: PydanticBaseSettingsSource, + env_settings: PydanticBaseSettingsSource, + dotenv_settings: PydanticBaseSettingsSource, + file_secret_settings: PydanticBaseSettingsSource, + ) -> tuple[PydanticBaseSettingsSource, ...]: + """Make .env file take priority over system environment variables. + + Default order: init > env > dotenv > secrets + Our order: init > dotenv > env > secrets + """ + return init_settings, dotenv_settings, env_settings, file_secret_settings # Global settings instance settings = Settings() -# Helper function to get absolute paths def get_absolute_path(relative_path: str) -> str: - """Convert relative path to absolute path""" - base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - return os.path.join(base_dir, relative_path) + """Convert relative path to absolute path based on project root""" + return str(PROJECT_ROOT / relative_path) diff --git a/docs/DEPLOY_CENTOS8.md b/docs/DEPLOY_CENTOS8.md index c3db0f7..d71df34 100644 --- a/docs/DEPLOY_CENTOS8.md +++ b/docs/DEPLOY_CENTOS8.md @@ -1,4 +1,4 @@ -# OmniShopAgent CentOS 8 部署指南 +# ShopAgent CentOS 8 部署指南 ## 一、环境要求 @@ -122,7 +122,7 @@ streamlit run app.py --server.port=8501 --server.address=0.0.0.0 ```ini [Unit] -Description=OmniShopAgent Streamlit App +Description=ShopAgent Streamlit App After=network.target [Service] diff --git a/docs/技术实现报告.md b/docs/技术实现报告.md index 5a1fe39..314c59d 100644 --- a/docs/技术实现报告.md +++ b/docs/技术实现报告.md @@ -1,8 +1,8 @@ -# OmniShopAgent 项目技术实现报告 +# ShopAgent 项目技术实现报告 ## 一、项目概述 -OmniShopAgent 是一个基于 **LangGraph** 和 **ReAct 模式** 的自主多模态时尚购物智能体。系统能够自主决定调用哪些工具、维护对话状态、判断何时回复,实现智能化的商品发现与推荐。 +ShopAgent 是一个基于 **LangGraph** 和 **ReAct 模式** 的自主多模态时尚购物智能体。系统能够自主决定调用哪些工具、维护对话状态、判断何时回复,实现智能化的商品发现与推荐。 ### 核心特性 @@ -385,7 +385,7 @@ streamlit run app.py ## 八、附录:项目结构 ``` -OmniShopAgent/ +ShopAgent/ ├── app/ │ ├── agents/ │ │ └── shopping_agent.py diff --git a/scripts/check_services.sh b/scripts/check_services.sh deleted file mode 100755 index 8522bb5..0000000 --- a/scripts/check_services.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================= -# OmniShopAgent - 服务健康检查脚本 -# 检查 Streamlit、Search API 等依赖 -# ============================================================================= -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' - -echo "==========================================" -echo "OmniShopAgent 服务健康检查" -echo "==========================================" - -# 1. Python 环境 -echo -n "[Python] " -if command -v python3 &>/dev/null; then - VER=$(python3 -c 'import sys; v=sys.version_info; print(f"{v.major}.{v.minor}.{v.micro}")' 2>/dev/null) - if [[ "$VER" == "3.1"* ]] || [[ "$VER" == "3.12"* ]]; then - echo -e "${GREEN}OK${NC} $VER" - else - echo -e "${YELLOW}WARN${NC} $VER (建议 3.12+)" - fi -else - echo -e "${RED}FAIL${NC} 未找到" -fi - -# 2. 虚拟环境 -echo -n "[Virtualenv] " -if [ -d "$PROJECT_ROOT/venv" ]; then - echo -e "${GREEN}OK${NC} $PROJECT_ROOT/venv" -else - echo -e "${YELLOW}WARN${NC} 未找到 venv" -fi - -# 3. .env 配置 -echo -n "[.env] " -if [ -f "$PROJECT_ROOT/.env" ]; then - if grep -q "OPENAI_API_KEY=sk-" "$PROJECT_ROOT/.env" 2>/dev/null; then - echo -e "${GREEN}OK${NC} 已配置" - else - echo -e "${YELLOW}WARN${NC} 请配置 OPENAI_API_KEY" - fi -else - echo -e "${RED}FAIL${NC} 未找到" -fi - -# 4. 数据目录(可选,用于图片上传) -echo -n "[数据] " -if [ -d "$PROJECT_ROOT/data/images" ] && [ -f "$PROJECT_ROOT/data/styles.csv" ]; then - IMG_COUNT=$(find "$PROJECT_ROOT/data/images" -name "*.jpg" 2>/dev/null | wc -l) - echo -e "${GREEN}OK${NC} $IMG_COUNT 张图片" -else - echo -e "${YELLOW}WARN${NC} 未找到 data/images 或 data/styles.csv (可选,用于图片风格分析)" -fi - -# 5. Streamlit -echo -n "[Streamlit] " -if pgrep -f "streamlit run app.py" >/dev/null 2>&1; then - echo -e "${GREEN}OK${NC} 运行中" -else - echo -e "${YELLOW}WARN${NC} 未运行 (./scripts/start.sh)" -fi - -echo "==========================================" diff --git a/scripts/setup_env_centos8.sh b/scripts/setup_env_centos8.sh deleted file mode 100755 index 76b9b59..0000000 --- a/scripts/setup_env_centos8.sh +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================= -# OmniShopAgent - CentOS 8 环境准备脚本 -# 准备 Python 3.12、Docker、依赖及虚拟环境 -# ============================================================================= -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -VENV_DIR="${VENV_DIR:-$PROJECT_ROOT/venv}" -PYTHON_VERSION="${PYTHON_VERSION:-3.12}" - -echo "==========================================" -echo "OmniShopAgent - CentOS 8 环境准备" -echo "==========================================" -echo "项目目录: $PROJECT_ROOT" -echo "虚拟环境: $VENV_DIR" -echo "Python 版本: $PYTHON_VERSION" -echo "==========================================" - -# ----------------------------------------------------------------------------- -# 1. 安装系统依赖 -# ----------------------------------------------------------------------------- -echo "[1/4] 安装系统依赖..." -sudo dnf install -y \ - gcc \ - gcc-c++ \ - make \ - openssl-devel \ - bzip2-devel \ - libffi-devel \ - sqlite-devel \ - xz-devel \ - zlib-devel \ - readline-devel \ - tk-devel \ - libuuid-devel \ - curl \ - wget \ - git \ - tar - -# ----------------------------------------------------------------------------- -# 2. 检查 Docker(可选) -# ----------------------------------------------------------------------------- -echo "[2/4] 检查 Docker..." -if ! command -v docker &>/dev/null; then - echo " 安装 Docker..." - sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || { - sudo dnf install -y dnf-plugins-core - sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo - } - sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin - sudo systemctl enable docker - sudo systemctl start docker - sudo usermod -aG docker "$USER" 2>/dev/null || true - echo " Docker 已安装。请执行 'newgrp docker' 或重新登录以使用 docker 命令。" -else - echo " Docker 已安装: $(docker --version)" -fi - -# ----------------------------------------------------------------------------- -# 3. 安装 Python 3.12 -# ----------------------------------------------------------------------------- -echo "[3/4] 安装 Python $PYTHON_VERSION..." - -USE_CONDA=false -if command -v python3.12 &>/dev/null; then - echo " Python 3.12 已安装" -elif command -v conda &>/dev/null; then - echo " 使用 conda 创建 Python $PYTHON_VERSION 环境..." - conda create -n shop_agent "python=$PYTHON_VERSION" -y - USE_CONDA=true - echo " Conda 环境已创建。请执行: conda activate shop_agent" - echo " 然后手动执行: pip install -r $PROJECT_ROOT/requirements.txt" - echo " 跳过 venv 创建..." -else - echo " 从源码编译 Python $PYTHON_VERSION..." - sudo dnf groupinstall -y 'Development Tools' - cd /tmp - PY_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.0.tgz" - PY_TGZ="Python-${PYTHON_VERSION}.0.tgz" - [ -f "$PY_TGZ" ] || wget -q "$PY_URL" -O "$PY_TGZ" - tar xzf "$PY_TGZ" - cd "Python-${PYTHON_VERSION}.0" - ./configure --enable-optimizations --prefix=/usr/local - make -j "$(nproc)" - sudo make altinstall - cd /tmp - rm -rf "Python-${PYTHON_VERSION}.0" "$PY_TGZ" -fi - -# ----------------------------------------------------------------------------- -# 4. 创建虚拟环境并安装依赖(非 conda 时) -# ----------------------------------------------------------------------------- -if [ "$USE_CONDA" = true ]; then - echo "[4/4] 已使用 conda,跳过 venv 创建" -else - echo "[4/4] 创建虚拟环境与安装 Python 依赖..." - - PYTHON_BIN="" - for p in python3.12 python3.11 python3; do - if command -v "$p" &>/dev/null; then - VER=$("$p" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0") - if [[ "$VER" == "3.1"* ]] || [[ "$VER" == "3.12"* ]]; then - PYTHON_BIN="$p" - break - fi - fi - done - - if [ -z "$PYTHON_BIN" ]; then - echo " 错误: 未找到 Python 3.10+。若使用 conda,请先执行: conda activate shop_agent" - echo " 然后手动执行: pip install -r $PROJECT_ROOT/requirements.txt" - exit 1 - fi - - if [ ! -d "$VENV_DIR" ]; then - echo " 创建虚拟环境: $VENV_DIR" - "$PYTHON_BIN" -m venv "$VENV_DIR" - fi - - echo " 激活虚拟环境并安装依赖..." - set +u - source "$VENV_DIR/bin/activate" - set -u - pip install -U pip - pip install -r "$PROJECT_ROOT/requirements.txt" - echo " Python 依赖安装完成。" -fi - -# 配置 .env -if [ ! -f "$PROJECT_ROOT/.env" ]; then - echo "" - echo " 创建 .env 配置文件..." - cp "$PROJECT_ROOT/.env.example" "$PROJECT_ROOT/.env" - echo " 请编辑 $PROJECT_ROOT/.env 配置 OPENAI_API_KEY 等参数。" -fi - -echo "" -echo "==========================================" -echo "环境准备完成!" -echo "==========================================" -echo "下一步:" -echo " 1. 编辑 .env 配置 OPENAI_API_KEY、SEARCH_API_BASE_URL 等" -echo " 2. (可选)下载数据: python scripts/download_dataset.py" -echo " 3. 启动应用: ./scripts/start.sh" -echo "" -echo "激活虚拟环境: source $VENV_DIR/bin/activate" -echo "==========================================" diff --git a/scripts/start.sh b/scripts/start.sh index 10bef6a..8cab72b 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -1,30 +1,26 @@ #!/usr/bin/env bash # ============================================================================= -# OmniShopAgent - 启动脚本 +# ShopAgent - 启动脚本 # 启动 Streamlit 应用 # ============================================================================= set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +# 从项目根目录执行: sh scripts/start.sh +PROJECT_ROOT="$(pwd)" VENV_DIR="${VENV_DIR:-$PROJECT_ROOT/venv}" STREAMLIT_PORT="${STREAMLIT_PORT:-6008}" STREAMLIT_HOST="${STREAMLIT_HOST:-0.0.0.0}" cd "$PROJECT_ROOT" -# 激活虚拟环境 -if [ -d "$VENV_DIR" ]; then - echo "激活虚拟环境: $VENV_DIR" - set +u - source "$VENV_DIR/bin/activate" - set -u -else - echo "警告: 未找到虚拟环境 $VENV_DIR,使用当前 Python" +if [ "$CONDA_DEFAULT_ENV" != "aishopping-py312" ]; then + echo "正在激活环境..." + source ~/miniconda3/etc/profile.d/conda.sh + conda activate aishopping-py312 fi echo "==========================================" -echo "OmniShopAgent 启动" +echo "ShopAgent 启动" echo "==========================================" echo "[1/1] 启动 Streamlit (端口 $STREAMLIT_PORT)..." diff --git a/scripts/stop.sh b/scripts/stop.sh deleted file mode 100755 index d16d35d..0000000 --- a/scripts/stop.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash -# ============================================================================= -# OmniShopAgent - 停止脚本 -# 停止 Streamlit 进程 -# ============================================================================= -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" -STREAMLIT_PORT="${STREAMLIT_PORT:-6008}" - -echo "==========================================" -echo "OmniShopAgent 停止" -echo "==========================================" - -# 1. 停止 Streamlit 进程 -echo "[1/1] 停止 Streamlit..." -if pgrep -f "streamlit run app.py" >/dev/null 2>&1; then - pkill -f "streamlit run app.py" 2>/dev/null || true - echo " Streamlit 已停止" -else - echo " Streamlit 未在运行" -fi - -# 按端口查找并终止 -if command -v lsof &>/dev/null; then - PID=$(lsof -ti:$STREAMLIT_PORT 2>/dev/null || true) - if [ -n "$PID" ]; then - kill $PID 2>/dev/null || true - echo " 已终止端口 $STREAMLIT_PORT 上的进程" - fi -fi - -echo "==========================================" -echo "OmniShopAgent 已停止" -echo "==========================================" -- libgit2 0.21.2