Commit bad17b157189d0f6649875fb25d8ae16f56f31da

Authored by tangwang
1 parent 8810a6fa

调通baseline

1 -# OmniShopAgent 1 +# ShopAgent
2 2
3 An autonomous multi-modal fashion shopping agent powered by **LangGraph** and **ReAct pattern**. 3 An autonomous multi-modal fashion shopping agent powered by **LangGraph** and **ReAct pattern**.
4 4
@@ -8,7 +8,7 @@ An autonomous multi-modal fashion shopping agent powered by **LangGraph** and ** @@ -8,7 +8,7 @@ An autonomous multi-modal fashion shopping agent powered by **LangGraph** and **
8 8
9 ## Overview 9 ## Overview
10 10
11 -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. 11 +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.
12 12
13 **Key Features:** 13 **Key Features:**
14 - Autonomous tool selection and execution 14 - Autonomous tool selection and execution
@@ -98,7 +98,7 @@ Agent: analyze_image_style(path) → Extracts shirt details @@ -98,7 +98,7 @@ Agent: analyze_image_style(path) → Extracts shirt details
98 ```bash 98 ```bash
99 # Clone and install dependencies 99 # Clone and install dependencies
100 git clone <repository-url> 100 git clone <repository-url>
101 -cd OmniShopAgent 101 +cd ShopAgent
102 python -m venv venv 102 python -m venv venv
103 source venv/bin/activate # Windows: venv\Scripts\activate 103 source venv/bin/activate # Windows: venv\Scripts\activate
104 pip install -r requirements.txt 104 pip install -r requirements.txt
1 """ 1 """
2 -OmniShopAgent - Streamlit UI 2 +ShopAgent - Streamlit UI
3 Multi-modal fashion shopping assistant with conversational AI 3 Multi-modal fashion shopping assistant with conversational AI
4 """ 4 """
5 5
@@ -23,7 +23,7 @@ logger = logging.getLogger(__name__) @@ -23,7 +23,7 @@ logger = logging.getLogger(__name__)
23 23
24 # Page config 24 # Page config
25 st.set_page_config( 25 st.set_page_config(
26 - page_title="OmniShopAgent", 26 + page_title="ShopAgent",
27 page_icon="👗", 27 page_icon="👗",
28 layout="centered", 28 layout="centered",
29 initial_sidebar_state="collapsed", 29 initial_sidebar_state="collapsed",
@@ -541,7 +541,7 @@ def main(): @@ -541,7 +541,7 @@ def main():
541 st.markdown( 541 st.markdown(
542 """ 542 """
543 <div class="app-header"> 543 <div class="app-header">
544 - <div class="app-title">👗 OmniShopAgent</div> 544 + <div class="app-title">👗 ShopAgent</div>
545 <div class="app-subtitle">AI Fashion Shopping Assistant</div> 545 <div class="app-subtitle">AI Fashion Shopping Assistant</div>
546 </div> 546 </div>
547 """, 547 """,
1 """ 1 """
2 -OmniShopAgent - Multi-modal E-commerce Search Agent 2 +ShopAgent - Multi-modal E-commerce Search Agent
3 """ 3 """
4 4
5 __version__ = "0.1.0" 5 __version__ = "0.1.0"
app/agents/shopping_agent.py
@@ -44,7 +44,7 @@ class AgentState(TypedDict): @@ -44,7 +44,7 @@ class AgentState(TypedDict):
44 messages: Annotated[Sequence[BaseMessage], add_messages] 44 messages: Annotated[Sequence[BaseMessage], add_messages]
45 current_image_path: Optional[str] # Track uploaded image 45 current_image_path: Optional[str] # Track uploaded image
46 46
47 - 47 +print("settings")
48 class ShoppingAgent: 48 class ShoppingAgent:
49 """True ReAct agent with autonomous decision making""" 49 """True ReAct agent with autonomous decision making"""
50 50
@@ -59,6 +59,10 @@ class ShoppingAgent: @@ -59,6 +59,10 @@ class ShoppingAgent:
59 ) 59 )
60 if settings.openai_api_base_url: 60 if settings.openai_api_base_url:
61 llm_kwargs["base_url"] = settings.openai_api_base_url 61 llm_kwargs["base_url"] = settings.openai_api_base_url
  62 +
  63 + print("llm_kwargs")
  64 + print(llm_kwargs)
  65 +
62 self.llm = ChatOpenAI(**llm_kwargs) 66 self.llm = ChatOpenAI(**llm_kwargs)
63 67
64 # Get tools and bind to model 68 # Get tools and bind to model
1 """ 1 """
2 -Configuration management for OmniShopAgent 2 +Configuration management for ShopAgent
3 Loads environment variables and provides configuration objects 3 Loads environment variables and provides configuration objects
4 """ 4 """
5 5
6 -import os 6 +from pathlib import Path
7 from typing import Optional 7 from typing import Optional
8 8
9 -from pydantic_settings import BaseSettings 9 +from pydantic_settings import BaseSettings, PydanticBaseSettingsSource, SettingsConfigDict
  10 +
  11 +# config.py sits at app/config.py → parent.parent = project root
  12 +PROJECT_ROOT = Path(__file__).resolve().parent.parent
10 13
11 14
12 class Settings(BaseSettings): 15 class Settings(BaseSettings):
13 """Application settings loaded from environment variables 16 """Application settings loaded from environment variables
14 17
15 All settings can be configured via .env file or environment variables. 18 All settings can be configured via .env file or environment variables.
  19 + Priority (high → low): init kwargs > .env file > env vars > defaults
16 """ 20 """
17 21
  22 + model_config = SettingsConfigDict(
  23 + env_file=str(PROJECT_ROOT / ".env"),
  24 + env_file_encoding="utf-8",
  25 + case_sensitive=False,
  26 + extra="ignore",
  27 + )
  28 +
18 # OpenAI Configuration 29 # OpenAI Configuration
19 openai_api_key: str 30 openai_api_key: str
20 openai_model: str = "gpt-4o-mini" 31 openai_model: str = "gpt-4o-mini"
@@ -30,7 +41,7 @@ class Settings(BaseSettings): @@ -30,7 +41,7 @@ class Settings(BaseSettings):
30 41
31 # Search API (see docs/搜索API对接指南.md) 42 # Search API (see docs/搜索API对接指南.md)
32 search_api_base_url: str = "http://120.76.41.98:6002" 43 search_api_base_url: str = "http://120.76.41.98:6002"
33 - search_api_tenant_id: str = "162" 44 + search_api_tenant_id: str = "170"
34 45
35 # Application Configuration 46 # Application Configuration
36 app_host: str = "0.0.0.0" 47 app_host: str = "0.0.0.0"
@@ -43,19 +54,27 @@ class Settings(BaseSettings): @@ -43,19 +54,27 @@ class Settings(BaseSettings):
43 processed_data_path: str = "./data/processed" 54 processed_data_path: str = "./data/processed"
44 image_data_path: str = "./data/images" 55 image_data_path: str = "./data/images"
45 56
46 - class Config:  
47 - env_file = ".env"  
48 - env_file_encoding = "utf-8"  
49 - case_sensitive = False  
50 - extra = "ignore" 57 + @classmethod
  58 + def settings_customise_sources(
  59 + cls,
  60 + settings_cls: type[BaseSettings],
  61 + init_settings: PydanticBaseSettingsSource,
  62 + env_settings: PydanticBaseSettingsSource,
  63 + dotenv_settings: PydanticBaseSettingsSource,
  64 + file_secret_settings: PydanticBaseSettingsSource,
  65 + ) -> tuple[PydanticBaseSettingsSource, ...]:
  66 + """Make .env file take priority over system environment variables.
  67 +
  68 + Default order: init > env > dotenv > secrets
  69 + Our order: init > dotenv > env > secrets
  70 + """
  71 + return init_settings, dotenv_settings, env_settings, file_secret_settings
51 72
52 73
53 # Global settings instance 74 # Global settings instance
54 settings = Settings() 75 settings = Settings()
55 76
56 77
57 -# Helper function to get absolute paths  
58 def get_absolute_path(relative_path: str) -> str: 78 def get_absolute_path(relative_path: str) -> str:
59 - """Convert relative path to absolute path"""  
60 - base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  
61 - return os.path.join(base_dir, relative_path) 79 + """Convert relative path to absolute path based on project root"""
  80 + return str(PROJECT_ROOT / relative_path)
docs/DEPLOY_CENTOS8.md
1 -# OmniShopAgent CentOS 8 部署指南 1 +# ShopAgent CentOS 8 部署指南
2 2
3 ## 一、环境要求 3 ## 一、环境要求
4 4
@@ -122,7 +122,7 @@ streamlit run app.py --server.port=8501 --server.address=0.0.0.0 @@ -122,7 +122,7 @@ streamlit run app.py --server.port=8501 --server.address=0.0.0.0
122 122
123 ```ini 123 ```ini
124 [Unit] 124 [Unit]
125 -Description=OmniShopAgent Streamlit App 125 +Description=ShopAgent Streamlit App
126 After=network.target 126 After=network.target
127 127
128 [Service] 128 [Service]
docs/技术实现报告.md
1 -# OmniShopAgent 项目技术实现报告 1 +# ShopAgent 项目技术实现报告
2 2
3 ## 一、项目概述 3 ## 一、项目概述
4 4
5 -OmniShopAgent 是一个基于 **LangGraph** 和 **ReAct 模式** 的自主多模态时尚购物智能体。系统能够自主决定调用哪些工具、维护对话状态、判断何时回复,实现智能化的商品发现与推荐。 5 +ShopAgent 是一个基于 **LangGraph** 和 **ReAct 模式** 的自主多模态时尚购物智能体。系统能够自主决定调用哪些工具、维护对话状态、判断何时回复,实现智能化的商品发现与推荐。
6 6
7 ### 核心特性 7 ### 核心特性
8 8
@@ -385,7 +385,7 @@ streamlit run app.py @@ -385,7 +385,7 @@ streamlit run app.py
385 ## 八、附录:项目结构 385 ## 八、附录:项目结构
386 386
387 ``` 387 ```
388 -OmniShopAgent/ 388 +ShopAgent/
389 ├── app/ 389 ├── app/
390 │ ├── agents/ 390 │ ├── agents/
391 │ │ └── shopping_agent.py 391 │ │ └── shopping_agent.py
scripts/check_services.sh deleted
@@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
1 -#!/usr/bin/env bash  
2 -# =============================================================================  
3 -# OmniShopAgent - 服务健康检查脚本  
4 -# 检查 Streamlit、Search API 等依赖  
5 -# =============================================================================  
6 -set -euo pipefail  
7 -  
8 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"  
9 -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"  
10 -RED='\033[0;31m'  
11 -GREEN='\033[0;32m'  
12 -YELLOW='\033[1;33m'  
13 -NC='\033[0m'  
14 -  
15 -echo "=========================================="  
16 -echo "OmniShopAgent 服务健康检查"  
17 -echo "=========================================="  
18 -  
19 -# 1. Python 环境  
20 -echo -n "[Python] "  
21 -if command -v python3 &>/dev/null; then  
22 - VER=$(python3 -c 'import sys; v=sys.version_info; print(f"{v.major}.{v.minor}.{v.micro}")' 2>/dev/null)  
23 - if [[ "$VER" == "3.1"* ]] || [[ "$VER" == "3.12"* ]]; then  
24 - echo -e "${GREEN}OK${NC} $VER"  
25 - else  
26 - echo -e "${YELLOW}WARN${NC} $VER (建议 3.12+)"  
27 - fi  
28 -else  
29 - echo -e "${RED}FAIL${NC} 未找到"  
30 -fi  
31 -  
32 -# 2. 虚拟环境  
33 -echo -n "[Virtualenv] "  
34 -if [ -d "$PROJECT_ROOT/venv" ]; then  
35 - echo -e "${GREEN}OK${NC} $PROJECT_ROOT/venv"  
36 -else  
37 - echo -e "${YELLOW}WARN${NC} 未找到 venv"  
38 -fi  
39 -  
40 -# 3. .env 配置  
41 -echo -n "[.env] "  
42 -if [ -f "$PROJECT_ROOT/.env" ]; then  
43 - if grep -q "OPENAI_API_KEY=sk-" "$PROJECT_ROOT/.env" 2>/dev/null; then  
44 - echo -e "${GREEN}OK${NC} 已配置"  
45 - else  
46 - echo -e "${YELLOW}WARN${NC} 请配置 OPENAI_API_KEY"  
47 - fi  
48 -else  
49 - echo -e "${RED}FAIL${NC} 未找到"  
50 -fi  
51 -  
52 -# 4. 数据目录(可选,用于图片上传)  
53 -echo -n "[数据] "  
54 -if [ -d "$PROJECT_ROOT/data/images" ] && [ -f "$PROJECT_ROOT/data/styles.csv" ]; then  
55 - IMG_COUNT=$(find "$PROJECT_ROOT/data/images" -name "*.jpg" 2>/dev/null | wc -l)  
56 - echo -e "${GREEN}OK${NC} $IMG_COUNT 张图片"  
57 -else  
58 - echo -e "${YELLOW}WARN${NC} 未找到 data/images 或 data/styles.csv (可选,用于图片风格分析)"  
59 -fi  
60 -  
61 -# 5. Streamlit  
62 -echo -n "[Streamlit] "  
63 -if pgrep -f "streamlit run app.py" >/dev/null 2>&1; then  
64 - echo -e "${GREEN}OK${NC} 运行中"  
65 -else  
66 - echo -e "${YELLOW}WARN${NC} 未运行 (./scripts/start.sh)"  
67 -fi  
68 -  
69 -echo "=========================================="  
scripts/setup_env_centos8.sh deleted
@@ -1,150 +0,0 @@ @@ -1,150 +0,0 @@
1 -#!/usr/bin/env bash  
2 -# =============================================================================  
3 -# OmniShopAgent - CentOS 8 环境准备脚本  
4 -# 准备 Python 3.12、Docker、依赖及虚拟环境  
5 -# =============================================================================  
6 -set -euo pipefail  
7 -  
8 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"  
9 -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"  
10 -VENV_DIR="${VENV_DIR:-$PROJECT_ROOT/venv}"  
11 -PYTHON_VERSION="${PYTHON_VERSION:-3.12}"  
12 -  
13 -echo "=========================================="  
14 -echo "OmniShopAgent - CentOS 8 环境准备"  
15 -echo "=========================================="  
16 -echo "项目目录: $PROJECT_ROOT"  
17 -echo "虚拟环境: $VENV_DIR"  
18 -echo "Python 版本: $PYTHON_VERSION"  
19 -echo "=========================================="  
20 -  
21 -# -----------------------------------------------------------------------------  
22 -# 1. 安装系统依赖  
23 -# -----------------------------------------------------------------------------  
24 -echo "[1/4] 安装系统依赖..."  
25 -sudo dnf install -y \  
26 - gcc \  
27 - gcc-c++ \  
28 - make \  
29 - openssl-devel \  
30 - bzip2-devel \  
31 - libffi-devel \  
32 - sqlite-devel \  
33 - xz-devel \  
34 - zlib-devel \  
35 - readline-devel \  
36 - tk-devel \  
37 - libuuid-devel \  
38 - curl \  
39 - wget \  
40 - git \  
41 - tar  
42 -  
43 -# -----------------------------------------------------------------------------  
44 -# 2. 检查 Docker(可选)  
45 -# -----------------------------------------------------------------------------  
46 -echo "[2/4] 检查 Docker..."  
47 -if ! command -v docker &>/dev/null; then  
48 - echo " 安装 Docker..."  
49 - sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 2>/dev/null || {  
50 - sudo dnf install -y dnf-plugins-core  
51 - sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo  
52 - }  
53 - sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin  
54 - sudo systemctl enable docker  
55 - sudo systemctl start docker  
56 - sudo usermod -aG docker "$USER" 2>/dev/null || true  
57 - echo " Docker 已安装。请执行 'newgrp docker' 或重新登录以使用 docker 命令。"  
58 -else  
59 - echo " Docker 已安装: $(docker --version)"  
60 -fi  
61 -  
62 -# -----------------------------------------------------------------------------  
63 -# 3. 安装 Python 3.12  
64 -# -----------------------------------------------------------------------------  
65 -echo "[3/4] 安装 Python $PYTHON_VERSION..."  
66 -  
67 -USE_CONDA=false  
68 -if command -v python3.12 &>/dev/null; then  
69 - echo " Python 3.12 已安装"  
70 -elif command -v conda &>/dev/null; then  
71 - echo " 使用 conda 创建 Python $PYTHON_VERSION 环境..."  
72 - conda create -n shop_agent "python=$PYTHON_VERSION" -y  
73 - USE_CONDA=true  
74 - echo " Conda 环境已创建。请执行: conda activate shop_agent"  
75 - echo " 然后手动执行: pip install -r $PROJECT_ROOT/requirements.txt"  
76 - echo " 跳过 venv 创建..."  
77 -else  
78 - echo " 从源码编译 Python $PYTHON_VERSION..."  
79 - sudo dnf groupinstall -y 'Development Tools'  
80 - cd /tmp  
81 - PY_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.0.tgz"  
82 - PY_TGZ="Python-${PYTHON_VERSION}.0.tgz"  
83 - [ -f "$PY_TGZ" ] || wget -q "$PY_URL" -O "$PY_TGZ"  
84 - tar xzf "$PY_TGZ"  
85 - cd "Python-${PYTHON_VERSION}.0"  
86 - ./configure --enable-optimizations --prefix=/usr/local  
87 - make -j "$(nproc)"  
88 - sudo make altinstall  
89 - cd /tmp  
90 - rm -rf "Python-${PYTHON_VERSION}.0" "$PY_TGZ"  
91 -fi  
92 -  
93 -# -----------------------------------------------------------------------------  
94 -# 4. 创建虚拟环境并安装依赖(非 conda 时)  
95 -# -----------------------------------------------------------------------------  
96 -if [ "$USE_CONDA" = true ]; then  
97 - echo "[4/4] 已使用 conda,跳过 venv 创建"  
98 -else  
99 - echo "[4/4] 创建虚拟环境与安装 Python 依赖..."  
100 -  
101 - PYTHON_BIN=""  
102 - for p in python3.12 python3.11 python3; do  
103 - if command -v "$p" &>/dev/null; then  
104 - VER=$("$p" -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null || echo "0")  
105 - if [[ "$VER" == "3.1"* ]] || [[ "$VER" == "3.12"* ]]; then  
106 - PYTHON_BIN="$p"  
107 - break  
108 - fi  
109 - fi  
110 - done  
111 -  
112 - if [ -z "$PYTHON_BIN" ]; then  
113 - echo " 错误: 未找到 Python 3.10+。若使用 conda,请先执行: conda activate shop_agent"  
114 - echo " 然后手动执行: pip install -r $PROJECT_ROOT/requirements.txt"  
115 - exit 1  
116 - fi  
117 -  
118 - if [ ! -d "$VENV_DIR" ]; then  
119 - echo " 创建虚拟环境: $VENV_DIR"  
120 - "$PYTHON_BIN" -m venv "$VENV_DIR"  
121 - fi  
122 -  
123 - echo " 激活虚拟环境并安装依赖..."  
124 - set +u  
125 - source "$VENV_DIR/bin/activate"  
126 - set -u  
127 - pip install -U pip  
128 - pip install -r "$PROJECT_ROOT/requirements.txt"  
129 - echo " Python 依赖安装完成。"  
130 -fi  
131 -  
132 -# 配置 .env  
133 -if [ ! -f "$PROJECT_ROOT/.env" ]; then  
134 - echo ""  
135 - echo " 创建 .env 配置文件..."  
136 - cp "$PROJECT_ROOT/.env.example" "$PROJECT_ROOT/.env"  
137 - echo " 请编辑 $PROJECT_ROOT/.env 配置 OPENAI_API_KEY 等参数。"  
138 -fi  
139 -  
140 -echo ""  
141 -echo "=========================================="  
142 -echo "环境准备完成!"  
143 -echo "=========================================="  
144 -echo "下一步:"  
145 -echo " 1. 编辑 .env 配置 OPENAI_API_KEY、SEARCH_API_BASE_URL 等"  
146 -echo " 2. (可选)下载数据: python scripts/download_dataset.py"  
147 -echo " 3. 启动应用: ./scripts/start.sh"  
148 -echo ""  
149 -echo "激活虚拟环境: source $VENV_DIR/bin/activate"  
150 -echo "=========================================="  
1 #!/usr/bin/env bash 1 #!/usr/bin/env bash
2 # ============================================================================= 2 # =============================================================================
3 -# OmniShopAgent - 启动脚本 3 +# ShopAgent - 启动脚本
4 # 启动 Streamlit 应用 4 # 启动 Streamlit 应用
5 # ============================================================================= 5 # =============================================================================
6 set -euo pipefail 6 set -euo pipefail
7 7
8 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"  
9 -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" 8 +# 从项目根目录执行: sh scripts/start.sh
  9 +PROJECT_ROOT="$(pwd)"
10 VENV_DIR="${VENV_DIR:-$PROJECT_ROOT/venv}" 10 VENV_DIR="${VENV_DIR:-$PROJECT_ROOT/venv}"
11 STREAMLIT_PORT="${STREAMLIT_PORT:-6008}" 11 STREAMLIT_PORT="${STREAMLIT_PORT:-6008}"
12 STREAMLIT_HOST="${STREAMLIT_HOST:-0.0.0.0}" 12 STREAMLIT_HOST="${STREAMLIT_HOST:-0.0.0.0}"
13 13
14 cd "$PROJECT_ROOT" 14 cd "$PROJECT_ROOT"
15 15
16 -# 激活虚拟环境  
17 -if [ -d "$VENV_DIR" ]; then  
18 - echo "激活虚拟环境: $VENV_DIR"  
19 - set +u  
20 - source "$VENV_DIR/bin/activate"  
21 - set -u  
22 -else  
23 - echo "警告: 未找到虚拟环境 $VENV_DIR,使用当前 Python" 16 +if [ "$CONDA_DEFAULT_ENV" != "aishopping-py312" ]; then
  17 + echo "正在激活环境..."
  18 + source ~/miniconda3/etc/profile.d/conda.sh
  19 + conda activate aishopping-py312
24 fi 20 fi
25 21
26 echo "==========================================" 22 echo "=========================================="
27 -echo "OmniShopAgent 启动" 23 +echo "ShopAgent 启动"
28 echo "==========================================" 24 echo "=========================================="
29 25
30 echo "[1/1] 启动 Streamlit (端口 $STREAMLIT_PORT)..." 26 echo "[1/1] 启动 Streamlit (端口 $STREAMLIT_PORT)..."
scripts/stop.sh deleted
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -#!/usr/bin/env bash  
2 -# =============================================================================  
3 -# OmniShopAgent - 停止脚本  
4 -# 停止 Streamlit 进程  
5 -# =============================================================================  
6 -set -euo pipefail  
7 -  
8 -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"  
9 -PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"  
10 -STREAMLIT_PORT="${STREAMLIT_PORT:-6008}"  
11 -  
12 -echo "=========================================="  
13 -echo "OmniShopAgent 停止"  
14 -echo "=========================================="  
15 -  
16 -# 1. 停止 Streamlit 进程  
17 -echo "[1/1] 停止 Streamlit..."  
18 -if pgrep -f "streamlit run app.py" >/dev/null 2>&1; then  
19 - pkill -f "streamlit run app.py" 2>/dev/null || true  
20 - echo " Streamlit 已停止"  
21 -else  
22 - echo " Streamlit 未在运行"  
23 -fi  
24 -  
25 -# 按端口查找并终止  
26 -if command -v lsof &>/dev/null; then  
27 - PID=$(lsof -ti:$STREAMLIT_PORT 2>/dev/null || true)  
28 - if [ -n "$PID" ]; then  
29 - kill $PID 2>/dev/null || true  
30 - echo " 已终止端口 $STREAMLIT_PORT 上的进程"  
31 - fi  
32 -fi  
33 -  
34 -echo "=========================================="  
35 -echo "OmniShopAgent 已停止"  
36 -echo "=========================================="