Skip to content
Open
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
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_NORMALIZATION=unit
POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BATCH_SIZE=10
POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_TIMEOUT_SECONDS=30

# Optional workload-specific endpoint overrides.
# POWERCONTEXT_SERVER_INFERENCE_GENERATION_BASE_URL=http://127.0.0.1:8080/v1
# POWERCONTEXT_SERVER_INFERENCE_GENERATION_HEADERS={"Authorization":"Bearer replace-me"}
# POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL_SETTINGS={"max_tokens":4096}
# POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BASE_URL=http://127.0.0.1:8081/v1
# POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_HEADERS={"Authorization":"Bearer replace-me"}
# POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL_SETTINGS={"dimensions":2560}
# A dedicated reranker LLM is optional; without it, reranking reuses the generation model.
# POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL=openai-chat:local-reranker
# POWERCONTEXT_SERVER_INFERENCE_RERANK_BASE_URL=http://127.0.0.1:8082/v1
# POWERCONTEXT_SERVER_INFERENCE_RERANK_HEADERS={"Authorization":"Bearer replace-me"}
# POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL_SETTINGS={"max_tokens":256}
# POWERCONTEXT_SERVER_INFERENCE_RERANK_TIMEOUT_SECONDS=30
# POWERCONTEXT_SERVER_INFERENCE_RERANK_MAX_REQUESTS=2

# Provider A: OpenAI (enabled). Set OPENAI_API_KEY in the Server shell.
POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL=openai:gpt-4.1-mini
POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL=openai:text-embedding-3-small
Expand Down
45 changes: 43 additions & 2 deletions docs/en/development/pydantic-ai-inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,49 @@ export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_PROFILE_ID="project-embedding-v1"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_DIMENSION="1536"
```

Provider credentials remain in the environment variables understood by the selected Pydantic AI provider. They are
not fields on PowerContext models.
Each workload can target a different model service. Custom base URLs use the provider interface named by the model
identifier; use `openai-chat:<model>` for an OpenAI-compatible Chat Completions service, `openai:<model>` for an
OpenAI-compatible Responses or embeddings service, and `anthropic:<model>` for an Anthropic-compatible generation
service. The built-in reranker is an LLM listwise reranker, so its independent endpoint is also a Pydantic AI generation
endpoint rather than a cross-encoder `/rerank` API:

```bash
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL="openai-chat:generator"
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_BASE_URL="http://127.0.0.1:8080/v1"
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_HEADERS='{"Authorization":"Bearer generation-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL_SETTINGS='{"max_tokens":4096}'

export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL="openai:embedding"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BASE_URL="http://127.0.0.1:8081/v1"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_HEADERS='{"Authorization":"Bearer embedding-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL_SETTINGS='{"dimensions":1536}'

export POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL="openai-chat:reranker"
export POWERCONTEXT_SERVER_INFERENCE_RERANK_BASE_URL="http://127.0.0.1:8082/v1"
export POWERCONTEXT_SERVER_INFERENCE_RERANK_HEADERS='{"Authorization":"Bearer rerank-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL_SETTINGS='{"max_tokens":256}'
```

The header and model-settings values are JSON objects. Header values are treated as secrets by settings models and are
installed as static headers on the workload's provider client. They are not included in Pydantic AI request settings.
Do not put `extra_headers` inside a model-settings object; use the dedicated headers variable so configuration and log
redaction remain effective. Pydantic AI passes the remaining model settings through to the selected provider. The
reranker always fixes `temperature` to zero. A custom embedding base URL currently requires the OpenAI-compatible
embeddings interface.

A base URL may contain a gateway path prefix. The selected Pydantic AI provider still owns the operation suffix, such
as `/chat/completions`, `/responses`, or `/embeddings`; arbitrary operation-path rewriting is not supported.
Custom base URLs and static headers require an explicit OpenAI- or Anthropic-compatible model identifier so
PowerContext can construct the corresponding provider client.

When `RERANK_MODEL` is unset, LLM reranking reuses the generation model and base URL. Reranker headers and model
settings can still extend or override the generation configuration. A header override creates a separate provider
client for the rerank workload while retaining the generation model identifier and base URL. A separate reranker base
URL requires an explicit reranker model. The reranker timeout and request limit inherit their generation counterparts
unless they are set explicitly.

When no custom base URL or headers are needed, provider credentials remain in the environment variables understood by
the selected Pydantic AI provider.

The Server rejects a partial embedding profile. `embedding_model`, `embedding_profile_id`, and `embedding_dimension`
must be configured together. SQLite vector search uses that embedding configuration because the index dimension and
Expand Down
22 changes: 22 additions & 0 deletions docs/en/docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,26 @@ Server settings use the `POWERCONTEXT_SERVER_` prefix.
| `POWERCONTEXT_SERVER_RUNTIME_MEMORY_RERANK_CANDIDATE_LIMIT` | `30` | Coarse candidate pool supplied to the reranker |
| `POWERCONTEXT_SERVER_RUNTIME_SCHEDULE_SECONDS` | unset | Scheduler interval; unset disables scheduling |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL` | unset | Pydantic AI model identifier for Memory extraction |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_BASE_URL` | provider default | Custom generation provider base URL |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_HEADERS` | `{}` | JSON object of static generation client headers; values are secrets |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL_SETTINGS` | `{}` | JSON object of Pydantic AI generation model settings |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_TIMEOUT_SECONDS` | `30` | Generation timeout |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MAX_REQUESTS` | `2` | Maximum model requests in one generation operation |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL` | unset | Pydantic AI embedding model identifier |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BASE_URL` | provider default | Custom OpenAI-compatible embeddings base URL |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_HEADERS` | `{}` | JSON object of static embedding client headers; values are secrets |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL_SETTINGS` | `{}` | JSON object of Pydantic AI embedding model settings |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_PROFILE_ID` | unset | Stable embedding deployment identity |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_DIMENSION` | unset | Embedding vector dimension |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_NORMALIZATION` | `unit` | `unit` or `none` vector normalization |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_TIMEOUT_SECONDS` | `30` | Embedding timeout |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BATCH_SIZE` | `10` | Maximum texts sent in one embedding request |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL` | generation model | Optional dedicated Pydantic AI model for LLM reranking |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_BASE_URL` | inherited/provider default | Custom LLM reranker provider base URL |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_HEADERS` | `{}` | JSON object of static LLM reranker client headers; values are secrets |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL_SETTINGS` | `{}` | JSON object of Pydantic AI reranker model settings |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_TIMEOUT_SECONDS` | generation timeout | LLM reranker timeout |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MAX_REQUESTS` | generation request limit | Maximum model requests in one rerank operation |
| `POWERCONTEXT_SERVER_RUNTIME_EXPERIENCE_SCHEDULE_SECONDS` | unset | Experience incubation interval; unset disables that job |
| `POWERCONTEXT_SERVER_EXTERNAL_SKILLS` | unset | JSON object containing the host identity and explicit Agent Skill targets |

Expand Down Expand Up @@ -117,6 +135,10 @@ change stored Memory or indexes. Provider and structured-output failures remain
reranking when search must remain independent of model availability. See
[RFC 0080](/en/rfcs/0080_memory_search_reranking/) for the algorithm, concurrency, and API boundaries.

The built-in reranker is an LLM listwise reranker, not a dedicated cross-encoder protocol. By default it reuses the
generation model and its provider settings. Set `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL` to give that LLM operation
an independent model, base URL, headers, settings, timeout, and request limit.

The same configured generation model gates explicit Experience generation, managed Skill generation and evolution,
and external Skill import or fork. Without it, these operations return a capability error before persisting a
Candidate. Candidate Review, exact reads, and external Skill scan/list/resolve continue to work.
Expand Down
14 changes: 9 additions & 5 deletions docs/en/rfcs/0080_memory_search_reranking.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ structured generation request selects a sparse, ordered subset from that bounded
returns final hits.

The first policy is `powercontext.memory.rerank.listwise.v1`: retrieve up to 30 coarse candidates by default and let
the configured generation model select no more than the caller's requested `limit`. Reranking is disabled by default,
the configured LLM reranker select no more than the caller's requested `limit`. Reranking is disabled by default,
does not change stored Memory or indexes, and preserves every selected hit's exact Artifact, entry, and Revision
identity.

Expand Down Expand Up @@ -46,6 +46,9 @@ export POWERCONTEXT_SERVER_RUNTIME_MEMORY_RERANK_CANDIDATE_LIMIT=30
powercontext server run
```

To isolate reranking from other generation workloads, configure `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL` and its
provider settings instead. The built-in policy remains an LLM structured-generation operation in either form.

The existing search request remains unchanged:

```python
Expand All @@ -69,7 +72,7 @@ timeout and request bound and fixes temperature to zero. This improves repeatabi
deterministic.

