Metadata-Version: 2.4
Name: llmdog
Version: 0.0.3
Summary: 轻量级 LLM 命令行工具与 Python 库，支持兼容 OpenAI Chat Completions 格式的任意 API 端点。
Project-URL: Homepage, https://github.com/llmdog/llmdog
Project-URL: Bug Tracker, https://github.com/llmdog/llmdog/issues
Author: Chandler
License-Expression: MIT
Keywords: ai,chatbot,cli,llm,openai
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: pyyaml>=6.0
Requires-Dist: requests>=2.28.0
Requires-Dist: rich>=13.0.0
Requires-Dist: tenacity>=8.0.0
Requires-Dist: typer>=0.12.0
Requires-Dist: typing-extensions>=4.0.0
Provides-Extra: dev
Requires-Dist: black>=23.0; extra == 'dev'
Requires-Dist: isort>=5.0; extra == 'dev'
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: types-pyyaml; extra == 'dev'
Requires-Dist: types-requests; extra == 'dev'
Description-Content-Type: text/markdown

# llmdog

轻量级 LLM 命令行工具与 Python 库，支持兼容 OpenAI Chat Completions 格式的任意 API 端点。

---

## 功能特性

- **命令行工具**：`llmdog chat --content "你好"` 一行命令发起对话
- **Python 库**：`from llmdog import chat` 直接在代码中调用
- **多配置来源**：支持环境变量、YAML/JSON 配置文件、运行时参数，优先级明确
- **可扩展后端**：基于抽象基类 + 注册表模式，无需修改核心代码即可接入新后端
- **生产级重试**：使用 tenacity 实现指数退避重试，应对网络抖动
- **Rich 美化输出**：彩色终端输出、旋转进度条、配置表格，Rich 未安装时自动降级
- **友好错误提示**：结构化日志 + 详细错误描述，快速定位问题

---

## 安装和环境配置

### 从 PyPI 安装

```bash
pip install llmdog
```


### 环境要求

- Python >= 3.9
- 依赖：`requests`, `tenacity`, `typer`, `rich`, `pyyaml`, `typing-extensions`

### 配置 API Key

**方式一：环境变量（推荐）**

```bash
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
```

**方式二：配置文件**

在家目录或项目根目录创建 `.llmdog.yaml`：

```yaml
api_key: sk-xxxxxxxxxxxxxxxxxxxxxxxx
model: qwen2.5-coder-32b-instruct
timeout: 120
```

---

## 使用示例和代码片段

### 命令行使用

```bash
# 基础对话
llmdog chat --content "你好，你是谁？"

# 指定模型
llmdog chat --content "帮我写一个快速排序算法" --model qwen3-72b-instruct

# 指定超时时间
llmdog chat --content "分析这段代码" --timeout 60

# 使用指定配置文件
llmdog chat --content "测试" --config-file ~/.my_llm.yaml

# 查看当前生效配置
llmdog config show

# 查看版本
llmdog --version

# 查看帮助
llmdog --help
llmdog chat --help
```

### Python 库调用

**最简调用（依赖环境变量 `LLM_API_KEY`）：**

```python
from llmdog import chat

reply = chat("你好，你是谁？")
print(reply)
```

**指定模型和超时：**

```python
from llmdog import chat

reply = chat(
    "帮我写一个 Python 装饰器实现函数计时",
    model="qwen3-72b-instruct",
    timeout=60,
)
print(reply)
```

**使用 Config 对象：**

```python
from llmdog import chat
from llmdog.config import load_config

cfg = load_config(
    api_key="sk-xxxxxxxxxxxxxxxxxxxxxxxx",
    model="qwen2.5-coder-32b-instruct",
    timeout=120,
)

reply = chat("解释一下 Python GIL", config=cfg)
print(reply)
```

**直接使用后端类：**

```python
from llmdog.backends.llmapi import LlmApiBackend

backend = LlmApiBackend(
    api_key="sk-xxx",
    api_url="https://your-custom-endpoint/v1/chat/completions",
    default_model="your-model",
)
reply = backend.chat("你好")
print(reply)
```

---

### 多服务商配置示例

llmdog 使用兼容 OpenAI Chat Completions 格式的统一接口，支持任意符合该格式的 LLM 服务商。
以下是主流服务商的完整配置参考。

---

#### DeepSeek

| 参数 | 值 |
|------|----|
| `api_url` | `https://api.deepseek.com/v1/chat/completions` |
| `api_key` | 在 [DeepSeek 控制台](https://platform.deepseek.com/) 申请，格式 `sk-...` |
| 模型名称 | `deepseek-chat`（通用）、`deepseek-reasoner`（推理增强）|

**环境变量配置：**

```bash
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
export LLM_API_URL="https://api.deepseek.com/v1/chat/completions"
export LLM_MODEL="deepseek-chat"
```

**配置文件 `~/.llmdog.yaml`：**

```yaml
api_key: sk-xxxxxxxxxxxxxxxxxxxxxxxx
api_url: https://api.deepseek.com/v1/chat/completions
model: deepseek-chat
timeout: 60
verify_ssl: true
```

**命令行调用：**

```bash
# 使用环境变量配置后直接调用
llmdog chat --content "用 Python 实现二叉树的层序遍历"

# 运行时指定所有参数
llmdog chat \
  --content "用 Python 实现二叉树的层序遍历" \
  --api-key sk-xxxxxxxxxxxxxxxxxxxxxxxx \
  --api-url https://api.deepseek.com/v1/chat/completions \
  --model deepseek-chat
```

**Python 调用：**

```python
from llmdog import chat
from llmdog.config import load_config

cfg = load_config(
    api_key="sk-xxxxxxxxxxxxxxxxxxxxxxxx",
    api_url="https://api.deepseek.com/v1/chat/completions",
    model="deepseek-chat",
    timeout=60,
    verify_ssl=True,
)
reply = chat("用 Python 实现二叉树的层序遍历", config=cfg)
print(reply)
```

---

#### 阿里云百炼（Qwen / 通义千问）

| 参数 | 值 |
|------|----|
| `api_url` | `https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions` |
| `api_key` | 在 [阿里云百炼控制台](https://bailian.console.aliyun.com/) 申请，格式 `sk-...` |
| 模型名称 | 见下表 |

**Qwen 主要模型列表：**

| 模型标识符 | 说明 |
|-----------|------|
| `qwen-max` | 旗舰版，能力最强 |
| `qwen-plus` | 均衡版，性价比高 |
| `qwen-turbo` | 快速版，低延迟 |
| `qwen-long` | 长文档处理，支持超长上下文 |
| `qwen2.5-72b-instruct` | Qwen2.5 开源旗舰版 |
| `qwen2.5-coder-32b-instruct` | 代码专用版 |

**环境变量配置：**

```bash
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
export LLM_API_URL="https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
export LLM_MODEL="qwen-max"
```

**配置文件 `~/.llmdog.yaml`：**

```yaml
api_key: sk-xxxxxxxxxxxxxxxxxxxxxxxx
api_url: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
model: qwen-max
timeout: 120
verify_ssl: true
```

**命令行调用：**

```bash
# 使用旗舰模型
llmdog chat --content "分析这段 SQL 语句的性能瓶颈" --model qwen-max

# 切换为代码专用模型
llmdog chat --content "帮我优化这个排序算法" --model qwen2.5-coder-32b-instruct
```

**Python 调用：**

```python
from llmdog import chat
from llmdog.config import load_config

cfg = load_config(
    api_key="sk-xxxxxxxxxxxxxxxxxxxxxxxx",
    api_url="https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
    model="qwen2.5-coder-32b-instruct",
)
reply = chat("帮我优化这个排序算法", config=cfg)
print(reply)
```

---

#### OpenAI

| 参数 | 值 |
|------|----|
| `api_url` | `https://api.openai.com/v1/chat/completions` |
| `api_key` | 在 [OpenAI Platform](https://platform.openai.com/) 申请，格式 `sk-...` |
| 模型名称 | `gpt-4o`、`gpt-4o-mini`、`gpt-4-turbo`、`o1`、`o3-mini` |

**环境变量配置：**

```bash
export LLM_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxx"
export LLM_API_URL="https://api.openai.com/v1/chat/completions"
export LLM_MODEL="gpt-4o"
```

**命令行调用：**

```bash
llmdog chat --content "解释量子纠缠" --model gpt-4o --timeout 90
```

**Python 调用：**

```python
from llmdog import chat

# 通过环境变量已配置好 api_url 和 api_key 的情况下
reply = chat("解释量子纠缠", model="gpt-4o", timeout=90)
print(reply)
```

---

#### OpenAI API（默认）

llmdog 内置默认配置即为端点，无需额外设置 `api_url`。

| 参数 | 值 |
|------|----|
| `api_url` | `http://api.openai.com/v1/chat/completions`（默认） |
| `api_key` | 内网申请的 Bearer Token，通过环境变量 `LLM_API_KEY` 配置 |
| 模型名称 | `qwen2.5-coder-32b-instruct`（默认）、`qwen3-30b-a3b-instruct-2507`、`qwen3-72b-instruct` |
| `verify_ssl` | `false`（内网环境，默认关闭 SSL 验证）|

**环境变量配置：**

```bash
export LLM_API_KEY="your-internal-bearer-token"
# api_url 使用默认值，无需设置
```

**配置文件 `~/.llmdog.yaml`：**

```yaml
api_key: your-internal-bearer-token
model: qwen3-72b-instruct
timeout: 120
max_retries: 3
verify_ssl: false
```

**命令行调用：**

```bash
# 使用默认配置（最简调用）
llmdog chat --content "你好，你是谁？"

# 指定高性能模型
llmdog chat --content "帮我分析这段 Python 代码" --model qwen3-72b-instruct
```

**Python 调用：**

```python
from llmdog import chat

# api_url 使用默认值，仅需配置 api_key
reply = chat("帮我分析这段 Python 代码", model="qwen3-72b-instruct")
print(reply)
```

---

#### 通用参数说明

以下参数适用于所有服务商，可在配置文件、环境变量或运行时传入：

| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| `timeout` | `int` | `120` | HTTP 请求超时秒数，复杂推理任务建议适当增大 |
| `max_retries` | `int` | `3` | 请求失败最大重试次数，使用指数退避策略 |
| `verify_ssl` | `bool` | `false` | 是否验证 SSL 证书，公网服务商建议设为 `true` |

**多服务商配置文件切换示例：**

```bash
# 使用 DeepSeek 配置文件
llmdog chat --content "写一篇技术博客" --config-file ~/.llmdog-deepseek.yaml

# 使用 Qwen 配置文件
llmdog chat --content "写一篇技术博客" --config-file ~/.llmdog-qwen.yaml
```

---

## API 接口说明

### `llmdog.chat(content, *, backend=None, model=None, config=None, **kwargs)`

核心对话函数。

| 参数 | 类型 | 说明 |
|------|------|------|
| `content` | `str` | 用户输入文本（必填） |
| `backend` | `str \| None` | 后端标识符，默认 `"llmapi"` |
| `model` | `str \| None` | 模型名称，覆盖配置中的默认值 |
| `config` | `Config \| None` | 配置对象，为 `None` 时自动加载 |
| `api_key` | `str`（kwargs） | API Key，覆盖环境变量 |
| `api_url` | `str`（kwargs） | API 端点地址 |
| `timeout` | `int`（kwargs） | 超时秒数 |

**返回值**：`str | None` — 模型回复文本；失败时返回 `None`。

---

### `llmdog.load_config(config_file=None, **overrides)`

按优先级加载配置，返回 `Config` 实例。

**优先级（高 → 低）**：运行时参数 > 环境变量 > 配置文件 > 默认值

**支持的环境变量**：

| 环境变量 | 对应配置项 | 默认值 |
|----------|------------|--------|
| `LLM_API_KEY` | `api_key` | — |
| `LLM_API_URL` | `api_url` | LLM API端点 |
| `LLM_MODEL` | `model` | `qwen2.5-coder-32b-instruct` |
| `LLM_TIMEOUT` | `timeout` | `120` |
| `LLM_MAX_RETRIES` | `max_retries` | `3` |
| `LLM_VERIFY_SSL` | `verify_ssl` | `false` |

---

### `llmdog.register_backend(name, backend_cls)`

向注册表注册自定义后端，实现扩展。

```python
from llmdog import register_backend
from llmdog.backends.base import BaseBackend
from typing import Optional

class MyBackend(BaseBackend):
    name = "my_service"

    def chat(self, content: str, model=None, **kwargs) -> Optional[str]:
        # 你的实现
        return "custom reply"

register_backend("my_service", MyBackend)

# 使用自定义后端
from llmdog import chat
reply = chat("测试", backend="my_service")
```

---

## 依赖项清单

| 依赖 | 版本 | 用途 |
|------|------|------|
| `requests` | >=2.28.0 | HTTP 请求 |
| `tenacity` | >=8.0.0 | 重试机制 |
| `typer` | >=0.12.0 | CLI 框架 |
| `rich` | >=13.0.0 | 终端美化输出 |
| `pyyaml` | >=6.0 | YAML 配置文件解析 |
| `typing-extensions` | >=4.0.0 | Python 3.9 类型兼容 |

**开发依赖**（`pip install llmdog[dev]`）：

| 依赖 | 用途 |
|------|------|
| `pytest` | 单元测试框架 |
| `pytest-cov` | 测试覆盖率报告 |
| `black` | 代码格式化 |
| `isort` | import 排序 |
| `mypy` | 静态类型检查 |

---

## 贡献指南与许可证信息

### 贡献指南

1. Fork 本仓库并创建特性分支：`git checkout -b feature/my-new-backend`
2. 按照 PEP 257 规范为所有公开 API 添加 docstring
3. 确保新增后端继承 `BaseBackend` 并覆盖 `name` 属性
4. 运行测试并确保通过：`pytest tests/ -v`
5. 提交 Pull Request，附上功能描述和测试结果

### 运行测试

```bash
# 安装开发依赖
pip install -e ".[dev]"

# 运行全部测试
pytest tests/ -v

# 生成覆盖率报告
pytest tests/ --cov=llmdog --cov-report=term-missing
```

### 项目结构

```
src/llmdog/
├── __init__.py          # 公开 API 导出
├── cli.py               # Typer CLI 入口
├── chat.py              # 统一调用层（注册表模式）
├── config.py            # 配置管理
├── backends/
│   ├── base.py          # 抽象基类
│   └── llmapi.py        # OpenAI 兼容格式通用后端
└── utils/
    └── display.py       # Rich 终端美化工具
```

### 许可证

本项目使用 [MIT License](https://opensource.org/licenses/MIT)。
