Metadata-Version: 2.4
Name: infomankit
Version: 0.3.0
Summary: Infoman base library - A comprehensive toolkit for modern Python applications with dual ORM support
Project-URL: Homepage, https://github.com/infoman-lib/infoman-pykit
Project-URL: Documentation, https://github.com/infoman-lib/infoman-pykit
Project-URL: Repository, https://github.com/infoman-lib/infoman-pykit.git
Project-URL: Issues, https://github.com/infoman-lib/infoman-pykit/issues
Project-URL: Changelog, https://github.com/infoman-lib/infoman-pykit/blob/main/CHANGELOG.md
Author-email: Louis <louishwh@gmail.com>
Maintainer-email: Louis <louishwh@gmail.com>
License: MIT
Keywords: async,database,fastapi,llm,toolkit
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: AsyncIO
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.11
Requires-Dist: aiohttp~=3.13.2
Requires-Dist: cryptography~=46.0.3
Requires-Dist: dotenv==0.9.9
Requires-Dist: httpx~=0.28.1
Requires-Dist: loguru~=0.7.0
Requires-Dist: psutil~=7.1.3
Requires-Dist: pydantic-settings>=2.12.0
Requires-Dist: pydantic~=2.12.0
Requires-Dist: pyjwt~=2.10.0
Requires-Dist: pyyaml~=6.0.2
Provides-Extra: aikit
Requires-Dist: litellm~=1.75.0; extra == 'aikit'
Requires-Dist: qdrant-client~=1.16.2; extra == 'aikit'
Provides-Extra: cache
Requires-Dist: fastapi-cache2~=0.2.2; extra == 'cache'
Requires-Dist: redis[hiredis]~=7.1.0; extra == 'cache'
Provides-Extra: database
Requires-Dist: aiosqlite~=0.22.0; extra == 'database'
Requires-Dist: asyncmy~=0.2.10; extra == 'database'
Requires-Dist: asyncpg~=0.31.0; extra == 'database'
Requires-Dist: tortoise-orm~=0.25.2; extra == 'database'
Provides-Extra: database-alchemy
Requires-Dist: aiosqlite~=0.22.0; extra == 'database-alchemy'
Requires-Dist: alembic~=1.14.0; extra == 'database-alchemy'
Requires-Dist: asyncmy~=0.2.10; extra == 'database-alchemy'
Requires-Dist: asyncpg~=0.31.0; extra == 'database-alchemy'
Requires-Dist: sqlalchemy[asyncio]~=2.0.36; extra == 'database-alchemy'
Provides-Extra: database-full
Requires-Dist: aiosqlite~=0.22.0; extra == 'database-full'
Requires-Dist: alembic~=1.14.0; extra == 'database-full'
Requires-Dist: asyncmy~=0.2.10; extra == 'database-full'
Requires-Dist: asyncpg~=0.31.0; extra == 'database-full'
Requires-Dist: sqlalchemy[asyncio]~=2.0.36; extra == 'database-full'
Requires-Dist: tortoise-orm~=0.25.2; extra == 'database-full'
Provides-Extra: datakit
Requires-Dist: aiosqlite~=0.22.0; extra == 'datakit'
Requires-Dist: asyncmy~=0.2.10; extra == 'datakit'
Requires-Dist: asyncpg~=0.31.0; extra == 'datakit'
Requires-Dist: fastapi-cache2~=0.2.2; extra == 'datakit'
Requires-Dist: qdrant-client~=1.16.2; extra == 'datakit'
Requires-Dist: redis[hiredis]~=7.1.0; extra == 'datakit'
Requires-Dist: tortoise-orm~=0.25.2; extra == 'datakit'
Provides-Extra: dev
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pre-commit>=3.6.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.14.10; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material~=9.0.0; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'docs'
Requires-Dist: mkdocs~=1.6.1; extra == 'docs'
Provides-Extra: full
Requires-Dist: aiofiles~=25.1.0; extra == 'full'
Requires-Dist: aiosqlite~=0.22.0; extra == 'full'
Requires-Dist: asyncmy~=0.2.10; extra == 'full'
Requires-Dist: asyncpg~=0.31.0; extra == 'full'
Requires-Dist: fastapi-cache2~=0.2.2; extra == 'full'
Requires-Dist: fastapi~=0.127.0; extra == 'full'
Requires-Dist: granian~=2.6.0; extra == 'full'
Requires-Dist: litellm~=1.75.0; extra == 'full'
Requires-Dist: nats-py~=2.10.0; extra == 'full'
Requires-Dist: orjson~=3.11.5; extra == 'full'
Requires-Dist: prometheus-client~=0.23.1; extra == 'full'
Requires-Dist: prometheus-fastapi-instrumentator~=7.1.0; extra == 'full'
Requires-Dist: qdrant-client~=1.16.2; extra == 'full'
Requires-Dist: redis[hiredis]~=7.1.0; extra == 'full'
Requires-Dist: tortoise-orm~=0.25.2; extra == 'full'
Provides-Extra: full-enhanced
Requires-Dist: aiofiles~=25.1.0; extra == 'full-enhanced'
Requires-Dist: aiosqlite~=0.22.0; extra == 'full-enhanced'
Requires-Dist: alembic~=1.14.0; extra == 'full-enhanced'
Requires-Dist: asyncmy~=0.2.10; extra == 'full-enhanced'
Requires-Dist: asyncpg~=0.31.0; extra == 'full-enhanced'
Requires-Dist: fastapi-cache2~=0.2.2; extra == 'full-enhanced'
Requires-Dist: fastapi~=0.127.0; extra == 'full-enhanced'
Requires-Dist: granian~=2.6.0; extra == 'full-enhanced'
Requires-Dist: litellm~=1.75.0; extra == 'full-enhanced'
Requires-Dist: nats-py~=2.10.0; extra == 'full-enhanced'
Requires-Dist: orjson~=3.11.5; extra == 'full-enhanced'
Requires-Dist: prometheus-client~=0.23.1; extra == 'full-enhanced'
Requires-Dist: prometheus-fastapi-instrumentator~=7.1.0; extra == 'full-enhanced'
Requires-Dist: qdrant-client~=1.16.2; extra == 'full-enhanced'
Requires-Dist: redis[hiredis]~=7.1.0; extra == 'full-enhanced'
Requires-Dist: sqlalchemy[asyncio]~=2.0.36; extra == 'full-enhanced'
Requires-Dist: tortoise-orm~=0.25.2; extra == 'full-enhanced'
Provides-Extra: llm
Requires-Dist: litellm~=1.75.0; extra == 'llm'
Provides-Extra: messaging
Requires-Dist: nats-py~=2.10.0; extra == 'messaging'
Provides-Extra: test
Requires-Dist: factory-boy>=3.3.0; extra == 'test'
Requires-Dist: httpx>=0.25.0; extra == 'test'
Requires-Dist: mypy>=1.8.0; extra == 'test'
Requires-Dist: pre-commit>=3.6.0; extra == 'test'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'test'
Requires-Dist: pytest-benchmark>=4.0.0; extra == 'test'
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
Requires-Dist: pytest>=8.0.0; extra == 'test'
Requires-Dist: ruff>=0.14.10; extra == 'test'
Provides-Extra: vector
Requires-Dist: qdrant-client~=1.16.2; extra == 'vector'
Provides-Extra: web
Requires-Dist: aiofiles~=25.1.0; extra == 'web'
Requires-Dist: fastapi~=0.127.0; extra == 'web'
Requires-Dist: granian~=2.6.0; extra == 'web'
Requires-Dist: orjson~=3.11.5; extra == 'web'
Requires-Dist: prometheus-client~=0.23.1; extra == 'web'
Requires-Dist: prometheus-fastapi-instrumentator~=7.1.0; extra == 'web'
Provides-Extra: webapp
Requires-Dist: aiofiles~=25.1.0; extra == 'webapp'
Requires-Dist: fastapi-cache2~=0.2.2; extra == 'webapp'
Requires-Dist: fastapi~=0.127.0; extra == 'webapp'
Requires-Dist: granian~=2.6.0; extra == 'webapp'
Requires-Dist: orjson~=3.11.5; extra == 'webapp'
Requires-Dist: prometheus-client~=0.23.1; extra == 'webapp'
Requires-Dist: prometheus-fastapi-instrumentator~=7.1.0; extra == 'webapp'
Requires-Dist: redis[hiredis]~=7.1.0; extra == 'webapp'
Description-Content-Type: text/markdown

