mirror of
https://github.com/alibaba/open-code-review.git
synced 2026-08-04 05:50:40 +00:00
docs(pages): document local-model setup, tool-calling requirement, and LLM timeouts (#400)
* docs(pages): add FAQ entry for local models without native tool calling Two changes per locale (en/zh/ja), addressing #234: - New "No tool calls parsed" entry under Configuration & startup: the symptom loop, the durable rule that the model must support native tool calling (deepseek-r1 narrates calls in content and can never work; qwen3 works), the Ollama tools-tag search link, and the maintainer's curl snippet to verify a model emits structured tool_calls without OCR in the loop. - The existing "Max tool requests reached" entry (where users actually land) gains a 4th cause bullet cross-linking the new entry. Anchors follow generateHeadingId (pages/src/utils/headingId.ts), the site's actual slugger, and were verified against the rendered DOM in all three locales. Code blocks are byte-identical across locales per i18n convention; heading counts stay in parity. * docs(pages): document Ollama custom-provider setup and LLM timeouts Two additions per locale (en/zh/ja), addressing #234: - Custom providers: a copy-paste Ollama example (127.0.0.1:11434/v1, protocol openai) with the note that custom providers require a non-empty api_key placeholder (resolver has no env fallback for them) and a pointer to the FAQ tool-calling rule. - New Timeouts subsection: providers.<name>.timeout_sec / llm.timeout_sec / OCR_LLM_TIMEOUT, the 300s default, and the caveat that timeout_sec is not supported by 'ocr config set' (config_cmd has no timeout handling) so config.json must be edited directly. The ja Timeouts heading is タイムアウト(Timeouts) so the site slugger (which strips katakana) still yields a linkable #timeouts anchor. Code blocks byte-identical across locales; heading parity kept. * fix(pages): decode percent-encoded anchor fragments before id lookup marked percent-encodes non-ASCII hrefs (#超时 renders as #%E8%B6%85%E6%97%B6), but heading ids are raw text from generateHeadingId, so handleContentClick's getElementById never matched for CJK anchors: same-page clicks silently no-oped and cross-page anchor scrolls exhausted their retries at the top of the page. This affected every pre-existing zh in-page anchor (e.g. faq 复用已有的环境变量) as well as the zh links added for #234. Decode the fragment (with a malformed-input guard) at both lookup sites.
This commit is contained in:
parent
d75f945b46
commit
151cc7582e
7 changed files with 241 additions and 2 deletions
|
|
@ -72,6 +72,47 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
|
|||
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
|
||||
```
|
||||
|
||||
A local model served by Ollama is just a custom provider pointing at the
|
||||
local OpenAI-compatible endpoint:
|
||||
|
||||
```bash
|
||||
ocr config set provider ollama
|
||||
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
|
||||
ocr config set custom_providers.ollama.protocol openai
|
||||
ocr config set custom_providers.ollama.model qwen3:32b
|
||||
ocr config set custom_providers.ollama.api_key ollama
|
||||
```
|
||||
|
||||
Ollama ignores the API key, but custom providers require a non-empty
|
||||
`api_key` (there is no environment-variable fallback for them), so set
|
||||
any placeholder value. The model itself must support native tool
|
||||
calling — see
|
||||
["No tool calls parsed" (local models / Ollama)](../faq/#no-tool-calls-parsed-local-models-ollama)
|
||||
in the FAQ before picking one.
|
||||
|
||||
### Timeouts
|
||||
|
||||
Each LLM request has an HTTP timeout, defaulting to **300 seconds**.
|
||||
Slow local models (or large files) can need more. Three knobs, in
|
||||
increasing scope:
|
||||
|
||||
- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
|
||||
— per-provider, in seconds.
|
||||
- `llm.timeout_sec` — for the legacy `llm` section, in seconds.
|
||||
- `OCR_LLM_TIMEOUT` environment variable — integer seconds; overrides
|
||||
the config-file value for every resolution path.
|
||||
|
||||
The `timeout_sec` keys are not supported by `ocr config set` — edit
|
||||
`~/.opencodereview/config.json` directly:
|
||||
|
||||
```json
|
||||
{
|
||||
"custom_providers": {
|
||||
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Verify connectivity
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -53,6 +53,42 @@ OpenAI use different auth headers and different URL shapes — make sure
|
|||
against the current directory. If you're not inside a Git working tree,
|
||||
it exits early. Either `cd` into a repo, or pass `--repo /path/to/repo`.
|
||||
|
||||
### "No tool calls parsed" (local models / Ollama)
|
||||
|
||||
```
|
||||
[ocr] No tool calls parsed for src/foo.go, retrying...
|
||||
[ocr] Max tool requests reached for src/foo.go.
|
||||
```
|
||||
|
||||
If every review loops through `No tool calls parsed` retries and ends
|
||||
with "Max tool requests reached" and zero comments, the model — not the
|
||||
config — is the problem. OCR drives the review entirely through tool
|
||||
calls, so **the model must support native tool calling (function
|
||||
calling)**. A model that merely *narrates* tool calls in its text
|
||||
output (or inside `<think>` blocks) can never work with OCR, no matter
|
||||
how the prompt is tuned — `deepseek-r1` is a common example. Models
|
||||
with native tool support, such as `qwen3`, work fine. For Ollama, pick
|
||||
from the models tagged with tools support:
|
||||
<https://ollama.com/search?c=tools>.
|
||||
|
||||
Verify a local model directly, without OCR in the loop:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
|
||||
"model": "qwen3:32b",
|
||||
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
|
||||
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
|
||||
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
|
||||
}'
|
||||
```
|
||||
|
||||
Pass: the response contains a structured `tool_calls` array naming
|
||||
`report_bug`. Fail: the "call" appears as text inside `content`.
|
||||
|
||||
If the model *does* support tools but responses are slow on local
|
||||
hardware, raise the LLM timeout instead — see
|
||||
[Timeouts](../configuration/#timeouts).
|
||||
|
||||
## Filtering & rules
|
||||
|
||||
### My file isn't being reviewed
|
||||
|
|
@ -173,6 +209,9 @@ usually one of:
|
|||
`--max-tools 40` for more, `--max-tools 15` for fewer). Values 1–9
|
||||
are clamped up to 10; `0` (the default) uses the template default of
|
||||
30.
|
||||
- The model does not support native tool calling at all (common with
|
||||
local models) — see
|
||||
["No tool calls parsed" (local models / Ollama)](#no-tool-calls-parsed-local-models-ollama).
|
||||
|
||||
### Some sub-agents fail; the run still exits 0
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,47 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
|
|||
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
|
||||
```
|
||||
|
||||
Ollama で動かすローカルモデルは、ローカルの OpenAI 互換エンドポイントを
|
||||
指すカスタム provider にすぎません。
|
||||
|
||||
```bash
|
||||
ocr config set provider ollama
|
||||
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
|
||||
ocr config set custom_providers.ollama.protocol openai
|
||||
ocr config set custom_providers.ollama.model qwen3:32b
|
||||
ocr config set custom_providers.ollama.api_key ollama
|
||||
```
|
||||
|
||||
Ollama は API key を無視しますが、カスタム provider は空でない `api_key` を
|
||||
必要とします(カスタム provider には環境変数のフォールバックがありません)。
|
||||
そのため任意のプレースホルダー値を設定してください。モデル自体はネイティブな
|
||||
ツール呼び出しをサポートしている必要があります——選ぶ前に FAQ の
|
||||
["No tool calls parsed"(ローカルモデル / Ollama)](../faq/#no-tool-calls-parsed-ollama)を
|
||||
参照してください。
|
||||
|
||||
### タイムアウト(Timeouts)
|
||||
|
||||
各 LLM リクエストには HTTP タイムアウトがあり、デフォルトは **300 秒**です。
|
||||
遅いローカルモデル(あるいは大きなファイル)では、それ以上の時間が必要になることがあります。
|
||||
スコープの狭い順に、3 つの設定があります。
|
||||
|
||||
- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
|
||||
——provider ごと、秒単位。
|
||||
- `llm.timeout_sec`——レガシーな `llm` セクション用、秒単位。
|
||||
- `OCR_LLM_TIMEOUT` 環境変数——整数(秒単位)。すべての解決パスで設定ファイルの
|
||||
値を上書きします。
|
||||
|
||||
`timeout_sec` key は `ocr config set` ではサポートされていません——
|
||||
`~/.opencodereview/config.json` を直接編集してください。
|
||||
|
||||
```json
|
||||
{
|
||||
"custom_providers": {
|
||||
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 接続性を検証する
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -53,6 +53,39 @@ OpenAI は異なる auth header と URL フォーマットを使います——`
|
|||
`git ls-files`)を実行します。Git ワークツリー内にいない場合は、早期に終了します。リポジトリに
|
||||
`cd` するか、`--repo /path/to/repo` を渡してください。
|
||||
|
||||
### "No tool calls parsed"(ローカルモデル / Ollama)
|
||||
|
||||
```
|
||||
[ocr] No tool calls parsed for src/foo.go, retrying...
|
||||
[ocr] Max tool requests reached for src/foo.go.
|
||||
```
|
||||
|
||||
すべてのレビューが `No tool calls parsed` のリトライをループし、"Max tool requests
|
||||
reached" とコメント 0 件で終わる場合、問題は設定ではなくモデルにあります。OCR はレビュー全体を
|
||||
ツール呼び出しで駆動するため、**モデルはネイティブなツール呼び出し(function calling)を
|
||||
サポートしている必要があります**。ツール呼び出しをテキスト出力(あるいは `<think>` ブロック内)で
|
||||
*語るだけ*のモデルは、prompt をどう調整しても OCR では決して動作しません——`deepseek-r1` は
|
||||
よくある例です。`qwen3` のようなネイティブなツールサポートを持つモデルは問題なく動作します。
|
||||
Ollama の場合は、tools サポートのタグが付いたモデルから選んでください:
|
||||
<https://ollama.com/search?c=tools>。
|
||||
|
||||
OCR を介さずに、ローカルモデルを直接検証するには:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
|
||||
"model": "qwen3:32b",
|
||||
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
|
||||
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
|
||||
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
|
||||
}'
|
||||
```
|
||||
|
||||
合格: 応答に `report_bug` を指す構造化された `tool_calls` 配列が含まれる。不合格: 「呼び出し」が
|
||||
`content` 内のテキストとして現れる。
|
||||
|
||||
モデルがツールを*サポートしている*のに、ローカルハードウェアで応答が遅い場合は、代わりに
|
||||
LLM タイムアウトを引き上げてください——[タイムアウト](../configuration/#timeouts)を参照。
|
||||
|
||||
## フィルタリングとルール
|
||||
|
||||
### ファイルがレビューされない
|
||||
|
|
@ -163,6 +196,9 @@ JSON モードでは `warnings` にも表示されます。
|
|||
- ファイルが本当に大きい、あるいはコンテキストが重く、30 回では足りない。`--max-tools <n>` で
|
||||
上げるか下げるか調整してください(例: `--max-tools 40` でより多く、`--max-tools 15` でより少なく)。
|
||||
1〜9 は 10 に引き上げられます。`0`(デフォルト)はテンプレートのデフォルト 30 を使います。
|
||||
- モデルがネイティブなツール呼び出しを全くサポートしていない(ローカルモデルでよくある)——
|
||||
["No tool calls parsed"(ローカルモデル / Ollama)](#no-tool-calls-parsed-ollama)を
|
||||
参照してください。
|
||||
|
||||
### 一部のサブエージェントが失敗しても、実行は 0 で終了する
|
||||
|
||||
|
|
|
|||
|
|
@ -68,6 +68,43 @@ ocr config set custom_providers.my-gateway.model llama-3-70b
|
|||
ocr config set custom_providers.my-gateway.api_key "$MY_API_KEY"
|
||||
```
|
||||
|
||||
用 Ollama 跑本地模型,就是一个指向本地 OpenAI 兼容端点的自定义 provider:
|
||||
|
||||
```bash
|
||||
ocr config set provider ollama
|
||||
ocr config set custom_providers.ollama.url http://127.0.0.1:11434/v1
|
||||
ocr config set custom_providers.ollama.protocol openai
|
||||
ocr config set custom_providers.ollama.model qwen3:32b
|
||||
ocr config set custom_providers.ollama.api_key ollama
|
||||
```
|
||||
|
||||
Ollama 会忽略 API key,但自定义 provider 要求非空的 `api_key`(自定义
|
||||
provider 没有环境变量回退),所以设任意占位值即可。模型本身必须支持原生
|
||||
工具调用——选型前请先看 FAQ 中的
|
||||
["No tool calls parsed"(本地模型 / Ollama)](../faq/#no-tool-calls-parsed-本地模型-ollama)。
|
||||
|
||||
### 超时
|
||||
|
||||
每个 LLM 请求都有 HTTP 超时,默认 **300 秒**。慢的本地模型(或大文件)可能
|
||||
需要更长的时间。三个配置项,作用域递增:
|
||||
|
||||
- `providers.<name>.timeout_sec` / `custom_providers.<name>.timeout_sec`
|
||||
——per-provider,单位秒。
|
||||
- `llm.timeout_sec`——用于旧版 `llm` 配置段,单位秒。
|
||||
- `OCR_LLM_TIMEOUT` 环境变量——整数秒;对每条解析路径都覆盖配置文件里
|
||||
的值。
|
||||
|
||||
`ocr config set` 不支持 `timeout_sec` key——直接编辑
|
||||
`~/.opencodereview/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"custom_providers": {
|
||||
"ollama": { "url": "http://127.0.0.1:11434/v1", "protocol": "openai", "timeout_sec": 900 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 验证连通性
|
||||
|
||||
```bash
|
||||
|
|
|
|||
|
|
@ -48,6 +48,38 @@ URL 格式——确保 `llm.use_anthropic` 与你指向的 URL 相匹配:
|
|||
`ocr review` 对当前目录运行 `git diff`(以及对 untracked 文件的 `git ls-files`)。
|
||||
若你不在 Git 工作树内,它会提前退出。要么 `cd` 进仓库,要么传 `--repo /path/to/repo`。
|
||||
|
||||
### "No tool calls parsed"(本地模型 / Ollama)
|
||||
|
||||
```
|
||||
[ocr] No tool calls parsed for src/foo.go, retrying...
|
||||
[ocr] Max tool requests reached for src/foo.go.
|
||||
```
|
||||
|
||||
若每次评审都在 `No tool calls parsed` 重试中循环,最终以 "Max tool requests
|
||||
reached" 结束且没有任何评论,问题出在模型——而非配置。OCR 完全通过工具调用驱动评审,
|
||||
因此**模型必须支持原生工具调用(function calling)**。只在文本输出(或
|
||||
`<think>` 块内)*叙述*工具调用的模型,无论怎么调 prompt 都永远无法与 OCR
|
||||
配合使用——`deepseek-r1` 是常见例子。具备原生工具支持的模型(如 `qwen3`)则工作
|
||||
正常。对 Ollama,请从带 tools 标签的模型中挑选:
|
||||
<https://ollama.com/search?c=tools>。
|
||||
|
||||
绕开 OCR、直接验证本地模型:
|
||||
|
||||
```bash
|
||||
curl http://127.0.0.1:11434/v1/chat/completions -H "Content-Type: application/json" -d '{
|
||||
"model": "qwen3:32b",
|
||||
"messages": [{"role": "user", "content": "The code below has a bug, use the report_bug tool to report it.\n\nfunc add(a, b int) int {\n return a - b\n}"}],
|
||||
"tools": [{"type": "function", "function": {"name": "report_bug", "description": "Report a bug in the code",
|
||||
"parameters": {"type": "object", "properties": {"line": {"type": "integer"}, "description": {"type": "string"}}, "required": ["description"]}}}]
|
||||
}'
|
||||
```
|
||||
|
||||
通过:响应包含指向 `report_bug` 的结构化 `tool_calls` 数组。失败:“调用”以
|
||||
文本形式出现在 `content` 里。
|
||||
|
||||
若模型*确实*支持工具,只是在本地硬件上响应缓慢,请改为调高 LLM 超时——见
|
||||
[超时](../configuration/#超时)。
|
||||
|
||||
## 过滤与规则
|
||||
|
||||
### 我的文件没被评审
|
||||
|
|
@ -150,6 +182,8 @@ diff 能从 plan 中受益。要为单次评审跳过它,用更小 diff 运行
|
|||
- 文件确实大或上下文重,30 轮不够。用 `--max-tools <n>` 调高或调低
|
||||
(如 `--max-tools 40` 更多,`--max-tools 15` 更少)。1–9 会被上调到 10;
|
||||
`0`(默认)用模板默认 30。
|
||||
- 模型完全不支持原生工具调用(本地模型常见)——见
|
||||
["No tool calls parsed"(本地模型 / Ollama)](#no-tool-calls-parsed-本地模型-ollama)。
|
||||
|
||||
### 一些子 agent 失败;运行仍以 0 退出
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,16 @@ import docContentsIcon from '../assets/icons/doc-contents.svg';
|
|||
import searchIcon from '../assets/icons/icon-search.svg';
|
||||
import '../styles/docs-markdown.css';
|
||||
|
||||
// marked percent-encodes non-ASCII hrefs; heading ids are raw text from
|
||||
// generateHeadingId, so fragments must be decoded before lookup.
|
||||
function decodeFragment(fragment: string): string {
|
||||
try {
|
||||
return decodeURIComponent(fragment);
|
||||
} catch {
|
||||
return fragment;
|
||||
}
|
||||
}
|
||||
|
||||
/* ─── Sidebar tree data ─── */
|
||||
interface SidebarItem {
|
||||
id: string;
|
||||
|
|
@ -198,7 +208,7 @@ const DocsPage: React.FC = () => {
|
|||
// Skip pure anchors (same-page scroll)
|
||||
if (href.startsWith('#')) {
|
||||
e.preventDefault();
|
||||
const id = href.slice(1);
|
||||
const id = decodeFragment(href.slice(1));
|
||||
const el = document.getElementById(id);
|
||||
if (el) el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
return;
|
||||
|
|
@ -217,7 +227,8 @@ const DocsPage: React.FC = () => {
|
|||
e.preventDefault();
|
||||
navigateToDoc(slug);
|
||||
// Handle anchor scroll after navigation with reliable retry
|
||||
const anchor2 = href.split('#')[1];
|
||||
const anchor2raw = href.split('#')[1];
|
||||
const anchor2 = anchor2raw ? decodeFragment(anchor2raw) : undefined;
|
||||
if (anchor2) {
|
||||
const tryScroll = (attempts: number) => {
|
||||
const el = document.getElementById(anchor2);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue