mirror of
https://github.com/RYDE-WORK/lnp_ml.git
synced 2026-03-23 02:35:59 +08:00
Compare commits
No commits in common. "c225fc67a7fb25e40cee573c624ad0fca11c3fb9" and "75e1dcb0ebd8a2a4d7be28b32747051231203f5f" have entirely different histories.
c225fc67a7
...
75e1dcb0eb
@ -1,75 +0,0 @@
|
|||||||
# Python
|
|
||||||
__pycache__/
|
|
||||||
*.py[cod]
|
|
||||||
*$py.class
|
|
||||||
*.so
|
|
||||||
.Python
|
|
||||||
*.egg-info/
|
|
||||||
.eggs/
|
|
||||||
dist/
|
|
||||||
build/
|
|
||||||
*.egg
|
|
||||||
|
|
||||||
# Virtual environments
|
|
||||||
.venv/
|
|
||||||
venv/
|
|
||||||
ENV/
|
|
||||||
env/
|
|
||||||
.pixi/
|
|
||||||
|
|
||||||
# IDE
|
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
.cursor/
|
|
||||||
|
|
||||||
# Git
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
|
|
||||||
# Data (不需要打包到镜像)
|
|
||||||
data/
|
|
||||||
!data/.gitkeep
|
|
||||||
|
|
||||||
# Notebooks
|
|
||||||
notebooks/
|
|
||||||
*.ipynb
|
|
||||||
|
|
||||||
# Documentation
|
|
||||||
docs/
|
|
||||||
|
|
||||||
# Reports
|
|
||||||
reports/
|
|
||||||
|
|
||||||
# References
|
|
||||||
references/
|
|
||||||
|
|
||||||
# Scripts (训练脚本不需要)
|
|
||||||
scripts/
|
|
||||||
|
|
||||||
# Lock files
|
|
||||||
pixi.lock
|
|
||||||
|
|
||||||
# Tests
|
|
||||||
tests/
|
|
||||||
.pytest_cache/
|
|
||||||
|
|
||||||
# Logs
|
|
||||||
*.log
|
|
||||||
logs/
|
|
||||||
|
|
||||||
# Temporary files
|
|
||||||
*.tmp
|
|
||||||
*.temp
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Models (will be mounted as volume or copied explicitly)
|
|
||||||
# Note: models/final/ is copied in Dockerfile
|
|
||||||
models/finetune_cv/
|
|
||||||
models/pretrain_cv/
|
|
||||||
models/mpnn/
|
|
||||||
models/*.pt
|
|
||||||
models/*.json
|
|
||||||
!models/final/
|
|
||||||
|
|
||||||
63
Dockerfile
63
Dockerfile
@ -1,63 +0,0 @@
|
|||||||
# LNP-ML Docker Image
|
|
||||||
# 多阶段构建,支持 API 和 Streamlit 两种服务
|
|
||||||
|
|
||||||
FROM python:3.8-slim AS base
|
|
||||||
|
|
||||||
# 设置环境变量
|
|
||||||
ENV PYTHONUNBUFFERED=1 \
|
|
||||||
PYTHONDONTWRITEBYTECODE=1 \
|
|
||||||
PIP_NO_CACHE_DIR=1 \
|
|
||||||
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# 安装系统依赖
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
build-essential \
|
|
||||||
libxrender1 \
|
|
||||||
libxext6 \
|
|
||||||
curl \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# 复制依赖文件
|
|
||||||
COPY requirements.txt .
|
|
||||||
|
|
||||||
# 安装 Python 依赖
|
|
||||||
RUN pip install --upgrade pip && \
|
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# 复制项目代码
|
|
||||||
COPY pyproject.toml .
|
|
||||||
COPY README.md .
|
|
||||||
COPY LICENSE .
|
|
||||||
COPY lnp_ml/ ./lnp_ml/
|
|
||||||
COPY app/ ./app/
|
|
||||||
|
|
||||||
# 安装项目包
|
|
||||||
RUN pip install -e .
|
|
||||||
|
|
||||||
# 复制模型文件
|
|
||||||
COPY models/final/ ./models/final/
|
|
||||||
|
|
||||||
# ============ API 服务 ============
|
|
||||||
FROM base AS api
|
|
||||||
|
|
||||||
EXPOSE 8000
|
|
||||||
|
|
||||||
ENV MODEL_PATH=/app/models/final/model.pt
|
|
||||||
|
|
||||||
CMD ["uvicorn", "app.api:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
||||||
|
|
||||||
# ============ Streamlit 服务 ============
|
|
||||||
FROM base AS streamlit
|
|
||||||
|
|
||||||
EXPOSE 8501
|
|
||||||
|
|
||||||
# Streamlit 配置
|
|
||||||
ENV STREAMLIT_SERVER_PORT=8501 \
|
|
||||||
STREAMLIT_SERVER_ADDRESS=0.0.0.0 \
|
|
||||||
STREAMLIT_SERVER_HEADLESS=true \
|
|
||||||
STREAMLIT_BROWSER_GATHER_USAGE_STATS=false
|
|
||||||
|
|
||||||
CMD ["streamlit", "run", "app/app.py"]
|
|
||||||
|
|
||||||
42
Makefile
42
Makefile
@ -200,48 +200,6 @@ serve:
|
|||||||
@echo "然后访问: http://localhost:8501"
|
@echo "然后访问: http://localhost:8501"
|
||||||
|
|
||||||
|
|
||||||
#################################################################################
|
|
||||||
# DOCKER COMMANDS #
|
|
||||||
#################################################################################
|
|
||||||
|
|
||||||
## Build Docker images
|
|
||||||
.PHONY: docker-build
|
|
||||||
docker-build:
|
|
||||||
docker compose build
|
|
||||||
|
|
||||||
## Start all services with Docker Compose
|
|
||||||
.PHONY: docker-up
|
|
||||||
docker-up:
|
|
||||||
docker compose up -d
|
|
||||||
|
|
||||||
## Stop all Docker services
|
|
||||||
.PHONY: docker-down
|
|
||||||
docker-down:
|
|
||||||
docker compose down
|
|
||||||
|
|
||||||
## View Docker logs
|
|
||||||
.PHONY: docker-logs
|
|
||||||
docker-logs:
|
|
||||||
docker compose logs -f
|
|
||||||
|
|
||||||
## Build and start all services
|
|
||||||
.PHONY: docker-serve
|
|
||||||
docker-serve: docker-build docker-up
|
|
||||||
@echo ""
|
|
||||||
@echo "🚀 服务已启动!"
|
|
||||||
@echo " - API: http://localhost:8000"
|
|
||||||
@echo " - Web 应用: http://localhost:8501"
|
|
||||||
@echo ""
|
|
||||||
@echo "查看日志: make docker-logs"
|
|
||||||
@echo "停止服务: make docker-down"
|
|
||||||
|
|
||||||
## Clean Docker resources (images, volumes, etc.)
|
|
||||||
.PHONY: docker-clean
|
|
||||||
docker-clean:
|
|
||||||
docker compose down -v --rmi local
|
|
||||||
docker system prune -f
|
|
||||||
|
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
# Self Documenting Commands #
|
# Self Documenting Commands #
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
|||||||
150
app/app.py
150
app/app.py
@ -3,13 +3,9 @@ Streamlit 配方优化交互界面
|
|||||||
|
|
||||||
启动应用:
|
启动应用:
|
||||||
streamlit run app/app.py
|
streamlit run app/app.py
|
||||||
|
|
||||||
Docker 环境变量:
|
|
||||||
API_URL: API 服务地址 (默认: http://localhost:8000)
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import io
|
import io
|
||||||
import os
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
@ -18,8 +14,7 @@ import streamlit as st
|
|||||||
|
|
||||||
# ============ 配置 ============
|
# ============ 配置 ============
|
||||||
|
|
||||||
# 从环境变量读取 API 地址,支持 Docker 环境
|
API_URL = "http://localhost:8000"
|
||||||
API_URL = os.environ.get("API_URL", "http://localhost:8000")
|
|
||||||
|
|
||||||
AVAILABLE_ORGANS = [
|
AVAILABLE_ORGANS = [
|
||||||
"liver",
|
"liver",
|
||||||
@ -32,13 +27,13 @@ AVAILABLE_ORGANS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
ORGAN_LABELS = {
|
ORGAN_LABELS = {
|
||||||
"liver": "肝脏 (Liver)",
|
"liver": "🫀 肝脏 (Liver)",
|
||||||
"spleen": "脾脏 (Spleen)",
|
"spleen": "🟣 脾脏 (Spleen)",
|
||||||
"lung": "肺 (Lung)",
|
"lung": "🫁 肺 (Lung)",
|
||||||
"heart": "心脏 (Heart)",
|
"heart": "❤️ 心脏 (Heart)",
|
||||||
"kidney": "肾脏 (Kidney)",
|
"kidney": "🫘 肾脏 (Kidney)",
|
||||||
"muscle": "肌肉 (Muscle)",
|
"muscle": "💪 肌肉 (Muscle)",
|
||||||
"lymph_nodes": "淋巴结 (Lymph Nodes)",
|
"lymph_nodes": "🔵 淋巴结 (Lymph Nodes)",
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============ 页面配置 ============
|
# ============ 页面配置 ============
|
||||||
@ -151,20 +146,19 @@ def format_results_dataframe(results: dict) -> pd.DataFrame:
|
|||||||
for f in formulations:
|
for f in formulations:
|
||||||
row = {
|
row = {
|
||||||
"排名": f["rank"],
|
"排名": f["rank"],
|
||||||
# f"{target_organ}分布": f"{f['target_biodist']*100:.2f}%",
|
f"Biodist_{target_organ}": f"{f['target_biodist']:.4f}",
|
||||||
f"{target_organ}分布": f"{f['target_biodist']*100:.8f}%",
|
"阳离子脂质/mRNA": f["cationic_lipid_to_mrna_ratio"],
|
||||||
"阳离子脂质/mRNA比例": f["cationic_lipid_to_mrna_ratio"],
|
"阳离子脂质(mol)": f["cationic_lipid_mol_ratio"],
|
||||||
"阳离子脂质(mol)比例": f["cationic_lipid_mol_ratio"],
|
"磷脂(mol)": f["phospholipid_mol_ratio"],
|
||||||
"磷脂(mol)比例": f["phospholipid_mol_ratio"],
|
"胆固醇(mol)": f["cholesterol_mol_ratio"],
|
||||||
"胆固醇(mol)比例": f["cholesterol_mol_ratio"],
|
"PEG脂质(mol)": f["peg_lipid_mol_ratio"],
|
||||||
"PEG脂质(mol)比例": f["peg_lipid_mol_ratio"],
|
|
||||||
"辅助脂质": f["helper_lipid"],
|
"辅助脂质": f["helper_lipid"],
|
||||||
"给药途径": f["route"],
|
"给药途径": f["route"],
|
||||||
}
|
}
|
||||||
# 添加其他器官的 biodist
|
# 添加其他器官的 biodist
|
||||||
for organ, value in f["all_biodist"].items():
|
for organ, value in f["all_biodist"].items():
|
||||||
if organ != target_organ:
|
if organ != target_organ:
|
||||||
row[f"{organ}分布"] = f"{value*100:.2f}%"
|
row[f"Biodist_{organ}"] = f"{value:.4f}"
|
||||||
rows.append(row)
|
rows.append(row)
|
||||||
|
|
||||||
return pd.DataFrame(rows)
|
return pd.DataFrame(rows)
|
||||||
@ -190,7 +184,7 @@ def main():
|
|||||||
|
|
||||||
# ========== 侧边栏 ==========
|
# ========== 侧边栏 ==========
|
||||||
with st.sidebar:
|
with st.sidebar:
|
||||||
# st.header("⚙️ 参数设置")
|
st.header("⚙️ 参数设置")
|
||||||
|
|
||||||
# API 状态
|
# API 状态
|
||||||
if api_online:
|
if api_online:
|
||||||
@ -199,7 +193,7 @@ def main():
|
|||||||
st.error("🔴 API 服务离线")
|
st.error("🔴 API 服务离线")
|
||||||
st.info("请先启动 API 服务:\n```\nuvicorn app.api:app --port 8000\n```")
|
st.info("请先启动 API 服务:\n```\nuvicorn app.api:app --port 8000\n```")
|
||||||
|
|
||||||
# st.divider()
|
st.divider()
|
||||||
|
|
||||||
# SMILES 输入
|
# SMILES 输入
|
||||||
st.subheader("🔬 分子结构")
|
st.subheader("🔬 分子结构")
|
||||||
@ -212,18 +206,18 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 示例 SMILES
|
# 示例 SMILES
|
||||||
# with st.expander("📋 示例 SMILES"):
|
with st.expander("📋 示例 SMILES"):
|
||||||
# example_smiles = {
|
example_smiles = {
|
||||||
# "DLin-MC3-DMA": "CC(C)=CCCC(C)=CCCC(C)=CCN(C)CCCCCCCCOC(=O)CCCCCCC/C=C\\CCCCCCCC",
|
"DLin-MC3-DMA": "CC(C)=CCCC(C)=CCCC(C)=CCN(C)CCCCCCCCOC(=O)CCCCCCC/C=C\\CCCCCCCC",
|
||||||
# "简单胺": "CC(C)NCCNC(C)C",
|
"简单胺": "CC(C)NCCNC(C)C",
|
||||||
# "长链胺": "CCCCCCCCCCCCNCCNCCCCCCCCCCCC",
|
"长链胺": "CCCCCCCCCCCCNCCNCCCCCCCCCCCC",
|
||||||
# }
|
}
|
||||||
# for name, smi in example_smiles.items():
|
for name, smi in example_smiles.items():
|
||||||
# if st.button(f"使用 {name}", key=f"example_{name}"):
|
if st.button(f"使用 {name}", key=f"example_{name}"):
|
||||||
# st.session_state["smiles_input"] = smi
|
st.session_state["smiles_input"] = smi
|
||||||
# st.rerun()
|
st.rerun()
|
||||||
|
|
||||||
# st.divider()
|
st.divider()
|
||||||
|
|
||||||
# 目标器官选择
|
# 目标器官选择
|
||||||
st.subheader("🎯 目标器官")
|
st.subheader("🎯 目标器官")
|
||||||
@ -234,7 +228,7 @@ def main():
|
|||||||
index=0,
|
index=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
# st.divider()
|
st.divider()
|
||||||
|
|
||||||
# 高级选项
|
# 高级选项
|
||||||
with st.expander("🔧 高级选项"):
|
with st.expander("🔧 高级选项"):
|
||||||
@ -300,8 +294,8 @@ def main():
|
|||||||
with col2:
|
with col2:
|
||||||
best_score = results["formulations"][0]["target_biodist"]
|
best_score = results["formulations"][0]["target_biodist"]
|
||||||
st.metric(
|
st.metric(
|
||||||
"最优分布",
|
"最优 Biodistribution",
|
||||||
f"{best_score*100:.2f}%",
|
f"{best_score:.4f}",
|
||||||
)
|
)
|
||||||
|
|
||||||
with col3:
|
with col3:
|
||||||
@ -339,61 +333,61 @@ def main():
|
|||||||
)
|
)
|
||||||
|
|
||||||
# 详细信息
|
# 详细信息
|
||||||
# with st.expander("🔍 查看最优配方详情"):
|
with st.expander("🔍 查看最优配方详情"):
|
||||||
# best = results["formulations"][0]
|
best = results["formulations"][0]
|
||||||
|
|
||||||
# col1, col2 = st.columns(2)
|
col1, col2 = st.columns(2)
|
||||||
|
|
||||||
# with col1:
|
with col1:
|
||||||
# st.markdown("**配方参数**")
|
st.markdown("**配方参数**")
|
||||||
# st.json({
|
st.json({
|
||||||
# "阳离子脂质/mRNA 比例": best["cationic_lipid_to_mrna_ratio"],
|
"阳离子脂质/mRNA 比例": best["cationic_lipid_to_mrna_ratio"],
|
||||||
# "阳离子脂质 (mol%)": best["cationic_lipid_mol_ratio"],
|
"阳离子脂质 (mol%)": best["cationic_lipid_mol_ratio"],
|
||||||
# "磷脂 (mol%)": best["phospholipid_mol_ratio"],
|
"磷脂 (mol%)": best["phospholipid_mol_ratio"],
|
||||||
# "胆固醇 (mol%)": best["cholesterol_mol_ratio"],
|
"胆固醇 (mol%)": best["cholesterol_mol_ratio"],
|
||||||
# "PEG 脂质 (mol%)": best["peg_lipid_mol_ratio"],
|
"PEG 脂质 (mol%)": best["peg_lipid_mol_ratio"],
|
||||||
# "辅助脂质": best["helper_lipid"],
|
"辅助脂质": best["helper_lipid"],
|
||||||
# "给药途径": best["route"],
|
"给药途径": best["route"],
|
||||||
# })
|
})
|
||||||
|
|
||||||
# with col2:
|
with col2:
|
||||||
# st.markdown("**各器官 Biodistribution 预测**")
|
st.markdown("**各器官 Biodistribution 预测**")
|
||||||
# biodist_df = pd.DataFrame([
|
biodist_df = pd.DataFrame([
|
||||||
# {"器官": ORGAN_LABELS.get(k, k), "Biodistribution": f"{v:.4f}"}
|
{"器官": ORGAN_LABELS.get(k, k), "Biodistribution": f"{v:.4f}"}
|
||||||
# for k, v in best["all_biodist"].items()
|
for k, v in best["all_biodist"].items()
|
||||||
# ])
|
])
|
||||||
# st.dataframe(biodist_df, hide_index=True, use_container_width=True)
|
st.dataframe(biodist_df, hide_index=True, use_container_width=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# 欢迎信息
|
# 欢迎信息
|
||||||
st.info("👈 请在左侧输入 SMILES 并选择目标器官,然后点击「开始配方优选」")
|
st.info("👈 请在左侧输入 SMILES 并选择目标器官,然后点击「开始配方优选」")
|
||||||
|
|
||||||
# 使用说明
|
# 使用说明
|
||||||
# with st.expander("📖 使用说明"):
|
with st.expander("📖 使用说明"):
|
||||||
# st.markdown("""
|
st.markdown("""
|
||||||
# ### 如何使用
|
### 如何使用
|
||||||
|
|
||||||
# 1. **输入 SMILES**: 在左侧输入框中输入阳离子脂质的 SMILES 字符串
|
1. **输入 SMILES**: 在左侧输入框中输入阳离子脂质的 SMILES 字符串
|
||||||
# 2. **选择目标器官**: 选择您希望优化的器官靶向
|
2. **选择目标器官**: 选择您希望优化的器官靶向
|
||||||
# 3. **点击优选**: 系统将自动搜索最优配方组合
|
3. **点击优选**: 系统将自动搜索最优配方组合
|
||||||
# 4. **查看结果**: 右侧将显示 Top-20 优选配方
|
4. **查看结果**: 右侧将显示 Top-20 优选配方
|
||||||
# 5. **导出数据**: 点击导出按钮将结果保存为 CSV 文件
|
5. **导出数据**: 点击导出按钮将结果保存为 CSV 文件
|
||||||
|
|
||||||
# ### 优化参数
|
### 优化参数
|
||||||
|
|
||||||
# 系统会优化以下配方参数:
|
系统会优化以下配方参数:
|
||||||
# - **阳离子脂质/mRNA 比例**: 0.05 - 0.30
|
- **阳离子脂质/mRNA 比例**: 0.05 - 0.30
|
||||||
# - **阳离子脂质 mol 比例**: 0.05 - 0.80
|
- **阳离子脂质 mol 比例**: 0.05 - 0.80
|
||||||
# - **磷脂 mol 比例**: 0.00 - 0.80
|
- **磷脂 mol 比例**: 0.00 - 0.80
|
||||||
# - **胆固醇 mol 比例**: 0.00 - 0.80
|
- **胆固醇 mol 比例**: 0.00 - 0.80
|
||||||
# - **PEG 脂质 mol 比例**: 0.00 - 0.05
|
- **PEG 脂质 mol 比例**: 0.00 - 0.05
|
||||||
# - **辅助脂质**: DOPE / DSPC / DOTAP
|
- **辅助脂质**: DOPE / DSPC / DOTAP
|
||||||
# - **给药途径**: 静脉注射 / 肌肉注射
|
- **给药途径**: 静脉注射 / 肌肉注射
|
||||||
|
|
||||||
# ### 约束条件
|
### 约束条件
|
||||||
|
|
||||||
# mol 比例之和 = 1 (阳离子脂质 + 磷脂 + 胆固醇 + PEG 脂质)
|
mol 比例之和 = 1 (阳离子脂质 + 磷脂 + 胆固醇 + PEG 脂质)
|
||||||
# """)
|
""")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
services:
|
|
||||||
# FastAPI 后端服务
|
|
||||||
api:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: api
|
|
||||||
container_name: lnp-api
|
|
||||||
environment:
|
|
||||||
- MODEL_PATH=/app/models/final/model.pt
|
|
||||||
volumes:
|
|
||||||
# 挂载模型目录以便更新模型
|
|
||||||
- ./models/final:/app/models/final:ro
|
|
||||||
- ./models/mpnn:/app/models/mpnn:ro
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
deploy:
|
|
||||||
resources:
|
|
||||||
reservations:
|
|
||||||
devices:
|
|
||||||
- driver: nvidia
|
|
||||||
count: 1
|
|
||||||
capabilities: [gpu]
|
|
||||||
|
|
||||||
# Streamlit 前端服务
|
|
||||||
streamlit:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: streamlit
|
|
||||||
container_name: lnp-streamlit
|
|
||||||
ports:
|
|
||||||
- "8501:8501"
|
|
||||||
environment:
|
|
||||||
- API_URL=http://api:8000
|
|
||||||
depends_on:
|
|
||||||
api:
|
|
||||||
condition: service_started
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8501/_stcore/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
name: lnp-network
|
|
||||||
@ -1,49 +0,0 @@
|
|||||||
services:
|
|
||||||
# FastAPI 后端服务
|
|
||||||
api:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: api
|
|
||||||
container_name: lnp-api
|
|
||||||
environment:
|
|
||||||
- MODEL_PATH=/app/models/final/model.pt
|
|
||||||
- DEVICE=cpu
|
|
||||||
volumes:
|
|
||||||
# 挂载模型目录以便更新模型
|
|
||||||
- ./models/final:/app/models/final:ro
|
|
||||||
- ./models/mpnn:/app/models/mpnn:ro
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8000/"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 60s
|
|
||||||
|
|
||||||
# Streamlit 前端服务
|
|
||||||
streamlit:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
target: streamlit
|
|
||||||
container_name: lnp-streamlit
|
|
||||||
ports:
|
|
||||||
- "8501:8501"
|
|
||||||
environment:
|
|
||||||
- API_URL=http://api:8000
|
|
||||||
depends_on:
|
|
||||||
api:
|
|
||||||
condition: service_started
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8501/_stcore/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 30s
|
|
||||||
|
|
||||||
networks:
|
|
||||||
default:
|
|
||||||
name: lnp-network
|
|
||||||
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
# 严格遵循 pixi.toml 的依赖版本
|
|
||||||
# 注意: lnp_ml 本地包在 Dockerfile 中单独安装
|
|
||||||
|
|
||||||
# conda dependencies (in pixi.toml [dependencies])
|
|
||||||
loguru
|
|
||||||
tqdm
|
|
||||||
typer
|
|
||||||
|
|
||||||
# pypi dependencies (in pixi.toml [pypi-dependencies])
|
|
||||||
chemprop==1.7.0
|
|
||||||
setuptools
|
|
||||||
pandas>=2.0.3,<3
|
|
||||||
openpyxl>=3.1.5,<4
|
|
||||||
python-dotenv>=1.0.1,<2
|
|
||||||
pyarrow>=17.0.0,<18
|
|
||||||
fastparquet>=2024.2.0,<2025
|
|
||||||
fastapi>=0.124.4,<0.125
|
|
||||||
streamlit>=1.40.1,<2
|
|
||||||
httpx>=0.28.1,<0.29
|
|
||||||
uvicorn>=0.33.0,<0.34
|
|
||||||
Loading…
x
Reference in New Issue
Block a user