# infomankit

> 现代化 Python/AI 服务脚手架与工具箱。封装了配置加载、日志、FastAPI 服务、LLM 调用、缓存、消息队列、加解密等常用能力，帮助你快速把 idea 变成可部署的生产级服务。

## ✨ v0.3.0 新特性
- 🎉 **双 ORM 支持**：同时支持 Tortoise ORM 和 SQLAlchemy 2.0，灵活选择
- 🔄 **100% 向前兼容**：现有项目无需修改任何代码
- 🚀 **性能提升**：SQLAlchemy 2.0 带来 20-40% 的性能提升
- 📦 **渐进式迁移**：新功能用 SQLAlchemy，旧代码保持 Tortoise，平滑过渡

## 特性亮点
- **统一配置体系**：`.env` + `config.py` 支持多环境加载，覆盖应用、数据库、缓存、LLM、MQ、向量库等关键参数。
- **FastAPI 微服务基线**：开箱即可运行的 `infoman.service.app`，内置 CORS、GZip、链路日志、中英文错误码、请求 ID、健康/监控接口。
- **灵活的 ORM 选择**：支持 `Tortoise ORM`（简单易用）和 `SQLAlchemy 2.0`（强大性能），可单独或同时使用。
- **异步基础设施**：MySQL/PostgreSQL、Redis 缓存、Litellm、NATS、Qdrant/Milvus 的集成入口，易于按需扩展。
- **AI/LLM 辅助**：`infoman.llm.LLM` 提供问答、对话、流式输出、翻译、总结、代码审查等常用封装。
- **实用工具集**：日志系统、缓存/重试/计时装饰器、AES/RSA、异步 HTTP、文本结构化提取、Feishu Bot 等常用基建。
- **细粒度模块化**：可单独安装 `web`、`database`、`database-alchemy`、`llm`、`vector`、`messaging` 等 extra，仅引入所需依赖。

