Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,22 @@ For specialized deployment scenarios, see the detailed guides:
- **[Apple Silicon with mlx-vlm](examples/mlx-deploy/README.md)** - Optimized for Apple Silicon Macs
- **[Ollama Deployment](examples/ollama-deploy/README.md)** - Simple local deployment with Ollama

#### Option 4: SDK Server + Client (GPU-less Client)

Deploy the SDK Server on a GPU machine, then use any machine as a client — no GPU needed on the client side. The client connects via the MaaS-compatible protocol, pointing `api_url` at your self-hosted server.
Comment on lines +169 to +171

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description currently contains a generic contribution guide template and doesn’t describe the self-hosted README additions. Please update the PR description to match the actual change (adding a self-hosted SDK server/client guide) so reviewers and release notes consumers have accurate context.

Copilot uses AI. Check for mistakes.

```yaml
# Client config.yaml
pipeline:
maas:
enabled: true
api_url: http://<SERVER_IP>:5002/glmocr/parse
api_key: any-string # self-hosted server does not validate keys
verify_ssl: false
Comment on lines +171 to +180

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The snippet explicitly notes the self-hosted server does not validate API keys, which means the endpoint is unauthenticated by default. Please add a clear warning not to expose this server publicly, and recommend putting it behind network controls (firewall/VPC) and/or a reverse proxy providing TLS + auth if used outside a trusted network.

Copilot uses AI. Check for mistakes.
```

See the full guide: **[Self-hosted SDK Server + Client](examples/self-host/README.md)**

#### Update Configuration

After launching the service, configure `config.yaml`:
Expand Down
16 changes: 16 additions & 0 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,22 @@ sglang serve --model zai-org/GLM-OCR --port 8080 --speculative-algorithm NEXTN -
- **[Apple Silicon 使用 mlx-vlm](examples/mlx-deploy/README.md)** - 针对 Apple Silicon Mac 优化
- **[Ollama 部署](examples/ollama-deploy/README.md)** - 使用 Ollama 进行简单的本地部署

#### 方式 4: SDK Server + Client(Client 无需 GPU)

在 GPU 机器上部署 SDK Server,其他机器作为 Client 通过网络调用——Client 端无需 GPU。Client 通过 MaaS 兼容协议连接,将 `api_url` 指向自建 Server 即可。

```yaml
# Client 端 config.yaml
pipeline:
maas:
enabled: true
api_url: http://<SERVER_IP>:5002/glmocr/parse
api_key: any-string # 自建 Server 不校验 API key
verify_ssl: false
Comment on lines +169 to +178

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里提到自建 Server 不校验 API key,意味着该服务默认无鉴权。建议补充明确的安全提示:不要将该服务直接暴露到公网;如需跨网络使用,请通过防火墙/VPC 或反向代理提供 TLS 与鉴权(例如 Basic Auth / Token / mTLS)。

Copilot uses AI. Check for mistakes.
```

完整指南见:**[自部署 SDK Server + Client](examples/self-host/README.md)**

##### 更新配置

启动服务后,配置 `config.yaml`:
Expand Down
103 changes: 103 additions & 0 deletions examples/self-host/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Self-hosted SDK Server + Client Mode

The GLM-OCR SDK supports a split **Server / Client** deployment: run the SDK Server on a GPU machine, and connect from any other machine over HTTP — no GPU required on the client side.

## Architecture

```
┌──────────────────────┐ HTTP ┌──────────────────────────────┐
│ Client (no GPU) │ ────────────────→ │ Server (GPU machine) │
│ │ POST /glmocr/parse│ │
│ glmocr CLI / Python │ ←──────────────── │ python -m glmocr.server │
│ │ JSON response │ (layout + OCR pipeline) │
└──────────────────────┘ └──────────────────────────────┘
```

The Server runs the full OCR pipeline (layout detection + parallel OCR). The Client calls it over HTTP with zero local computation.

## Server Side

On the GPU machine, start the Server:

```bash
# 1. Install (includes selfhosted pipeline + server)
pip install "glmocr[selfhosted,server]"

# 2. Configure self-hosted mode and point to your local vLLM / SGLang
# In config.yaml: set pipeline.maas.enabled: false and configure ocr_api

# 3. Start the server
python -m glmocr.server --config config.yaml
```

The server listens on `0.0.0.0:5002` by default, with the API endpoint at `/glmocr/parse`.

## Client Side

On any machine (no GPU needed), point the SDK's MaaS client at your self-hosted server:

```bash
pip install glmocr
```

Edit `config.yaml`:

```yaml
pipeline:
maas:
enabled: true
api_url: http://<SERVER_IP>:<SERVER_PORT>/glmocr/parse
api_key: any-string # Self-hosted server does not validate API keys
verify_ssl: false # Internal networks typically lack HTTPS

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify_ssl: false disables TLS certificate verification when using HTTPS. Consider rewording the comment to clarify it’s only needed for self-signed/internal HTTPS; if you’re using plain http:// it has no effect, and if you’re using proper HTTPS it should remain true.

Suggested change
verify_ssl: false # Internal networks typically lack HTTPS
verify_ssl: false # Only relevant for https:// URLs; no effect with http://. Use false only for self-signed/internal HTTPS, otherwise keep true.

Copilot uses AI. Check for mistakes.
```
Comment on lines +50 to +52

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This guide notes the server doesn’t validate API keys, but it should also include an explicit warning about the security implications (no auth by default) and recommend running it only on trusted networks or behind a reverse proxy with TLS/auth when used beyond localhost.

Copilot uses AI. Check for mistakes.

Then use the CLI or Python API:

```bash
# CLI
glmocr parse document.png --config config.yaml

# Or set via environment variable

Copilot AI Apr 8, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The “Or set via environment variable” example only sets ZHIPU_API_KEY and then runs glmocr parse without --config. Without also overriding the MaaS api_url (e.g., via GLMOCR_API_URL or a config file), the CLI will use the packaged default cloud endpoint instead of the self-hosted server. Update this section to either keep using --config config.yaml or show the necessary env vars to point pipeline.maas.api_url at the self-hosted server.

Suggested change
# Or set via environment variable
# Or set via environment variables
export GLMOCR_API_URL=http://<SERVER_IP>:5002/glmocr/parse

Copilot uses AI. Check for mistakes.
export ZHIPU_API_KEY=any-string
glmocr parse document.png
```

```python
# Python API
from glmocr import GlmOcr

with GlmOcr(
mode="maas",
api_url="http://<SERVER_IP>:5002/glmocr/parse",
api_key="any-string",
) as parser:
result = parser.parse("document.png")
print(result.markdown_result)
```

## Protocol Details

The server accepts both input formats:

| Input format | Example |
|---|---|
| SDK native | `{"images": ["url1", "url2"]}` |
| MaaS compatible | `{"file": "url", "model": "glm-ocr"}` |

The server response includes both SDK and MaaS field sets:

```json
{
"json_result": [...],
"markdown_result": "...",
"layout_details": [...],
"md_results": "...",
"data_info": {"pages": []},
"usage": {},
"model": "glm-ocr",
"id": "chatcmpl-...",
"created": 1709234567
}
```

This means the client can use the SDK CLI / Python API or send raw HTTP requests — both will parse the response correctly.
Loading