Showing
28 changed files
with
150 additions
and
129 deletions
| 1 | -# Git | ||
| 2 | -.git | ||
| 3 | -.gitignore | ||
| 4 | - | ||
| 5 | -# IDE | ||
| 6 | -.idea | ||
| 7 | -.vscode | ||
| 8 | -*.swp | ||
| 9 | -*.swo | ||
| 10 | - | ||
| 11 | # Python | 1 | # Python |
| 12 | -__pycache__ | 2 | +__pycache__/ |
| 13 | *.py[cod] | 3 | *.py[cod] |
| 14 | *$py.class | 4 | *$py.class |
| 15 | *.so | 5 | *.so |
| 16 | .Python | 6 | .Python |
| 17 | -.venv | 7 | +*.egg-info/ |
| 8 | +dist/ | ||
| 9 | +build/ | ||
| 10 | + | ||
| 11 | +# Virtual environments | ||
| 12 | +.venv/ | ||
| 18 | venv/ | 13 | venv/ |
| 19 | 14 | ||
| 20 | -# Cache | ||
| 21 | -.ruff_cache | ||
| 22 | -.mypy_cache | ||
| 23 | -.pytest_cache | ||
| 24 | -.cache | 15 | +# IDE |
| 16 | +.idea/ | ||
| 17 | +.vscode/ | ||
| 18 | +*.swp | ||
| 19 | +*.swo | ||
| 25 | 20 | ||
| 26 | -# Logs | ||
| 27 | -logs/ | ||
| 28 | -*.log | 21 | +# Git |
| 22 | +.git/ | ||
| 23 | +.gitignore | ||
| 29 | 24 | ||
| 30 | # Docker | 25 | # Docker |
| 31 | -dockerfiles/ | ||
| 32 | Dockerfile | 26 | Dockerfile |
| 33 | .dockerignore | 27 | .dockerignore |
| 28 | + | ||
| 29 | +# Logs | ||
| 30 | +*.log | ||
| 31 | + | ||
| 32 | +# Local configs | ||
| 33 | +cfg/config.local.yaml |
Dockerfile
deleted
100644 → 0
| 1 | -FROM python:3.12-slim | ||
| 2 | -ARG DEBIAN_FRONTEND=noninteractive | ||
| 3 | -ENV TZ=Asia/Shanghai PROJECT_ROOT=/app ENV=docker APP_LOG_TYPE=file,console | ||
| 4 | - | ||
| 5 | -# 使用 Debian 的阿里云镜像 | ||
| 6 | -RUN echo "deb http://mirrors.aliyun.com/debian/ bookworm main contrib non-free" > /etc/apt/sources.list && \ | ||
| 7 | - echo "deb http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free" >> /etc/apt/sources.list && \ | ||
| 8 | - echo "deb http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free" >> /etc/apt/sources.list | ||
| 9 | - | ||
| 10 | -# 安装系统依赖 | ||
| 11 | -RUN apt update && apt install -y --no-install-recommends gcc curl vim && rm -rf /var/lib/apt/lists/* | ||
| 12 | -# 安装uv工具 | ||
| 13 | -RUN pip install --no-cache-dir uv | ||
| 14 | -WORKDIR /app | ||
| 15 | -COPY . . | ||
| 16 | -RUN uv pip install --system --no-cache ".[es,postgres]" | ||
| 17 | - | ||
| 18 | -EXPOSE 8000 | ||
| 19 | - | ||
| 20 | -CMD ["python", "main.py"] |
Dockerfile.embedding
0 → 100644
| 1 | +# ============================================================================ | ||
| 2 | +# embedding-server Dockerfile | ||
| 3 | +# ============================================================================ | ||
| 4 | +# 构建命令: | ||
| 5 | +# docker build -f Dockerfile.embedding -t embedding-server:latest . | ||
| 6 | +# | ||
| 7 | +# 运行命令: | ||
| 8 | +# docker run -d -p 8000:8000 --name embedding-server embedding-server:latest | ||
| 9 | +# ============================================================================ | ||
| 10 | + | ||
| 11 | +ARG PYTHON_VERSION=3.12 | ||
| 12 | +#ARG UV_VERSION=0.6.0 | ||
| 13 | + | ||
| 14 | +# ---------------------------------------------------------------------------- | ||
| 15 | +# 构建阶段 | ||
| 16 | +# ---------------------------------------------------------------------------- | ||
| 17 | +FROM python:${PYTHON_VERSION}-slim AS builder | ||
| 18 | +# 使用 Debian 的阿里云镜像 | ||
| 19 | +RUN echo "deb http://mirrors.aliyun.com/debian/ bookworm main contrib non-free" > /etc/apt/sources.list && \ | ||
| 20 | + echo "deb http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free" >> /etc/apt/sources.list && \ | ||
| 21 | + echo "deb http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free" >> /etc/apt/sources.list | ||
| 22 | + | ||
| 23 | +# 安装编译依赖和 uv | ||
| 24 | +RUN apt-get update \ | ||
| 25 | + && apt-get install -y --no-install-recommends gcc curl vim \ | ||
| 26 | + && rm -rf /var/lib/apt/lists/* | ||
| 27 | + | ||
| 28 | +RUN pip install --no-cache-dir uv | ||
| 29 | + | ||
| 30 | +WORKDIR /app | ||
| 31 | + | ||
| 32 | +# 复制项目文件(仅 embedding-server 所需) | ||
| 33 | +COPY pyproject.toml uv.lock ./ | ||
| 34 | +COPY src/embedding_sever/ ./src/embedding_sever/ | ||
| 35 | + | ||
| 36 | +# 安装依赖:核心依赖 + embedding 专用依赖 | ||
| 37 | +RUN uv sync --no-dev --no-editable --extra embedding | ||
| 38 | + | ||
| 39 | +# ---------------------------------------------------------------------------- | ||
| 40 | +# 运行阶段 | ||
| 41 | +# ---------------------------------------------------------------------------- | ||
| 42 | +FROM python:${PYTHON_VERSION}-slim | ||
| 43 | + | ||
| 44 | +WORKDIR /app | ||
| 45 | + | ||
| 46 | +# 从构建阶段复制虚拟环境和源码 | ||
| 47 | +COPY --from=builder /app/.venv /app/.venv | ||
| 48 | +COPY --from=builder /app/src/embedding_sever /app/src/embedding_sever | ||
| 49 | + | ||
| 50 | +# 环境变量 | ||
| 51 | +ENV PATH="/app/.venv/bin:$PATH" | ||
| 52 | +ENV PYTHONPATH="/app/src" | ||
| 53 | +ENV PROJECT_ROOT="/app/src" | ||
| 54 | +ENV PYTHONUNBUFFERED=1 | ||
| 55 | +ENV ENV=prod | ||
| 56 | +ENV APP_LOG_TYPE=file,console | ||
| 57 | + | ||
| 58 | +EXPOSE 8000 | ||
| 59 | + | ||
| 60 | +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ | ||
| 61 | + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" || exit 1 | ||
| 62 | + | ||
| 63 | +CMD ["embedding-server"] |
Dockerfile_use_base
deleted
100644 → 0
dockerfiles/Dockerfile_base260402
deleted
100644 → 0
| 1 | -# 基础镜像 - 安装依赖 | ||
| 2 | -FROM python:3.12-slim | ||
| 3 | - | ||
| 4 | -ARG DEBIAN_FRONTEND=noninteractive | ||
| 5 | -ENV TZ=Asia/Shanghai | ||
| 6 | - | ||
| 7 | -# 使用 Debian 的阿里云镜像 | ||
| 8 | -RUN echo "deb http://mirrors.aliyun.com/debian/ bookworm main contrib non-free" > /etc/apt/sources.list && \ | ||
| 9 | - echo "deb http://mirrors.aliyun.com/debian/ bookworm-updates main contrib non-free" >> /etc/apt/sources.list && \ | ||
| 10 | - echo "deb http://mirrors.aliyun.com/debian-security/ bookworm-security main contrib non-free" >> /etc/apt/sources.list | ||
| 11 | - | ||
| 12 | -# 安装系统依赖 | ||
| 13 | -RUN apt-get update && apt-get install -y --no-install-recommends gcc curl vim && rm -rf /var/lib/apt/lists/* | ||
| 14 | - | ||
| 15 | -# 安装uv工具 | ||
| 16 | -RUN pip install --no-cache-dir uv | ||
| 17 | -WORKDIR /app | ||
| 18 | - | ||
| 19 | -# 复制依赖文件(从构建上下文根目录复制) | ||
| 20 | -COPY pyproject.toml uv.lock ./ | ||
| 21 | - | ||
| 22 | -RUN uv pip install --system --no-cache ".[es,postgres]" |
| 1 | +[build-system] | ||
| 2 | +requires = ["hatchling"] | ||
| 3 | +build-backend = "hatchling.build" | ||
| 4 | + | ||
| 1 | [project] | 5 | [project] |
| 2 | -name = "aigc-embedding-service" | 6 | +name = "ai_server" |
| 3 | version = "0.1.0" | 7 | version = "0.1.0" |
| 4 | -description = "基于向量的CRUD服务,支持多种Embedding场景" | 8 | +description = "Add your description here" |
| 5 | requires-python = ">=3.12" | 9 | requires-python = ">=3.12" |
| 6 | dependencies = [ | 10 | dependencies = [ |
| 7 | "fastapi==0.135.3", | 11 | "fastapi==0.135.3", |
| 8 | "uvicorn[standard]==0.42.0", | 12 | "uvicorn[standard]==0.42.0", |
| 9 | "pydantic==2.12.5", | 13 | "pydantic==2.12.5", |
| 14 | + "numpy>=1.24.0", | ||
| 15 | + "aiohttp>=3.8.0", | ||
| 10 | "aabd==0.4.3", | 16 | "aabd==0.4.3", |
| 11 | "path==17.1.1", | 17 | "path==17.1.1", |
| 12 | "omegaconf==2.3.0", | 18 | "omegaconf==2.3.0", |
| 13 | "elasticsearch>=9.3.0", | 19 | "elasticsearch>=9.3.0", |
| 14 | "packaging==26.0", | 20 | "packaging==26.0", |
| 15 | - "aiohttp==3.13.5", | ||
| 16 | ] | 21 | ] |
| 17 | 22 | ||
| 18 | [project.optional-dependencies] | 23 | [project.optional-dependencies] |
| 19 | -dev = [ | ||
| 20 | - "pytest>=8.3.0", | ||
| 21 | - "pytest-asyncio>=0.24.0", | ||
| 22 | - "black>=24.10.0", | ||
| 23 | - "ruff>=0.7.0", | ||
| 24 | - "mypy>=1.13.0", | ||
| 25 | -] | ||
| 26 | -es = [ | 24 | +# embedding-server 专用依赖 |
| 25 | +embedding = [ | ||
| 27 | "elasticsearch==9.3.0", | 26 | "elasticsearch==9.3.0", |
| 28 | ] | 27 | ] |
| 29 | -postgres = [ | ||
| 30 | - "psycopg[binary,pool]==3.3.3", | ||
| 31 | - "psycopg-pool==3.3.0", | ||
| 32 | -] | 28 | +# task-server 专用依赖 |
| 29 | +task = [ | ||
| 33 | 30 | ||
| 34 | -[tool.black] | ||
| 35 | -line-length = 100 | ||
| 36 | -target-version = ['py312'] | ||
| 37 | - | ||
| 38 | -[tool.ruff] | ||
| 39 | -line-length = 100 | ||
| 40 | -select = ["E", "F", "I", "N", "W", "UP", "B", "C4", "SIM"] | ||
| 41 | -ignore = ["E501"] | 31 | +] |
| 42 | 32 | ||
| 43 | -[tool.mypy] | ||
| 44 | -python_version = "3.12" | ||
| 45 | -warn_return_any = true | ||
| 46 | -warn_unused_configs = true | ||
| 47 | -disallow_untyped_defs = true | 33 | +[tool.uv] |
| 34 | +package = true | ||
| 48 | 35 | ||
| 49 | -[tool.pytest.ini_options] | ||
| 50 | -asyncio_mode = "auto" | ||
| 51 | -testpaths = ["tests"] | ||
| 52 | -python_files = ["test_*.py"] | ||
| 53 | -python_classes = ["Test*"] | ||
| 54 | -python_functions = ["test_*"] | 36 | +[tool.hatch.build.targets.wheel] |
| 37 | +packages = ["src/embedding_sever"] | ||
| 55 | 38 | ||
| 56 | -[tool.setuptools] | ||
| 57 | -packages = [] | 39 | +[project.scripts] |
| 40 | +embedding-server = "embedding_sever.main:main" | ||
| 41 | +#task-server = "task_server.main:main" |
src/embedding_sever/api/__init__.py
0 → 100644
| 1 | -from typing import List, Optional, Literal, Union, Dict, Any, Annotated | 1 | +from typing import List, Optional, Literal, Union, Dict, Any |
| 2 | 2 | ||
| 3 | from fastapi import APIRouter, Depends | 3 | from fastapi import APIRouter, Depends |
| 4 | import numpy | 4 | import numpy |
| 5 | from pydantic import BaseModel, Field, TypeAdapter | 5 | from pydantic import BaseModel, Field, TypeAdapter |
| 6 | 6 | ||
| 7 | -from api.resp_bean import RespBean, success | 7 | +from embedding_sever.api.resp_bean import RespBean, success |
| 8 | 8 | ||
| 9 | router = APIRouter() | 9 | router = APIRouter() |
| 10 | 10 | ||
| @@ -89,8 +89,8 @@ class SearchResponseData(BaseModel): | @@ -89,8 +89,8 @@ class SearchResponseData(BaseModel): | ||
| 89 | 89 | ||
| 90 | 90 | ||
| 91 | # ============== 接口定义 ============== | 91 | # ============== 接口定义 ============== |
| 92 | -from service.data_service import DataService | ||
| 93 | -from service import get_data_service | 92 | +from embedding_sever.service.data_service import DataService |
| 93 | +from embedding_sever.service import get_data_service | ||
| 94 | 94 | ||
| 95 | 95 | ||
| 96 | @router.put("/{type}/put", response_model=RespBean, tags=["数据服务"], summary="写入数据") | 96 | @router.put("/{type}/put", response_model=RespBean, tags=["数据服务"], summary="写入数据") |
| 1 | from fastapi.middleware.cors import CORSMiddleware | 1 | from fastapi.middleware.cors import CORSMiddleware |
| 2 | from starlette.responses import JSONResponse | 2 | from starlette.responses import JSONResponse |
| 3 | -from api.http_log import LoggingMiddleware | 3 | +from embedding_sever.api.http_log import LoggingMiddleware |
| 4 | from fastapi import FastAPI | 4 | from fastapi import FastAPI |
| 5 | -from api.router import api_router | ||
| 6 | -from config import settings | 5 | +from embedding_sever.api.router import api_router |
| 6 | +from embedding_sever.config import settings | ||
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | def config_fastapi(fastapi_app: FastAPI): | 9 | def config_fastapi(fastapi_app: FastAPI): |
| @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) | @@ -6,7 +6,7 @@ logger = logging.getLogger(__name__) | ||
| 6 | from fastapi import Request | 6 | from fastapi import Request |
| 7 | from starlette.middleware.base import BaseHTTPMiddleware | 7 | from starlette.middleware.base import BaseHTTPMiddleware |
| 8 | from starlette.responses import StreamingResponse | 8 | from starlette.responses import StreamingResponse |
| 9 | -from config import settings | 9 | +from embedding_sever.config import settings |
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | class LoggingMiddleware(BaseHTTPMiddleware): | 12 | class LoggingMiddleware(BaseHTTPMiddleware): |
| 1 | from fastapi import APIRouter | 1 | from fastapi import APIRouter |
| 2 | -from config import settings | ||
| 3 | -from api.data_router import router as data_router | 2 | +from embedding_sever.config import settings |
| 3 | +from embedding_sever.api.data_router import router as data_router | ||
| 4 | 4 | ||
| 5 | api_router = APIRouter(prefix=settings.url_prefix) | 5 | api_router = APIRouter(prefix=settings.url_prefix) |
| 6 | 6 |
src/embedding_sever/cfg/config.dev.yaml
0 → 100644
| 1 | +app_name: "Embedding Service" | ||
| 2 | +app_version: "1.0.0" | ||
| 3 | +port: 8000 | ||
| 4 | +debug: false | ||
| 5 | +url_prefix: "/aigc-embedding/api" | ||
| 6 | + | ||
| 7 | +db_es_enable: true | ||
| 8 | +db_es_url: "http://192.168.0.14:9200" | ||
| 9 | + | ||
| 10 | +#db_postgres_enable: false | ||
| 11 | +#db_postgres_url: "postgresql://postgres:postgres@localhost:5432/postgres" |
src/embedding_sever/cfg/config.yaml
0 → 100644
| 1 | +app_name: "Embedding Service" | ||
| 2 | +app_version: "1.0.0" | ||
| 3 | +port: 8000 | ||
| 4 | +debug: false | ||
| 5 | +url_prefix: "/aigc-embedding/api" | ||
| 6 | + | ||
| 7 | +db_es_enable: true | ||
| 8 | +db_es_url: "http://localhost:9200" | ||
| 9 | + | ||
| 10 | +#db_postgres_enable: false | ||
| 11 | +#db_postgres_url: "postgresql://postgres:postgres@localhost:5432/postgres" |
| @@ -2,7 +2,7 @@ from functools import lru_cache | @@ -2,7 +2,7 @@ from functools import lru_cache | ||
| 2 | 2 | ||
| 3 | from elasticsearch import AsyncElasticsearch | 3 | from elasticsearch import AsyncElasticsearch |
| 4 | 4 | ||
| 5 | -from config import settings | 5 | +from embedding_sever.config import settings |
| 6 | from .data_dao import DataDao | 6 | from .data_dao import DataDao |
| 7 | 7 | ||
| 8 | es_client = None | 8 | es_client = None |
| @@ -2,8 +2,7 @@ | @@ -2,8 +2,7 @@ | ||
| 2 | 2 | ||
| 3 | from typing import Any, Optional | 3 | from typing import Any, Optional |
| 4 | 4 | ||
| 5 | -from config import settings | ||
| 6 | -from db.base import VectorDBClient | 5 | +from embedding_sever.db.base import VectorDBClient |
| 7 | 6 | ||
| 8 | 7 | ||
| 9 | class ElasticsearchClient(VectorDBClient): | 8 | class ElasticsearchClient(VectorDBClient): |
| @@ -11,9 +11,9 @@ logger = get_logger(__name__) | @@ -11,9 +11,9 @@ logger = get_logger(__name__) | ||
| 11 | from contextlib import asynccontextmanager | 11 | from contextlib import asynccontextmanager |
| 12 | from typing import AsyncGenerator | 12 | from typing import AsyncGenerator |
| 13 | from fastapi import FastAPI | 13 | from fastapi import FastAPI |
| 14 | -from api.http_config import config_fastapi | ||
| 15 | -from config import settings | ||
| 16 | -from db import connect as db_client_connect, disconnect as db_client_disconnect | 14 | +from embedding_sever.api.http_config import config_fastapi |
| 15 | +from embedding_sever.config import settings | ||
| 16 | +from embedding_sever.db import connect as db_client_connect, disconnect as db_client_disconnect | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | @asynccontextmanager | 19 | @asynccontextmanager |
| @@ -48,7 +48,8 @@ app = FastAPI( | @@ -48,7 +48,8 @@ app = FastAPI( | ||
| 48 | ) | 48 | ) |
| 49 | config_fastapi(app) | 49 | config_fastapi(app) |
| 50 | 50 | ||
| 51 | -if __name__ == "__main__": | 51 | +def main(): |
| 52 | + """应用入口函数.""" | ||
| 52 | import uvicorn | 53 | import uvicorn |
| 53 | 54 | ||
| 54 | logger.info(f'docs_url: http://127.0.0.1:{settings.port}/docs') | 55 | logger.info(f'docs_url: http://127.0.0.1:{settings.port}/docs') |
| @@ -59,3 +60,7 @@ if __name__ == "__main__": | @@ -59,3 +60,7 @@ if __name__ == "__main__": | ||
| 59 | reload=settings.debug, | 60 | reload=settings.debug, |
| 60 | log_config=None | 61 | log_config=None |
| 61 | ) | 62 | ) |
| 63 | + | ||
| 64 | + | ||
| 65 | +if __name__ == "__main__": | ||
| 66 | + main() |
This diff could not be displayed because it is too large.
-
Please register or login to post a comment