From 52db191cc68e7364c791a0caaf90fb8a7b4203ba Mon Sep 17 00:00:00 2001 From: lroyia Date: Wed, 11 Feb 2026 17:23:48 +0800 Subject: [PATCH] Initial commit: Add project structure with GLM OCR demo --- .env.example | 14 +++++ .gitignore | 130 +++++++++++++++++++++++++++++++++++++++ README.md | 50 +++++++++++++++ requirements.txt | 23 +++++++ src/__init__.py | 1 + src/api/__init__.py | 1 + src/core/__init__.py | 1 + src/core/config.py | 21 +++++++ src/core/database.py | 22 +++++++ src/main.py | 44 +++++++++++++ src/models/__init__.py | 1 + src/services/__init__.py | 1 + tests/__init__.py | 1 + tests/test_main.py | 19 ++++++ 14 files changed, 329 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 README.md create mode 100644 requirements.txt create mode 100644 src/__init__.py create mode 100644 src/api/__init__.py create mode 100644 src/core/__init__.py create mode 100644 src/core/config.py create mode 100644 src/core/database.py create mode 100644 src/main.py create mode 100644 src/models/__init__.py create mode 100644 src/services/__init__.py create mode 100644 tests/__init__.py create mode 100644 tests/test_main.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3bbe1b3 --- /dev/null +++ b/.env.example @@ -0,0 +1,14 @@ +# Application +APP_NAME=GLM OCR Demo +APP_VERSION=0.1.0 +DEBUG=true + +# Server +HOST=0.0.0.0 +PORT=8000 + +# Database +DATABASE_URL=sqlite:///./app.db + +# Security +SECRET_KEY=your-secret-key-here-change-in-production \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34ed11d --- /dev/null +++ b/.gitignore @@ -0,0 +1,130 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +*.manifest +*.spec + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +Pipfile.lock + +# PEP 582 +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ac5ab6d --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# GLM OCR Demo + +基于 Python 的 Web 项目,使用 FastAPI 框架。 + +## 开发环境设置 + +1. 创建虚拟环境: +```bash +python -m venv venv +``` + +2. 激活虚拟环境: +```bash +# Windows +venv\Scripts\activate + +# Linux/Mac +source venv/bin/activate +``` + +3. 安装依赖: +```bash +pip install -r requirements.txt +``` + +4. 复制环境变量文件: +```bash +copy .env.example .env +``` + +5. 运行开发服务器: +```bash +python -m uvicorn src.main:app --reload --host 0.0.0.0 --port 8000 +``` + +## 项目结构 + +``` +glmocrdemo/ +├── src/ +│ ├── api/ # API 路由 +│ ├── models/ # 数据模型 +│ ├── services/ # 业务逻辑 +│ ├── core/ # 核心配置 +│ └── main.py # 应用入口 +├── tests/ # 测试文件 +├── .env.example # 环境变量示例 +├── requirements.txt # 项目依赖 +└── README.md # 项目说明 +``` \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..5487565 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,23 @@ +# Web Framework +fastapi==0.115.0 +uvicorn[standard]==0.32.0 + +# Database +sqlalchemy==2.0.35 +alembic==1.14.0 + +# Environment variables +python-dotenv==1.0.1 + +# Validation +pydantic==2.9.2 +pydantic-settings==2.6.0 + +# CORS +python-multipart==0.0.12 + +# HTTP client +httpx==0.27.2 + +# Utils +orjson==3.10.12 \ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..ee8c01e --- /dev/null +++ b/src/__init__.py @@ -0,0 +1 @@ +# src package \ No newline at end of file diff --git a/src/api/__init__.py b/src/api/__init__.py new file mode 100644 index 0000000..699e93e --- /dev/null +++ b/src/api/__init__.py @@ -0,0 +1 @@ +# api package \ No newline at end of file diff --git a/src/core/__init__.py b/src/core/__init__.py new file mode 100644 index 0000000..5d9df9c --- /dev/null +++ b/src/core/__init__.py @@ -0,0 +1 @@ +# core package \ No newline at end of file diff --git a/src/core/config.py b/src/core/config.py new file mode 100644 index 0000000..372d24d --- /dev/null +++ b/src/core/config.py @@ -0,0 +1,21 @@ +from pydantic_settings import BaseSettings + + +class Settings(BaseSettings): + app_name: str = "GLM OCR Demo" + app_version: str = "0.1.0" + debug: bool = True + + host: str = "0.0.0.0" + port: int = 8000 + + database_url: str = "sqlite:///./app.db" + + secret_key: str = "your-secret-key-here" + + class Config: + env_file = ".env" + case_sensitive = False + + +settings = Settings() \ No newline at end of file diff --git a/src/core/database.py b/src/core/database.py new file mode 100644 index 0000000..f00322d --- /dev/null +++ b/src/core/database.py @@ -0,0 +1,22 @@ +from sqlalchemy import create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker + +from src.core.config import settings + +engine = create_engine( + settings.database_url, + connect_args={"check_same_thread": False} if "sqlite" in settings.database_url else {} +) + +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() + + +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..50af5f2 --- /dev/null +++ b/src/main.py @@ -0,0 +1,44 @@ +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware + +from src.core.config import settings + +app = FastAPI( + title=settings.app_name, + version=settings.app_version, + debug=settings.debug +) + +# CORS middleware +app.add_middleware( + CORSMiddleware, + allow_origins=["*"] if settings.debug else [], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + + +@app.get("/") +async def root(): + return { + "app": settings.app_name, + "version": settings.app_version, + "status": "running" + } + + +@app.get("/health") +async def health_check(): + return {"status": "healthy"} + + +if __name__ == "__main__": + import uvicorn + + uvicorn.run( + "src.main:app", + host=settings.host, + port=settings.port, + reload=settings.debug + ) \ No newline at end of file diff --git a/src/models/__init__.py b/src/models/__init__.py new file mode 100644 index 0000000..853226e --- /dev/null +++ b/src/models/__init__.py @@ -0,0 +1 @@ +# models package \ No newline at end of file diff --git a/src/services/__init__.py b/src/services/__init__.py new file mode 100644 index 0000000..7e29b49 --- /dev/null +++ b/src/services/__init__.py @@ -0,0 +1 @@ +# services package \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..d4308e6 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# tests package \ No newline at end of file diff --git a/tests/test_main.py b/tests/test_main.py new file mode 100644 index 0000000..6f4af59 --- /dev/null +++ b/tests/test_main.py @@ -0,0 +1,19 @@ +from fastapi.testclient import TestClient +from src.main import app + +client = TestClient(app) + + +def test_root(): + response = client.get("/") + assert response.status_code == 200 + data = response.json() + assert "app" in data + assert "version" in data + assert data["status"] == "running" + + +def test_health_check(): + response = client.get("/health") + assert response.status_code == 200 + assert response.json() == {"status": "healthy"} \ No newline at end of file