## 目录速览
```
infoman/
├── config/            # 环境变量加载与全局配置
├── llm/               # Litellm 包装，提供 Chat/Stream/API
├── service/
│   ├── app.py         # FastAPI Application 入口
│   ├── routers/           # 健康检查与监控 API
│   ├── core/            # 事件、响应、认证
│   ├── infrastructure/  # 数据库，消息队列
│   ├── exception/     # 错误码、异常处理
│   ├── middleware/    # Logging、RequestID、RateLimit、中间件基类
│   ├── models/        # Tortoise 模型基类 & Embedding 配置
│   └── utils/         # redis 缓存装饰器、解析/转换
└── utils/
    ├── log/           # Loguru 配置与上下文
    ├── decorators/    # cache、retry、timing 等装饰器
    ├── encryption/    # AES/RSA/ECC
    ├── http/          # aiohttp 客户端、请求信息提取
    ├── notification/  # 飞书机器人通知
    └── text/          # JSON 结构提取等
```

## 安装
```bash
# Python >= 3.11
pip install -U infomankit

# 基础 Web 服务
pip install -U "infomankit[web]"

# 完整功能（使用 Tortoise ORM，100% 向前兼容）
pip install -U "infomankit[full]"

# 完整功能增强版（同时支持 Tortoise + SQLAlchemy）
pip install -U "infomankit[full-enhanced]"
```

常用 extra 组合：