Reranking is therefore appropriate when answer quality matters more than the added model latency and token cost. Keep
it disabled for low-latency lexical lookup or when no generation model is available.
it disabled for low-latency lexical lookup or when no LLM reranker is available.

## Observe a search

Expand All @@ -95,9 +98,10 @@ contract compatible. A benchmark can use the in-process trace to score the coars
| `memory_rerank_enabled` | `false` | Assemble and apply the listwise Memory reranker. |
| `memory_rerank_candidate_limit` | `30` | Coarse fused pool, from 1 through 100. |

The first implementation reuses `InferenceConfig.generation_model`, `generation_timeout_seconds`, and
`generation_max_requests`. Startup fails with a configuration error when reranking is enabled without a generation
model or an explicitly injected `MemoryReranker`.
By default the implementation reuses `InferenceConfig.generation_model` and its provider settings. A deployment may
instead configure the LLM reranker through `rerank_model`, `rerank_base_url`, `rerank_headers`,
`rerank_model_settings`, `rerank_timeout_seconds`, and `rerank_max_requests`. Startup fails with a configuration error
when reranking is enabled without a generation model, a rerank model, or an explicitly injected `MemoryReranker`.

An injected reranker is an application composition choice and is applied even when the environment flag is false. This
supports tests and deployments with a provider-specific adapter while keeping environment-driven composition explicit.
Expand Down
41 changes: 40 additions & 1 deletion docs/zh/development/pydantic-ai-inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,46 @@ export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_PROFILE_ID="project-embedding-v1"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_DIMENSION="1536"
```

provider credential 仍使用所选 Pydantic AI provider 支持的环境变量,不属于 PowerContext model 字段。
每类 workload 可以连接不同的模型服务。自定义 base URL 使用 model identifier 指定的 provider 接口:
OpenAI-compatible Chat Completions 服务使用 `openai-chat:<model>`,OpenAI-compatible Responses 或 embedding
服务使用 `openai:<model>`,Anthropic-compatible generation 服务使用 `anthropic:<model>`。内置 reranker 是 LLM
listwise reranker,因此它的独立 endpoint 也是 Pydantic AI generation endpoint,而不是 cross-encoder `/rerank`
API:

```bash
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL="openai-chat:generator"
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_BASE_URL="http://127.0.0.1:8080/v1"
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_HEADERS='{"Authorization":"Bearer generation-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL_SETTINGS='{"max_tokens":4096}'

export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL="openai:embedding"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BASE_URL="http://127.0.0.1:8081/v1"
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_HEADERS='{"Authorization":"Bearer embedding-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL_SETTINGS='{"dimensions":1536}'

export POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL="openai-chat:reranker"
export POWERCONTEXT_SERVER_INFERENCE_RERANK_BASE_URL="http://127.0.0.1:8082/v1"
export POWERCONTEXT_SERVER_INFERENCE_RERANK_HEADERS='{"Authorization":"Bearer rerank-secret"}'
export POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL_SETTINGS='{"max_tokens":256}'
```

header 和 model settings 都使用 JSON object。settings model 会将 header value 作为 secret 处理,并将它们作为
workload provider client 的静态 header;这些值不会进入 Pydantic AI request settings。不要在 model settings 中配置
`extra_headers`;使用独立的 headers 变量才能保留配置与日志脱敏语义。其余 model settings 由 Pydantic AI 传递给
所选 provider。reranker 始终将 `temperature` 固定为零。自定义 embedding base URL 目前要求服务实现
OpenAI-compatible embeddings 接口。

base URL 可以包含 gateway path prefix,但具体 operation suffix 仍由所选 Pydantic AI provider 决定,例如
`/chat/completions`、`/responses` 或 `/embeddings`;不支持任意改写 operation path。
自定义 base URL 或静态 header 时必须使用显式的 OpenAI- 或 Anthropic-compatible model identifier,PowerContext
才能创建对应的 provider client。

未设置 `RERANK_MODEL` 时,LLM rerank 复用 generation model 和 base URL;仍可通过 reranker headers 和 model
settings 扩展或覆盖 generation 配置。覆盖 header 时会为 rerank workload 创建独立 provider client,但保留
generation model identifier 和 base URL。独立的 reranker base URL 必须同时配置显式 reranker model。reranker
timeout 和 request limit 未显式设置时继承 generation 的对应配置。

不需要自定义 base URL 或 header 时,provider credential 仍使用所选 Pydantic AI provider 支持的环境变量。

Server 会拒绝不完整的 embedding profile。`embedding_model`、`embedding_profile_id` 和
`embedding_dimension` 必须一起配置。SQLite vector search 使用这组配置,因为 index dimension 必须与持久化向量一致。
Expand Down
22 changes: 22 additions & 0 deletions docs/zh/docs/reference/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,26 @@ Server 配置使用 `POWERCONTEXT_SERVER_` 前缀。
| `POWERCONTEXT_SERVER_RUNTIME_MEMORY_RERANK_CANDIDATE_LIMIT` | `30` | 交给 reranker 的粗排候选池大小 |
| `POWERCONTEXT_SERVER_RUNTIME_SCHEDULE_SECONDS` | 未设置 | Scheduler 间隔;未设置即不启用 |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL` | 未设置 | 用于 Memory extraction 的 Pydantic AI 模型标识 |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_BASE_URL` | provider 默认值 | 自定义 generation provider base URL |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_HEADERS` | `{}` | generation client 静态 header JSON object;value 按 secret 处理 |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MODEL_SETTINGS` | `{}` | Pydantic AI generation model settings JSON object |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_TIMEOUT_SECONDS` | `30` | Generation 超时 |
| `POWERCONTEXT_SERVER_INFERENCE_GENERATION_MAX_REQUESTS` | `2` | 单次 generation operation 的最大 model request 数量 |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL` | 未设置 | Pydantic AI embedding model 标识 |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BASE_URL` | provider 默认值 | 自定义 OpenAI-compatible embeddings base URL |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_HEADERS` | `{}` | embedding client 静态 header JSON object;value 按 secret 处理 |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_MODEL_SETTINGS` | `{}` | Pydantic AI embedding model settings JSON object |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_PROFILE_ID` | 未设置 | 稳定的 embedding deployment identity |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_DIMENSION` | 未设置 | embedding vector dimension |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_NORMALIZATION` | `unit` | `unit` 或 `none` vector normalization |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_TIMEOUT_SECONDS` | `30` | Embedding 超时 |
| `POWERCONTEXT_SERVER_INFERENCE_EMBEDDING_BATCH_SIZE` | `10` | 单次 embedding 请求最多发送的文本数量 |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL` | generation model | LLM rerank 可选的独立 Pydantic AI model |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_BASE_URL` | 继承值或 provider 默认值 | 自定义 LLM reranker provider base URL |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_HEADERS` | `{}` | LLM reranker client 静态 header JSON object;value 按 secret 处理 |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL_SETTINGS` | `{}` | Pydantic AI reranker model settings JSON object |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_TIMEOUT_SECONDS` | generation 超时 | LLM reranker 超时 |
| `POWERCONTEXT_SERVER_INFERENCE_RERANK_MAX_REQUESTS` | generation request limit | 单次 rerank operation 的最大 model request 数量 |
| `POWERCONTEXT_SERVER_RUNTIME_EXPERIENCE_SCHEDULE_SECONDS` | 未设置 | Experience 孵化间隔;未设置即不启用该 job |
| `POWERCONTEXT_SERVER_EXTERNAL_SKILLS` | 未设置 | 包含 host identity 和显式 Agent Skill targets 的 JSON object |

Expand Down Expand Up @@ -111,6 +129,10 @@ search request 最终 `limit` 的结果。它不会修改已存储 Memory 或索
显式返回;如果搜索必须独立于模型可用性,请关闭 rerank。算法、并发与 API 边界见
[RFC 0080](/zh/rfcs/0080_memory_search_reranking/)。

内置 reranker 是 LLM listwise reranker,不是独立的 cross-encoder protocol。默认复用 generation model 及其 provider
settings。设置 `POWERCONTEXT_SERVER_INFERENCE_RERANK_MODEL` 后,该 LLM operation 可以使用独立的 model、base URL、
headers、settings、timeout 和 request limit。

同一个 generation model 也控制显式 Experience generation、managed Skill generation/evolution,以及
external Skill import/fork。未配置模型时,这些 operation 会在持久化 Candidate 前返回 capability error;
Candidate Review、exact read 和 external Skill scan/list/resolve 仍可使用。
Expand Down
Loading
Loading