# dotpromptz-py

`dotpromptz-py` 是一个可执行 `.prompt` 模板格式的 Python 实现，支持：

- Jinja2 模板渲染
- 多模型适配器（`openai` / `anthropic` / `google`）
- 批量输入执行
- 结构化输出（`json` / `yaml` / `txt` / `image`）

## CLI 用法

安装 CLI（推荐，使用 `uv tool`）：

```bash
uv tool install dotpromptz-py
uv tool upgrade dotpromptz-py
```

如果你在仓库内开发，再执行：

```bash
uv sync
```

查看帮助：

```bash
prompt --help
```

### 全局参数

```bash
prompt --version
prompt --log-level DEBUG run demo.prompt
prompt --upgrade
```

- `--log-level`: `DEBUG|INFO|WARNING|ERROR|CRITICAL`，默认 `INFO`
- `--upgrade` / `-U`: 通过 `uv` 升级 `dotpromptz-py`

### 1) 运行 `.prompt`（会调用模型）

```bash
prompt run path/to/demo.prompt
prompt run path/to/demo.prompt --force
```

- `run` 会执行完整流程：编译、渲染、调用模型、写出结果文件
- 当输出文件已存在时，需加 `--force`
- `run` 前置要求：`.prompt` 里必须配置 `output.format` 和 `output.file_name`

### 2) 构建 `.prompt`（不调用模型）

```bash
prompt build path/to/demo.prompt
```

- `build` 只渲染，不请求 LLM
- 会在日志目录生成一个 `build_<prompt名>_<时间>_<pid>.yaml`，用于检查渲染后的消息与配置

### 3) 合并输入目录

```bash
prompt merge ./data
prompt merge ./data --pattern "**/*.json" -W --force
```

- 支持输入扩展名：`.json` `.yaml` `.yml` `.txt`
- `--pattern`: 自定义 glob 匹配
- `-W` / `--with-filename`: 注入 `FILENAME=<文件名去后缀>`
- 输出文件：
  - 合并 JSON/TXT -> `上级目录/<目录名>.jsonl`
  - 合并 YAML -> `上级目录/<目录名>.yaml`

### 4) Git 自动化命令

```bash
prompt git sync
prompt git push
prompt git submit path/to/demo.prompt
prompt git submit path/to/demo.prompt --no-mail
```

- `git sync`: `fetch + pull --ff-only`
- `git push`: 自动 `git add .`、生成提交信息、提交并推送
- `git submit`: 安装并触发 `submit-prompt` GitHub Workflow（依赖 `gh auth login`）

## `.prompt` 写法

`.prompt` 文件由两部分组成：

1. Frontmatter（YAML，必须用 `---` 包裹）
2. 模板体（消息内容，支持 Jinja2）

### 最小结构

```prompt
---
version: 2
---
:::user
hello
```

注意：

- `version` 必填，且当前必须为 2
- frontmatter 顶层只允许这些字段：
  - `version`
  - `description`
  - `adapter`
  - `config`
  - `input`
  - `output`
  - `runtime`

### 消息块语法

支持块：

- `:::system`
- `:::user`
- `:::model`
- `:::image`

示例：

```prompt
---
version: 1
---
:::system
你是一个简洁的助手。

:::user
请介绍 {{ topic }}

:::model
好的，我来介绍。

:::user
先看这张图：
:::image
https://example.com/cat.jpg
```

规则：

- 使用块语法时，第一条消息前不能有普通文本
- `:::image` 必须出现在某个 role 块后面
- `:::image` 的下一行写 URL/路径
- 如果模板体完全不写块，则整段文本会被当成一条 `user` 消息

### 模板变量（Jinja2）

你可以在模板体和 frontmatter 的字符串字段中使用 `{{ ... }}`。

变量来源：

- `input.data` / `input.files` / `input.defaults`
- 自动变量：
  - `TIME`: 时间戳，格式 `YYYYMMDD_HHMMSS`
  - `NAME`: `.prompt` 文件名（不含后缀）
  - `INDEX`: 批处理索引（主要用于输出文件名模板）
  - `SCHEMA`: `output.schema` 的 JSON 字符串

注意：输入变量名不要使用全大写（会与自动变量冲突）。

### `input` 配置

`input` 三个字段（`data` 和 `files` 互斥）：

```yaml
input:
  defaults:
    lang: zh
  data:
    topic: AI
```

或：

```yaml
input:
  files: ./data/input.jsonl
```

`files` 支持 `.json` `.yaml` `.yml` `.jsonl`。

### `output` 配置

`run` 命令必须配置 `output`，至少要有：

```yaml
output:
  format: txt   # json | yaml | txt | image
  file_name: '{{NAME}}_{{TIME}}'
```

可选：

- `output_dir`: 默认为 `output/{{NAME}}_{{TIME}}`
- `schema`: JSON Schema（仅 `json/yaml` 生效）
- `example`: YAML 示例（自动推断 schema，且与 `schema` 互斥）

### `adapter` / `config` / `runtime`

```yaml
adapter: openai
config:
  model: gpt-4o
  temperature: 0.2
runtime:
  max_workers: 5
  timeout: 30
  retry:
    max_retries: 2
    retry_delay: 1.0
```

### 完整可运行示例

```prompt
---
version: 1
description: 生成摘要
adapter: openai
config:
  model: gpt-4o-mini
  temperature: 0.2
input:
  data:
    topic: Dotprompt
output:
  format: json
  file_name: '{{NAME}}_{{TIME}}'
  schema:
    type: object
    properties:
      summary:
        type: string
    required: [summary]
    additionalProperties: false
runtime:
  max_workers: 3
---
:::system
你是一个技术写作助手。

:::user
请用中文总结 {{ topic }}，返回 JSON，必须满足这个 schema：
{{ SCHEMA }}
```

执行：

```bash
prompt run ./summary.prompt
```