| Extra              | 说明                                     |
|--------------------|----------------------------------------|
| `web`              | FastAPI/Granian/orjson                 |
| `database`         | Tortoise ORM（默认，向前兼容）                |
| `database-alchemy` | SQLAlchemy 2.0（新增，高性能）               |
| `database-full`    | 同时支持 Tortoise + SQLAlchemy            |
| `cache`            | Redis + fastapi-cache2                |
| `llm`              | Litellm                                |
| `vector`           | Qdrant                                 |
| `messaging`        | NATS                                   |
| `webapp`           | `web + cache`                          |
| `aikit`            | `llm + vector`                         |
| `full`             | 完整功能（使用 Tortoise）                    |
| `full-enhanced`    | 完整功能增强版（Tortoise + SQLAlchemy）      |

本地开发推荐：

```bash
git clone https://github.com/yourusername/infoman-pykit.git
cd infomankit
pip install -e ".[dev,full]"   # 安装所有依赖和 lint/test 工具
```

## 快速上手

### 1. 配置环境变量
创建 `.env.dev`，并设置 `ENV=dev` (默认 dev)。可根据 `infoman/config/config.py` 填写常用变量：

```bash
APP_NAME=Infoman Service
APP_HOST=0.0.0.0
APP_PORT=8808
MYSQL_HOST=127.0.0.1
MYSQL_DB=infoman
MYSQL_USER=root
MYSQL_PASSWORD=secret
REDIS_HOST=127.0.0.1
QDRANT_HOST=127.0.0.1
LLM_PROXY=litellm_proxy
JWT_SECRET_KEY=change-me
```

运行时会依次加载 `.env` 与 `.env.{ENV}`，缺省值可在 `config.py` 中找到。

### 2. 启动 FastAPI 服务
```bash
export ENV=dev
uvicorn infoman.service.app:application --host ${APP_HOST:-0.0.0.0} --port ${APP_PORT:-8808} --reload
# or
python -m infoman.service.launch --mode gunicorn
```

应用启动后默认提供：
- `/api/health`：健康检查，返回 `{code:200}`。
- `/api/monitor`：进程 & 系统指标、环境信息。
- 启动事件中会自动注册 MySQL、Redis 缓存、NATS、Qdrant 等（根据配置是否填写）。

### 3. 调用 LLM
```python
import asyncio
from infoman.llm import LLM

async def main():
    resp = await LLM.ask(
        model="gpt-4o-mini",
        prompt="请用一句话介绍 infoman-pykit。",
        system_prompt="You are a concise assistant."
    )
    if resp.success:
        print(resp.content, resp.total_tokens)

asyncio.run(main())
```

- `LLM.ask/chat/stream` 会自动补全 `LLM_PROXY` 前缀并返回 token 统计。
- `LLM.quick_*` 返回字符串，`LLM.translate/summarize/code_review` 内置常用 system prompt。

### 4. 使用 Redis 缓存装饰器
```python
from pydantic import BaseModel
from infoman.service.utils.cache import redis_cache

class ConfigSchema(BaseModel):
    key: str
    value: str

class ConfigService:
    @redis_cache(prefix="config", ttl=600)
    async def get_config(self, request, key: str) -> ConfigSchema:
        # request.app.state.redis_client 将被装饰器自动读取
        ...
```

返回值可以是 `BaseModel`、`list[BaseModel]` 或普通 `dict`，装饰器会自动序列化/反序列化。

### 5. 消息队列与事件路由

```python
from infoman.service.infrastructure.mq.nats import event_router


@event_router.on("topic.user.created", queue="worker")
async def handle_user_created(msg, nats_cli):
    payload = msg.data.decode()
    ...

# 启动时在 startup 事件中执行：
# await event_router.register(app.state.nats_client)
```

`NATSClient` 支持 `publish/request/subscribe/close`，并在 `events.startup` 中自动连接（配置 `NATS_SERVER` 后生效）。

## 日志与中间件
- `infoman.utils.log.logger` 基于 Loguru，自动创建多种文件（all/info/error/debug）并支持 JSON 日志、请求上下文（RequestID）。
- `LoggingMiddleware`：记录请求耗时、客户端信息；`RequestIDMiddleware` 为每次请求注入 `X-Request-ID`。
- `RateLimitMiddleware`：IP/用户/路径多策略限流，内存或 Redis 持久化。
- `BaseMiddleware` 为自定义中间件提供 session / 处理耗时写入示例。

## 统一错误与响应
- `infoman.service.exception.error` 定义系统、请求、数据库、业务、安全、外部服务等错误码枚举，可中英文提示。
- `AppException` + `handler.py` 将数据库、Pydantic、HTTP 异常统一转换为 `{code, message, details}`。
- `infoman.service.core.response.success/failed` 提供标准响应结构。

## 更多工具箱
- **装饰器**：`retry`(支持 async/sync 指数退避)、`cache`(内存缓存)、`timing`(执行耗时)。
- **加密**：AES(自动填充/随机 IV)、RSA(4096/自定义序列化)。
- **HTTP Client**：`HttpAsyncClient` 支持表单/JSON/文件上传，返回 `HttpResult`。
- **文本处理**：`utils.text.extractor.extract_json_from_string` 可从非结构化文本中提取 JSON。
- **通知**：`notification.feishu.RobotManager` 发送飞书机器人消息。
- **Embedding 配置**：`service.models.type.embed` 统一管理不同向量模型的维度/长度、集合命名。

## 配置清单速查

| 分类         | 重点变量 |
|--------------|----------|
| 应用         | `APP_NAME`, `APP_HOST`, `APP_PORT`, `APP_BASE_URI`, `APP_DEBUG` |
| 安全         | `JWT_SECRET_KEY`, `JWT_ALGORITHM`, `JWT_ACCESS_TOKEN_EXPIRE_MINUTES`, `OAUTH2_REDIRECT_URL` |
| 数据库       | `MYSQL_HOST`, `MYSQL_PORT`, `MYSQL_DB`, `MYSQL_USER`, `MYSQL_PASSWORD`, `MYSQL_TABLE_MODELS` |
| 缓存 / Redis | `REDIS_HOST`, `REDIS_PORT`, `REDIS_DB`, `REDIS_PASSWORD` |
| 向量数据库   | `QDRANT_HOST`/`API_KEY`/`HTTP_PORT`/`GRPC_PORT`、`MILVUS_HOST` 等（Milvus 需实现 `AsyncMilvusClient`） |
| MQ           | `NATS_SERVER`（逗号分隔多实例）, `NATS_NAME` |
| LLM          | `LLM_PROXY`（litellm 代理地址） |
| 日志         | `LOG_LEVEL`, `LOG_FORMAT`, `LOG_DIR`, `LOG_RETENTION`, `LOG_ENABLE_*` |

## 开发 & 测试
```bash
# Lint / 格式化
ruff check infoman
black infoman
isort infoman

# 类型检查
mypy infoman

# 测试
pytest
```

## 🔀 ORM 选择指南

从 v0.3.0 开始，infomankit 支持两种 ORM：

### Tortoise ORM（默认）
**适合**：简单 CRUD、快速开发、学习成本低
```python
from infoman.service.models.base import TimestampMixin
from tortoise import fields

class User(TimestampMixin):
    name = fields.CharField(max_length=100)

# 直接使用
user = await User.create(name="Alice")
```

### SQLAlchemy 2.0（高性能）
**适合**：复杂查询、高性能需求、工业级项目
```python
from infoman.service.models.base import AlchemyBase, AlchemyTimestampMixin
from sqlalchemy import String
from sqlalchemy.orm import Mapped, mapped_column

class User(AlchemyBase, AlchemyTimestampMixin):
    __tablename__ = "users"
    name: Mapped[str] = mapped_column(String(100))

# 使用仓储模式
from infoman.service.models.base import create_repository
user_repo = create_repository(User)
user = await user_repo.create(name="Alice")
```

**详细迁移指南**: 👉 [doc/MIGRATION_TO_SQLALCHEMY.md](./doc/MIGRATION_TO_SQLALCHEMY.md)

---

## License
MIT License © Infoman Contributors
