mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 10:17:55 +00:00
Merge remote-tracking branch 'origin/main' into branding-upd
# Conflicts: # docsgpt/core/models/anthropic.yaml # docsgpt/core/models/openai.yaml # frontend/src/admin/AdminUI.tsx
This commit is contained in:
commit
a25bec6821
300 files changed
+27029
-1745
No files matched your search
@@ -3,6 +3,10 @@ export default {
|
||||
"title": "🤖 Agent Basics",
|
||||
"href": "/Agents/basics"
|
||||
},
|
||||
"guardrails": {
|
||||
"title": "🛡️ Guardrails",
|
||||
"href": "/Agents/guardrails"
|
||||
},
|
||||
"api": {
|
||||
"title": "🔌 Agent API",
|
||||
"href": "/Agents/api"
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
---
|
||||
title: Agent Guardrails
|
||||
description: Scan user input, retrieved sources, tool results and answers with built-in checks — PII, secrets, banned terms, link policy, prompt injection, groundedness and an LLM judge — and choose to flag, redact or block. Includes the audit journal, instance floor and API reference.
|
||||
---
|
||||
|
||||
import { Callout, Tabs } from 'nextra/components';
|
||||
|
||||
# Agent Guardrails 🛡️
|
||||
|
||||
Guardrails are per-agent content controls that run **inside** an agent turn, at the points where text changes hands: when the user's question arrives, when retrieved documents are about to reach the model, when a tool returns, and when the answer is on its way out. Each control pairs a **check** (a detector) with a **stage** (where it runs) and an **action** (what happens on a match).
|
||||
|
||||
They apply everywhere the agent runs — the chat UI, the [Agent API](/Agents/api), the [OpenAI-compatible API](/Agents/openai-compatible), [webhooks](/Agents/webhooks), scheduled runs and the embeddable widget — and every decision is written to an audit journal you can review from the agent's logs page.
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Guardrails are a defence-in-depth layer, not a replacement for a well-written prompt or for tool approvals. The pattern and heuristic checks are deterministic and fast; the LLM judge is semantic but costs a model call. Start in **monitor mode**, read the journal, then promote to enforcement.
|
||||
</Callout>
|
||||
|
||||
## How a turn is scanned
|
||||
|
||||
An agent turn passes through four intervention points. A control attached to a stage sees the text at that stage and can leave it alone, mask parts of it, or stop the turn.
|
||||
|
||||
| Stage | What is scanned | `redact` does | `block` does |
|
||||
| --- | --- | --- | --- |
|
||||
| `input` | The user's question, before anything is sent to the model | The model and the stored conversation both receive the masked question | The turn ends immediately with the block message; nothing reaches the model |
|
||||
| `retrieval` | The retrieved document chunks, formatted as they will appear in the prompt | Masked in the prompt **and** in the sources shown to the user and stored with the conversation | The model is told the sources were withheld by policy; the user sees `[Withheld by a content policy.]` in place of each source |
|
||||
| `tool_result` | Each tool's result string, before it fans out to the model, the UI and the journal | The masked result is what the model and the user see | The result is replaced with a note telling the model it could not be used and must not speculate about its contents |
|
||||
| `output` | The answer as it streams from the model | Masked **before** the text leaves the server | The stream stops with the block message; any tokens already delivered are retracted from the client and the stored message |
|
||||
|
||||
A few details worth knowing:
|
||||
|
||||
- **Input redaction is what gets stored.** If a PII control redacts an email address in the question, the conversation history holds the redacted version. The raw text never lands in the database.
|
||||
- **Retrieval scanning covers custom prompts too.** If your prompt template interpolates documents itself (see [Customising prompts](/Guides/Customising-prompts)), the rendered documents are still scanned and the verdict is patched back into the prompt.
|
||||
- **Structured output is scanned whole.** When an agent has a JSON schema, redacting mid-token would produce invalid JSON, so the complete document is buffered and scanned once.
|
||||
- **Output blocks after streaming has begun are retractions.** Tokens on the wire cannot be recalled, so the server tells the client to clear the partial answer, replaces the persisted message with the block message, and clears any reasoning trace. On a reload the user sees only the block message.
|
||||
|
||||
### Streaming without leaks
|
||||
|
||||
Output controls run *before* a token is released. Deterministic checks hold a small lookback window (sized from the longest match any active check can produce, up to 8 KB for a PEM private key) and re-scan `held + new` on every chunk, so a card number or API key split across two stream deltas is still caught. Redacted spans are never cut in half: the release point is pulled back so a match is either fully masked or fully held.
|
||||
|
||||
Remote checks (the LLM judge) cannot afford a call per token, so the guard accumulates text to a sentence boundary (around 400 characters) and evaluates whole segments. A stream that never produces a sentence boundary is force-released past a 16 KB ceiling so it cannot stall forever.
|
||||
|
||||
The **groundedness** check only makes sense over a finished answer, so it is deferred to the end of the stream. A `block` from it is therefore always a retraction.
|
||||
|
||||
## Actions
|
||||
|
||||
| Action | Effect | Available for |
|
||||
| --- | --- | --- |
|
||||
| `flag` | Record the decision in the journal and the turn's activity log. Nothing about the answer changes. | Every check |
|
||||
| `redact` | Replace each matched span with a mask and continue. | Checks that report spans: `pii`, `secrets`, `denylist`, `url` |
|
||||
| `block` | Stop the turn and return the agent's block message. | Every check |
|
||||
|
||||
Within one stage the **most restrictive outcome wins**: if two controls match and one says block, the stage blocks. If several redact, all of their spans are masked, and overlapping spans are unioned so a short match can never leave part of a longer one in the clear.
|
||||
|
||||
Redaction masks are check-specific: PII uses the entity label (`[EMAIL]`, `[CREDIT_CARD]`), secrets use `[REDACTED]`, banned terms use `***`, and disallowed links use `<url redacted>`.
|
||||
|
||||
## Enforcement modes
|
||||
|
||||
| Mode | Behaviour |
|
||||
| --- | --- |
|
||||
| `monitor_only` (default) | Every control runs, but every action is downgraded to `flag`. Nothing is changed or blocked; the journal shows what *would* have happened. Streamed answers pass through untouched and are scanned once at the end. |
|
||||
| `scan_all` | Actions are enforced as configured. |
|
||||
|
||||
Monitor mode is the supported rollout path. Turn on the checks you want, run real traffic for a few days, look at the **Guardrail activity** panel for the control that is over-triggering, tune its settings, then switch to `scan_all`.
|
||||
|
||||
## Built-in checks
|
||||
|
||||
| Key | Label | Stages | Redacts | Remote | Typical latency |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `pii` | Personal information | input, retrieval, tool_result, output | Yes | No | ~2 ms |
|
||||
| `secrets` | Credentials and secrets | input, retrieval, tool_result, output | Yes | No | ~2 ms |
|
||||
| `denylist` | Banned terms | input, retrieval, tool_result, output | Yes | No | ~1 ms |
|
||||
| `url` | Link policy | input, retrieval, tool_result, output | Yes | No | ~2 ms |
|
||||
| `injection` | Prompt injection (heuristic) | input, retrieval, tool_result | No | No | ~3 ms |
|
||||
| `groundedness` | Grounding in sources | output | No | No | ~5 ms |
|
||||
| `policy` | Custom policy (LLM judge) | input, retrieval, tool_result, output | No | Yes | ~1 s |
|
||||
|
||||
The live catalog for your instance, including which checks the operator has allowed, is served by `GET /api/guardrails/catalog`.
|
||||
|
||||
### `pii` — Personal information
|
||||
|
||||
Pattern matching for structured identifiers. Reliable for the formats below; it does **not** find names or free-text addresses.
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `entities` | `["EMAIL", "PHONE", "US_SSN", "CREDIT_CARD"]` | Non-empty subset of `EMAIL`, `PHONE`, `US_SSN`, `CREDIT_CARD`, `IPV4`, `IBAN` |
|
||||
|
||||
Card numbers must be 13–19 digits and pass a Luhn check before they count, which keeps order numbers and long IDs from matching. Each match is reported under its entity name, so the journal tells you *which* kind of PII appeared.
|
||||
|
||||
### `secrets` — Credentials and secrets
|
||||
|
||||
No settings. Detects by known formats: AWS access keys, GitHub tokens, OpenAI and Anthropic keys, Slack tokens, Google API keys, JWTs, PEM private-key blocks (the whole armored block, not just the header) and generic `password=` / `api_key:` style assignments where only the value is masked.
|
||||
|
||||
### `denylist` — Banned terms
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `terms` | — (required) | 1–500 terms, each ≤ 128 characters |
|
||||
| `match` | `"word"` | `"word"` matches whole words only; `"substring"` matches anywhere |
|
||||
| `case_sensitive` | `false` | |
|
||||
|
||||
Useful for competitor names, internal codenames, or phrases you never want an agent to repeat.
|
||||
|
||||
### `url` — Link policy
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `allow_hosts` | `[]` | Up to 200 hosts. When non-empty, any link whose host is not in the list (or a subdomain of one) is disallowed |
|
||||
| `block_hosts` | `[]` | Up to 200 hosts. Links to these hosts (or their subdomains) are always disallowed |
|
||||
|
||||
At least one of the two lists is required. Hosts are matched against the parsed URL authority, so `https://allowed.com@evil.tld/` resolves to `evil.tld`. A URL that cannot be parsed is treated as disallowed.
|
||||
|
||||
### `injection` — Prompt injection (heuristic)
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `min_hits` | `1` | 1–10. Number of injection-like phrases needed before the check triggers |
|
||||
|
||||
Matches the phrasings that appear in real indirect-injection payloads: instruction overrides ("ignore previous instructions"), role hijacks ("you are now…"), system-prompt exfiltration ("reveal your instructions"), fake conversation turns (`system:` at the start of a line) and tool coercion ("you must immediately call the tool…"). It is most valuable at the `retrieval` and `tool_result` stages, where text an attacker may have planted arrives with the user's authority.
|
||||
|
||||
<Callout type="warning" emoji="⚠️">
|
||||
This check catches unobfuscated payloads only. A motivated attacker can evade it trivially. Pair it with the `policy` judge if you need semantic coverage.
|
||||
</Callout>
|
||||
|
||||
### `groundedness` — Grounding in sources
|
||||
|
||||
Output-only. Measures the lexical overlap between the answer and the retrieved sources using 4-word shingles and flags answers that fall below a threshold.
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `min_overlap` | `0.3` | 0–1. Fraction of the answer's shingles that must appear in the sources |
|
||||
| `min_words` | `25` | 1–1000. Shorter answers are skipped |
|
||||
| `require_retrieval` | `true` | When `true`, an answer produced with **no** retrieved sources triggers with category `NO_SOURCES` |
|
||||
|
||||
Lexical overlap is a proxy for support, not entailment. Keep this on `flag` until you have tuned the threshold against real traffic. When the sources contain no comparable text the check reports *not evaluated* rather than a verdict.
|
||||
|
||||
### `policy` — Custom policy (LLM judge)
|
||||
|
||||
Write a policy in plain language — a topic to stay off, a tone to hold, a rule to enforce — and a judge model decides whether the content breaks it.
|
||||
|
||||
| Setting | Default | Notes |
|
||||
| --- | --- | --- |
|
||||
| `policy` | — (required) | 10–2500 characters of policy text |
|
||||
| `confidence_threshold` | `0.7` | 0–1. The judge must both report a violation **and** be at least this confident |
|
||||
| `max_chars` | `8000` | 200–100000. Only the first `max_chars` of the content are sent to the judge |
|
||||
| `model` | `null` | Optional model id override for this control |
|
||||
|
||||
The judge is the instance's own model provider, so a self-hosted deployment gets a semantic guardrail with no extra vendor account. The model used is, in order: the control's `model`, then the instance-wide `GUARDRAILS_JUDGE_MODEL`, then the model the agent is answering with. Judge calls are tagged `guardrail` in token usage so their cost shows up separately from the agent's own generation.
|
||||
|
||||
The content is passed to the judge as untrusted data inside a delimited envelope, with fences and the envelope's own tags neutralised, and the judge is instructed to ignore any directions it finds inside. If the judge times out, errors, or returns something unparsable, the control reports *not evaluated* and the fail-open policy below decides what happens.
|
||||
|
||||
## When a check cannot run
|
||||
|
||||
A timeout, a provider error, or a missing judge model is **not** a clean pass. The control reports `not_evaluated`, the journal records it, and the agent's failure policy applies:
|
||||
|
||||
| Setting | Default | Meaning |
|
||||
| --- | --- | --- |
|
||||
| `fail_open` | `true` | Let the turn continue when a check could not run. Set to `false` to block the turn instead whenever a `block` **or** `redact` control could not run — fail-closed exists so that unscanned text never reaches the user, and a broken PII detector would otherwise release exactly what it was there to remove |
|
||||
| `timeout_ms` | `2000` | 100–60000. Deadline for the remote checks at one stage. Local pattern checks run inline and are not subject to it |
|
||||
|
||||
Remote controls at one stage run in parallel under a single deadline. At most 8 remote controls run per stage; any beyond that are reported as *not evaluated*.
|
||||
|
||||
## Configuring guardrails in the UI
|
||||
|
||||
Open the agent in the builder and expand the **Guardrails** section.
|
||||
|
||||
1. **Enable guardrails.** Nothing runs until this is on.
|
||||
2. **Enforcement mode.** Leave it on *Monitor only* while you calibrate; switch to *Enforce everywhere* when the journal looks right.
|
||||
3. **Checks.** Each check is a card with one chip per supported stage. Turning a chip on adds a control with the `flag` action; use the action selector on the chip to promote it to `redact` or `block`, and **Configure** to edit its settings. The card shows the approximate latency the check adds.
|
||||
4. **Blocked-response message.** Up to 500 characters, shown to the user whenever a control blocks. Defaults to *"Sorry, I can't help with that request."*
|
||||
5. **Continue if a check fails** and **Check timeout (ms)** map to `fail_open` and `timeout_ms`.
|
||||
|
||||
Checks that cannot run without settings (`denylist`, `url`, `policy`, and `pii` with no entities selected) are marked *Not configured* and block saving until they are filled in, so a half-configured control can never be published as if it were protecting you.
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Guardrails are the **agent owner's** policy. Team members with edit access can see the configuration but cannot change it — an editor who could clear a control would silently strip protection from everyone using the agent. Controls required by the instance floor (below) appear locked and cannot be removed.
|
||||
</Callout>
|
||||
|
||||
Guardrails also apply to a **draft** agent in the builder preview, which is the natural place to try a control before publishing.
|
||||
|
||||
## Configuring guardrails via the API
|
||||
|
||||
Guardrails live under `guardrails` in the agent's `config` field. Pass `config` as a JSON string when creating or updating an agent through `POST /api/create_agent` or `PUT /api/update_agent/<agent_id>` (the same multipart form the builder uses). `update_agent` replaces the whole `config`; send the complete object each time.
|
||||
|
||||
```json
|
||||
{
|
||||
"guardrails": {
|
||||
"enabled": true,
|
||||
"mode": "scan_all",
|
||||
"fail_open": true,
|
||||
"timeout_ms": 2000,
|
||||
"block_message": "Sorry, I can't help with that request.",
|
||||
"controls": [
|
||||
{ "check": "secrets", "stage": "output", "action": "redact" },
|
||||
{ "check": "pii", "stage": "input", "action": "redact",
|
||||
"settings": { "entities": ["EMAIL", "PHONE", "CREDIT_CARD"] } },
|
||||
{ "check": "injection", "stage": "retrieval", "action": "block",
|
||||
"settings": { "min_hits": 1 } },
|
||||
{ "check": "denylist", "stage": "output", "action": "redact",
|
||||
"settings": { "terms": ["Project Nimbus", "Acme Corp"], "match": "word" } },
|
||||
{ "check": "url", "stage": "output", "action": "redact",
|
||||
"settings": { "allow_hosts": ["docs.example.com", "example.com"] } },
|
||||
{ "check": "policy", "stage": "output", "action": "block",
|
||||
"settings": {
|
||||
"policy": "Never give legal, medical or investment advice. Never quote pricing that is not in the retrieved sources.",
|
||||
"confidence_threshold": 0.8
|
||||
} },
|
||||
{ "check": "groundedness", "stage": "output", "action": "flag",
|
||||
"settings": { "min_overlap": 0.3, "min_words": 25 } }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Tabs items={['cURL', 'Python']}>
|
||||
<Tabs.Tab>
|
||||
```bash
|
||||
curl -X PUT http://localhost:7091/api/update_agent/<agent_id> \
|
||||
-H "Authorization: Bearer <token>" \
|
||||
-F 'config={"guardrails":{"enabled":true,"mode":"monitor_only","controls":[{"check":"secrets","stage":"output","action":"redact"}]}}'
|
||||
```
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab>
|
||||
```python
|
||||
import json, requests
|
||||
|
||||
config = {"guardrails": {
|
||||
"enabled": True,
|
||||
"mode": "monitor_only",
|
||||
"controls": [{"check": "secrets", "stage": "output", "action": "redact"}],
|
||||
}}
|
||||
requests.put(
|
||||
"http://localhost:7091/api/update_agent/<agent_id>",
|
||||
headers={"Authorization": "Bearer <token>"},
|
||||
data={"config": json.dumps(config)},
|
||||
).raise_for_status()
|
||||
```
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
|
||||
Each control accepts `check`, `stage`, `action` (default `flag`), `enabled` (default `true`) and `settings`. Omitted top-level fields take the defaults shown above; `enabled` defaults to `false`.
|
||||
|
||||
Writes are validated **strictly**. The request is rejected with HTTP 400 and the message *"Invalid config: one or more guardrail controls failed validation."* when:
|
||||
|
||||
- a `check` is unknown, or is not allowed by the instance's `GUARDRAILS_CHECKS_ENABLED`;
|
||||
- a check is attached to a stage it does not support (for example `groundedness` at `input`);
|
||||
- `redact` is requested on a check that reports no spans (`injection`, `groundedness`, `policy`);
|
||||
- a control's settings are out of range, or a required setting is missing;
|
||||
- the same `(check, stage)` pair appears twice, or there are more than 50 controls;
|
||||
- `mode`, `timeout_ms` or `block_message` is out of bounds.
|
||||
|
||||
Reads are **lenient**: a stored control that has stopped validating (its check was disallowed by the operator, or removed in an upgrade) is dropped on its own and logged, and the remaining controls keep running. Agent export files carry `config`; on import an invalid guardrails block is dropped with a warning rather than failing the import.
|
||||
|
||||
### What a blocked turn looks like to a client
|
||||
|
||||
On the streaming endpoints, a block produces two final events. The first tells the client to retract anything it has rendered; the second carries the operator's block message as a user-facing error:
|
||||
|
||||
```json
|
||||
{"type": "guardrail", "guardrail": {"stage": "output", "categories": ["AWS_ACCESS_KEY"], "checks": ["secrets"]}, "retract": true}
|
||||
{"type": "error", "error": "Sorry, I can't help with that request."}
|
||||
```
|
||||
|
||||
The DocsGPT chat UI and the React widget handle both. For webhook and scheduled runs, the run is recorded with the block message and none of the blocked text is stored.
|
||||
|
||||
## The audit journal
|
||||
|
||||
Every control that **triggers**, and every control that **could not run**, writes a row to the `guardrail_events` table — in both enforcement modes, and for `flag` actions as well as `redact` and `block`. A streamed answer that re-matches the same span on every chunk produces one row, not one per chunk. Rows also flow into the turn's activity log under the `guardrail` component, so a decision is visible next to the tool calls and retrieval it belongs to.
|
||||
|
||||
### Guardrail activity panel
|
||||
|
||||
Open an agent's **Logs** page. Below the usage logs, the **Guardrail activity** panel shows, for a trailing window of 7, 30 or 90 days:
|
||||
|
||||
- four totals — **Blocked**, **Redacted**, **Flagged** and **Not evaluated** — because "we refused to answer", "we masked something", "we noticed something" and "a check silently stopped working" are four different problems;
|
||||
- a per-check breakdown, so you can see which control is doing the firing;
|
||||
- the most recent 100 decisions, filterable by check and outcome, each with its stage, category (`EMAIL`, `INSTRUCTION_OVERRIDE`, `UNGROUNDED`, …) and the detector's one-line detail.
|
||||
|
||||
### Journal API
|
||||
|
||||
| Endpoint | Purpose |
|
||||
| --- | --- |
|
||||
| `GET /api/guardrails/catalog` | Available checks (with stages, redaction support, latency hint and remote flag), stages, modes, allowed actions per stage, PII entity names, the default block message, and which `(check, stage)` pairs the instance floor claims. |
|
||||
| `GET /api/guardrails/events?agent_id=<id>&limit=100&offset=0` | Decisions for one agent, newest first. `limit` is capped at 500. |
|
||||
| `GET /api/guardrails/summary?days=30&agent_id=<id>` | Totals and a `breakdown` grouped by check, stage, action, outcome and category. `agent_id` is optional; `days` is capped at 365. |
|
||||
|
||||
All three require a user token. Event rows are scoped to the **requesting user**: on a shared agent you see the decisions made on your own conversations, not other members'. Responses never include the agent's API key or the matched text.
|
||||
|
||||
### What is stored, and for how long
|
||||
|
||||
By default the journal records *that* something matched — check, stage, action, outcome, category, a score where the check produces one, a match count and a short detail string — but **not the text**. Pre-redaction text is exactly what a PII control exists to keep out of storage. Set `GUARDRAILS_STORE_SCANNED_TEXT=true` to persist a sample of the first matched value (up to 200 characters) alongside each row for forensic review; it is stored in the database but never returned by the API.
|
||||
|
||||
Rows older than `GUARDRAILS_EVENTS_RETENTION_DAYS` (default 30) are purged by a daily Celery beat task. The `message_id` link is set to `NULL` rather than cascading when a conversation is deleted, so the compliance trail outlives the conversation it came from.
|
||||
|
||||
## Instance settings
|
||||
|
||||
Operators control guardrails deployment-wide with these settings:
|
||||
|
||||
| Setting | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `GUARDRAILS_ENABLED` | `true` | Master switch. `false` disables every stage on every agent; the builder shows a notice explaining that nothing configured will run. |
|
||||
| `GUARDRAILS_CHECKS_ENABLED` | `[]` | Allowlist of check keys. Empty means every registered check. A disallowed check cannot be saved through the API, and existing controls that use it are dropped on read. |
|
||||
| `GUARDRAILS_FLOOR` | `{}` | A guardrails config fragment every agent inherits and cannot weaken. See below. |
|
||||
| `GUARDRAILS_JUDGE_MODEL` | unset | Model id for `policy` controls that do not set their own `model`. Unset reuses the agent's model. |
|
||||
| `GUARDRAILS_STORE_SCANNED_TEXT` | `false` | Persist a sample of matched text with each journal row. |
|
||||
| `GUARDRAILS_EVENTS_RETENTION_DAYS` | `30` | Journal retention. Minimum 1. |
|
||||
|
||||
List and dict settings are read from the environment as JSON, for example:
|
||||
|
||||
```bash
|
||||
GUARDRAILS_CHECKS_ENABLED='["pii", "secrets", "denylist", "url", "injection", "groundedness"]'
|
||||
```
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Leaving `policy` out of `GUARDRAILS_CHECKS_ENABLED` is how an air-gapped or privacy-sensitive deployment guarantees that no user text is sent to a judge model, regardless of what agent owners configure.
|
||||
</Callout>
|
||||
|
||||
### The instance floor
|
||||
|
||||
`GUARDRAILS_FLOOR` lets an operator impose a minimum policy on every agent. It uses the same shape as an agent's `guardrails` object and **must include `"enabled": true`** — without it the floor parses but applies to nothing, and a warning is logged.
|
||||
|
||||
```bash
|
||||
GUARDRAILS_FLOOR='{
|
||||
"enabled": true,
|
||||
"mode": "scan_all",
|
||||
"fail_open": false,
|
||||
"controls": [
|
||||
{"check": "secrets", "stage": "output", "action": "redact"},
|
||||
{"check": "secrets", "stage": "tool_result", "action": "redact"},
|
||||
{"check": "injection", "stage": "retrieval", "action": "block"}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
The floor is merged into each agent's own configuration at run time. An agent may tighten, never loosen:
|
||||
|
||||
- Guardrails are forced on for every agent, even one whose owner never enabled them.
|
||||
- If the floor's mode is `scan_all`, the merged mode is `scan_all`. Otherwise the agent's mode stands.
|
||||
- If the floor sets `fail_open: false`, the agent is fail-closed. The merged `timeout_ms` is the larger of the two.
|
||||
- Floor controls the agent does not define are added.
|
||||
- Where both define the same `(check, stage)`, the floor's **settings** are authoritative and the **stricter action** wins (`block` > `redact` > `flag`). The two settings dicts are deliberately not merged: adding to `denylist.terms` tightens, but adding to `url.allow_hosts` loosens, so an agent that could edit floor settings could always find a loosening edit. An agent that needs different settings attaches its own control at a stage the floor does not claim.
|
||||
|
||||
In the builder, floor controls appear as active and locked. The catalog exposes only which `(check, stage)` pairs the floor claims and their action — the floor's settings (banned-term lists, policy prompts) stay server-side so they cannot be read and evaded by any authenticated user.
|
||||
|
||||
The floor also applies to the individual AI Agent nodes inside a workflow, which do not otherwise carry per-agent controls (see below).
|
||||
|
||||
## Scope and limitations
|
||||
|
||||
- **Workflow agents** run the `input` stage with their own controls, but the AI Agent nodes inside the workflow run only the instance floor, not the parent agent's controls. Aggregate output guarding across a workflow is not yet wired.
|
||||
- **Pattern checks match formats, not meaning.** `pii` does not find names; `injection` misses obfuscated payloads; `groundedness` measures word overlap, not truth. Use `policy` where you need a semantic judgement, and keep an eye on the *Not evaluated* count when you do.
|
||||
- **Redaction is best-effort against structured identifiers.** A value that does not match a known format passes through. Treat `redact` as a safety net, not as a data-loss-prevention guarantee.
|
||||
- **Latency.** Local checks add low single-digit milliseconds. A `policy` control adds a model round trip per scanned segment, and on the `output` stage it holds the stream until each sentence boundary has been judged.
|
||||
|
||||
## Extending: writing your own check
|
||||
|
||||
Checks are plain Python classes registered with a small registry, mirroring how chunkers and retrievers are pluggable. Subclass `GuardrailCheck` from `docsgpt.guardrails`, declare the stages you support, implement `scan`, and register it:
|
||||
|
||||
```python
|
||||
from docsgpt.guardrails import GuardrailCheck, GuardrailCreator, Stage
|
||||
from docsgpt.guardrails.types import CheckOutcome, Span
|
||||
|
||||
|
||||
class TicketIdCheck(GuardrailCheck):
|
||||
name = "ticket_id"
|
||||
label = "Internal ticket ids"
|
||||
description = "Masks references to internal tracker tickets."
|
||||
supported_stages = {Stage.OUTPUT, Stage.TOOL_RESULT}
|
||||
supports_redaction = True # scan() reports spans
|
||||
latency_hint_ms = 1
|
||||
max_match_chars = 16 # longest match; sizes the streaming window
|
||||
|
||||
def scan(self, text, stage, context):
|
||||
import re
|
||||
spans = [
|
||||
Span(m.start(), m.end(), "TICKET_ID", replacement="[TICKET]")
|
||||
for m in re.finditer(r"\bOPS-\d{3,6}\b", text)
|
||||
]
|
||||
if not spans:
|
||||
return CheckOutcome.clean()
|
||||
return CheckOutcome.hit(categories=["TICKET_ID"], spans=spans,
|
||||
detail=f"{len(spans)} ticket id(s)")
|
||||
|
||||
|
||||
GuardrailCreator.register(TicketIdCheck.name, TicketIdCheck)
|
||||
```
|
||||
|
||||
Override `validate_settings` to strictly validate and normalise per-control settings on write, set `remote = True` for anything that makes a network call (so it runs under the stage deadline), and set `requires_complete_text = True` if the verdict is only meaningful over a finished answer. `max_match_chars` must cover the longest span the check can report, or the streaming guard may release the tail of a match before scanning it. Once registered, the check appears in the catalog and the builder automatically.
|
||||
@@ -88,6 +88,7 @@ Admins get a dashboard backed by a REST surface under `/api/admin` (every endpoi
|
||||
| `GET` | `/api/admin/audit` | Authentication/admin audit feed. |
|
||||
| `GET` | `/api/admin/devices/audit` | Remote-device audit feed. |
|
||||
| `GET` | `/api/admin/teams` | Instance-wide oversight of all teams. |
|
||||
| `GET` `PUT` `DELETE` | `/api/admin/quotas/...` | [Usage quotas](/Deploying/Usage-Quotas) for the instance, teams and users. |
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Deactivating a user via the dashboard works for any auth type, while OIDC deployments can also offboard through [SCIM](/Deploying/OIDC-SSO#scim-user-provisioning). Both revoke live sessions immediately.
|
||||
@@ -141,9 +142,10 @@ Sharing rules:
|
||||
|
||||
## Audit log
|
||||
|
||||
Access-control actions are appended to the `auth_events` table alongside the [authentication events](/Deploying/OIDC-SSO#login-auditing). This includes admin actions — `admin_user_activated` / `admin_user_deactivated`, `admin_sessions_revoked`, `role_granted` / `role_revoked` (with `metadata.source` = `manual` or `oidc_group`) — and team events (`team.create`, `team.member_add`, `team.member_role`, `team.member_remove`, `team.share`, `team.unshare`, `team.transfer_owner`, `team.delete`). The acting admin is recorded in the event metadata.
|
||||
Access-control actions are appended to the `auth_events` table alongside the [authentication events](/Deploying/OIDC-SSO#login-auditing). This includes admin actions — `admin_user_activated` / `admin_user_deactivated`, `admin_sessions_revoked`, `role_granted` / `role_revoked` (with `metadata.source` = `manual` or `oidc_group`), `quota_policy_set` / `quota_policy_deleted` — and team events (`team.create`, `team.member_add`, `team.member_role`, `team.member_remove`, `team.share`, `team.unshare`, `team.transfer_owner`, `team.delete`). The acting admin is recorded in the event metadata.
|
||||
|
||||
## Related
|
||||
|
||||
- [SSO with OIDC](/Deploying/OIDC-SSO) — sign-in, group allowlists, and the `auth_events` table.
|
||||
- [Usage Quotas](/Deploying/Usage-Quotas) — token and cost limits per user and per team.
|
||||
- [App Configuration](/Deploying/DocsGPT-Settings) — the full settings reference.
|
||||
@@ -39,13 +39,14 @@ On a machine with internet access, pull the images and save them to one file:
|
||||
```bash
|
||||
TAG=latest # or a release, e.g. 0.19.0
|
||||
docker pull arc53/docsgpt:$TAG
|
||||
docker pull arc53/docsgpt-fe:$TAG
|
||||
docker pull redis:6-alpine
|
||||
docker pull postgres:16-alpine
|
||||
docker save -o docsgpt-images.tar \
|
||||
arc53/docsgpt:$TAG arc53/docsgpt-fe:$TAG redis:6-alpine postgres:16-alpine
|
||||
arc53/docsgpt:$TAG redis:6-alpine postgres:16-alpine
|
||||
```
|
||||
|
||||
The backend image serves the web UI too, so the standalone stack needs no frontend image. Add `arc53/docsgpt-fe:$TAG` only if you run the checkout Compose files or Kubernetes, which use it.
|
||||
|
||||
Copy `docsgpt-images.tar` and the [standalone Compose file](/Deploying/Docker-Deploying#quickest-setup-pre-built-images-no-checkout) into the air-gapped network, then load the images (or push them to your internal registry):
|
||||
|
||||
```bash
|
||||
|
||||
@@ -78,7 +78,7 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a
|
||||
|
||||
3. **Embedding Model (no action needed):**
|
||||
|
||||
The embedding model is downloaded automatically the first time you ingest a document, and cached under `models/` in the repository root for subsequent runs. Set `EMBEDDINGS_CACHE_DIR` to use another directory.
|
||||
The embedding model is downloaded automatically the first time you ingest a document, and cached for subsequent runs under `models/` in the data home: the repository root, unless `DOCSGPT_HOME` points elsewhere. Set `EMBEDDINGS_CACHE_DIR` to use another directory.
|
||||
|
||||
For an offline or air-gapped machine, fetch it ahead of time instead:
|
||||
|
||||
@@ -119,7 +119,34 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a
|
||||
|
||||
5. **Run the Backend:**
|
||||
|
||||
For local development, run the ASGI composition under uvicorn. It serves the **whole** application, hot-reloads on source changes, and matches the production runtime:
|
||||
One command runs the API and the worker from this checkout, each restarting when you save a file:
|
||||
|
||||
```bash
|
||||
docsgpt dev
|
||||
```
|
||||
|
||||
Both run as children of that terminal, with their output interleaved and labelled, and Ctrl-C stops
|
||||
them together. Useful flags:
|
||||
|
||||
| Flag | What it does |
|
||||
| --- | --- |
|
||||
| `--ui` | also start the Vite dev server, so the whole app runs from one command |
|
||||
| `--mock-llm` | run `scripts/mock_llm.py` and point DocsGPT at it, so no API key is needed |
|
||||
| `--no-worker` | leave the worker to you, for instance when debugging it in your editor |
|
||||
| `--no-reload` | do not restart anything on save |
|
||||
| `--port` | serve the API somewhere other than 7091 |
|
||||
|
||||
`docsgpt dev` is for a checkout. `docsgpt up --native`, by contrast, installs supervised services
|
||||
that outlive the shell — see [Run it as services](/Deploying/Pip-Install#run-it-as-services-without-docker).
|
||||
|
||||
<Callout type="info">
|
||||
`docsgpt doctor` checks the things that usually break a new setup: whether PostgreSQL answers and
|
||||
its schema matches this version, whether Redis answers, whether a model provider is configured,
|
||||
and whether the port is free. Run it first when something does not start.
|
||||
</Callout>
|
||||
|
||||
To run the two processes yourself instead, start the ASGI composition under uvicorn. It serves the
|
||||
**whole** application, hot-reloads on source changes, and matches the production runtime:
|
||||
|
||||
```bash
|
||||
uvicorn docsgpt.asgi:asgi_app --host 0.0.0.0 --port 7091 --reload
|
||||
@@ -135,7 +162,7 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a
|
||||
|
||||
But it serves **only** the WSGI Flask app and omits the native-async routes mounted on the ASGI shell in `docsgpt/asgi.py`: the `/mcp` FastMCP endpoint, the chat reconnect reader `GET /api/messages/<id>/events`, the notification stream `GET /api/events`, the remote-device command stream `GET /api/devices/sessions/<id>/events`, and artifact downloads `GET /api/artifacts/<id>/download`. Under `flask run` those paths return 404 — chat still works (`POST /stream` is a Flask route), but live notifications, stream auto-resume, paired devices and artifact downloads don't. Use `flask run` only when you don't need them.
|
||||
|
||||
6. **Start the Celery Worker:**
|
||||
6. **Start the Celery Worker** (not needed if you used `docsgpt dev`)**:**
|
||||
|
||||
Open a new terminal window (and activate your virtual environment if you used one). Start the Celery worker to handle background tasks:
|
||||
|
||||
@@ -153,10 +180,14 @@ To run the DocsGPT backend locally, you'll need to set up a Python environment a
|
||||
|
||||
**Running in Debugger (VSCode):**
|
||||
|
||||
For easier debugging, you can launch the Flask app and Celery worker directly from VSCode's debugger.
|
||||
For easier debugging, you can launch the API and the Celery worker directly from VSCode's debugger.
|
||||
|
||||
* Press <kbd>Shift</kbd> + <kbd>Cmd</kbd> + <kbd>D</kbd> (macOS) or <kbd>Shift</kbd> + <kbd>Windows</kbd> + <kbd>D</kbd> (Windows) to open the Run and Debug view.
|
||||
* You should see configurations named "Flask" and "Celery". Select the desired configuration and click the "Start Debugging" button (green play icon).
|
||||
* You should see configurations named "API (uvicorn)" and "Celery worker", and a compound "DocsGPT: Full Stack" that starts them with the frontend. Select one and click the "Start Debugging" button (green play icon).
|
||||
|
||||
The API configuration runs the same ASGI app as production, so the routes mounted on the ASGI shell
|
||||
work under the debugger. It deliberately runs without `--reload`: the reloader restarts the server in
|
||||
a child process, which your breakpoints would not be attached to.
|
||||
|
||||
## 3. Start the Frontend
|
||||
|
||||
@@ -207,3 +238,16 @@ To run the DocsGPT frontend locally, you'll need Node.js and npm (Node Package M
|
||||
This command will start the Vite development server. The frontend application will typically be accessible at [http://localhost:5173/](http://localhost:5173/). The terminal will display the exact URL where the frontend is running.
|
||||
|
||||
With both the backend and frontend running, you should now have a fully functional DocsGPT development environment. You can access the application in your browser at [http://localhost:5173/](http://localhost:5173/) and start developing!
|
||||
|
||||
## Working on two branches at once
|
||||
|
||||
Each install keeps its own directory and its own services, so a second branch can run beside the
|
||||
first as long as it gets its own port:
|
||||
|
||||
```bash
|
||||
docsgpt dev --port 7092 # a second checkout, second terminal
|
||||
docsgpt up --native --dir ~/.docsgpt/review --port 7092 # or a second installed copy
|
||||
```
|
||||
|
||||
A native install in another directory gets its own service names, so the two never write over each
|
||||
other's units. `docsgpt status --dir ~/.docsgpt/review` reports on that one alone.
|
||||
@@ -17,14 +17,122 @@ Docker is the recommended method for deploying DocsGPT, providing a consistent a
|
||||
|
||||
**Important Note for Windows Users:** Docker Desktop on Windows generally requires the WSL 2 backend to function correctly, especially when using features like host networking which are utilized in DocsGPT's Docker Compose setup. Ensure WSL 2 is enabled and configured in Docker Desktop settings.
|
||||
|
||||
## Run it with `docsgpt up`
|
||||
|
||||
The `docsgpt` Python package can set up and run the stack described below for
|
||||
you. It needs Docker with Compose 2.24 or newer. The installer gets
|
||||
[uv](https://docs.astral.sh/uv/), installs the package with it and runs
|
||||
`docsgpt up`:
|
||||
|
||||
macOS and Linux:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://docs.ac/install | bash
|
||||
```
|
||||
|
||||
Windows (PowerShell):
|
||||
|
||||
```powershell
|
||||
irm https://docs.ac/install.ps1 | iex
|
||||
```
|
||||
|
||||
Both scripts are attached to every [release](https://github.com/arc53/DocsGPT/releases)
|
||||
as `install.sh` and `install.ps1`. To install the package yourself instead
|
||||
(Python 3.12 or newer; uv brings one when it is missing):
|
||||
|
||||
```bash
|
||||
uv tool install docsgpt # or: pipx install docsgpt
|
||||
docsgpt up
|
||||
```
|
||||
|
||||
`docsgpt up` keeps the stack in `~/.docsgpt/server` (`/opt/docsgpt` when run as
|
||||
root on Linux; `--dir` or `DOCSGPT_HOME` choose another folder): the Compose
|
||||
file of the installed version, a `.env` with your settings and the generated
|
||||
secrets, and `install.json`. Data lives in named Docker volumes. The first run
|
||||
asks two questions:
|
||||
|
||||
- **Who should reach DocsGPT:** only this computer; other machines on the
|
||||
network (plain HTTP, with `AUTH_TYPE=simple_jwt` and an access token); or a
|
||||
domain name with HTTPS (Caddy gets the certificate, access token as well).
|
||||
- **Which model provider:** the DocsGPT public API (no key needed), OpenAI,
|
||||
Anthropic, Google Gemini, OpenRouter, Groq, or an OpenAI-compatible server
|
||||
such as Ollama or vLLM.
|
||||
|
||||
Flags answer the same questions, for scripts and servers:
|
||||
|
||||
```bash
|
||||
docsgpt up --yes --domain docs.example.com --provider openai --api-key "$OPENAI_API_KEY"
|
||||
```
|
||||
|
||||
Running `docsgpt up` again is safe: it keeps `.env` and the secrets and runs
|
||||
the images of the installed package version. `docsgpt up --reconfigure` asks
|
||||
the questions again.
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| `docsgpt status` | Version, address, containers, and whether the API answers |
|
||||
| `docsgpt logs [-f] [service]` | Container logs |
|
||||
| `docsgpt token` | The access token, for installs reachable beyond this computer |
|
||||
| `docsgpt open` | Open DocsGPT in the browser |
|
||||
| `docsgpt env set KEY=VALUE` | Change a setting; `docsgpt up` applies it |
|
||||
| `docsgpt upgrade` | Upgrade the package (for `uv tool` installs) and restart on the new version |
|
||||
| `docsgpt down` | Stop the stack; data and settings stay |
|
||||
| `docsgpt uninstall [--purge]` | Remove the containers; `--purge` also deletes the settings and all data |
|
||||
|
||||
### Backups
|
||||
|
||||
`docsgpt backup` writes one archive holding a dump of the database and a tar of
|
||||
each data volume (`indexes`, `inputs`, `vectors`):
|
||||
|
||||
```bash
|
||||
docsgpt backup # into <stack>/backups
|
||||
docsgpt backup --out /mnt/backups # somewhere else, e.g. a mounted disk
|
||||
```
|
||||
|
||||
While the archive is made, the backend and the worker stop and start again, so
|
||||
the database dump and the files in the volumes describe the same moment; Postgres
|
||||
itself keeps running. On a small install that pause is seconds, but count on it
|
||||
if you run `docsgpt backup` from cron. The archive is written readable only by
|
||||
the user who took it.
|
||||
|
||||
The archive does **not** include `.env`, because that file holds the install's
|
||||
secrets. `docsgpt backup --with-settings` puts it in, for when the archive
|
||||
itself is stored somewhere private. Keep `.env` safe separately otherwise: the
|
||||
database password in it is what an existing Postgres volume expects.
|
||||
|
||||
Restoring replaces the data in an install:
|
||||
|
||||
```bash
|
||||
docsgpt restore ~/.docsgpt/server/backups/docsgpt-20260916-120000.tar.gz
|
||||
```
|
||||
|
||||
It asks first, then stops the stack, puts the volumes and the database back, and
|
||||
starts DocsGPT again. `--yes` skips the question for scripts. A backup taken
|
||||
with a newer DocsGPT is refused, since its data may not fit this version's
|
||||
schema; upgrade first, or pass `--force` if you know the two match.
|
||||
|
||||
The Postgres data directory itself is not archived: the dump is the database
|
||||
backup, and copying a directory Postgres is writing to would capture a torn
|
||||
copy. Caddy's certificates are not archived either, as it obtains them again.
|
||||
|
||||
More `docsgpt up` options: `--port`, `--docling` (the image with the docling
|
||||
parser engine and OCR), `--image-tag develop` (follow the `main` branch) and
|
||||
`--adopt` (manage a stack you started from the standalone Compose file in
|
||||
another folder; both use the same data volumes). For Ollama on the same
|
||||
machine, use the base URL `http://host.docker.internal:11434/v1`; on Linux,
|
||||
also make Ollama listen beyond localhost (`OLLAMA_HOST=0.0.0.0`).
|
||||
|
||||
## Quickest Setup: Pre-built Images, No Checkout
|
||||
|
||||
Every release publishes ready-to-run images to Docker Hub (`arc53/docsgpt`,
|
||||
`arc53/docsgpt-fe`) and GitHub Container Registry (`ghcr.io/arc53/docsgpt`,
|
||||
`ghcr.io/arc53/docsgpt-fe`) for `linux/amd64` and `linux/arm64`. The images
|
||||
contain everything the default configuration needs (embedding models,
|
||||
tokenizers, tiktoken's encoding), so a fresh container makes no downloads on
|
||||
first use. You do not need the source tree to run them:
|
||||
`ghcr.io/arc53/docsgpt-fe`) for `linux/amd64` and `linux/arm64`.
|
||||
`arc53/docsgpt` runs the API, serves the web UI and runs the worker;
|
||||
`arc53/docsgpt-fe` is the separate frontend image the checkout Compose files
|
||||
and Kubernetes use. The images contain everything the default configuration
|
||||
needs (embedding models, tokenizers, tiktoken's encoding), so a fresh
|
||||
container makes no downloads on first use. You do not need the source tree to
|
||||
run them:
|
||||
|
||||
1. **Download the standalone Compose file** (also attached to every
|
||||
[release](https://github.com/arc53/DocsGPT/releases)):
|
||||
@@ -52,7 +160,9 @@ first use. You do not need the source tree to run them:
|
||||
docker compose -f docker-compose-standalone.yaml up -d
|
||||
```
|
||||
|
||||
Then open [http://localhost:5173/](http://localhost:5173/). Data lives in
|
||||
Then open [http://localhost:7091/](http://localhost:7091/). The web UI and
|
||||
the API share that port, which is published on `127.0.0.1`: only this
|
||||
machine can reach it until you change `DOCSGPT_BIND` (below). Data lives in
|
||||
named Docker volumes; `docker compose -f docker-compose-standalone.yaml down`
|
||||
keeps it and `down -v` removes it.
|
||||
|
||||
@@ -66,6 +176,77 @@ the shell, e.g. `DOCSGPT_IMAGE_TAG=0.20.0 DOCSGPT_IMAGE_VARIANT=-docling`.
|
||||
The same two variables drive `deployment/docker-compose-hub.yaml` in a
|
||||
checkout.
|
||||
|
||||
### Opening it from other machines
|
||||
|
||||
Publish the port on every interface and turn on authentication in `.env`:
|
||||
|
||||
```bash
|
||||
DOCSGPT_BIND=0.0.0.0
|
||||
AUTH_TYPE=simple_jwt
|
||||
JWT_SECRET_KEY=<a long random value, e.g. openssl rand -hex 32>
|
||||
```
|
||||
|
||||
Then run `docker compose -f docker-compose-standalone.yaml up -d` again. The UI
|
||||
takes its API address from the page it was loaded from, so
|
||||
`http://<server-address>:7091/` works without further settings. Without
|
||||
`AUTH_TYPE`, anyone who can reach the port can use DocsGPT.
|
||||
|
||||
With `simple_jwt` the UI asks for a token, which the backend prints when it
|
||||
starts: `docker compose -f docker-compose-standalone.yaml logs backend | grep "Simple JWT"`.
|
||||
The token is signed with `JWT_SECRET_KEY`. Without that setting each container
|
||||
generates its own secret, and a re-created container (after `pull` or a
|
||||
settings change) gets a new one and so a new token. Over plain HTTP the token
|
||||
travels as readable text; outside a trusted network, use HTTPS as below.
|
||||
`DOCSGPT_PORT` changes the host port (default `7091`). See
|
||||
[Authentication Settings](/Deploying/DocsGPT-Settings#authentication-settings) for the other modes.
|
||||
|
||||
### HTTPS with your own domain
|
||||
|
||||
The Compose file has an optional Caddy service that obtains and renews a
|
||||
Let's Encrypt certificate and proxies to the backend.
|
||||
|
||||
1. Point the domain's DNS records at the machine and open ports 80 and 443.
|
||||
2. Add to `.env`:
|
||||
|
||||
```bash
|
||||
COMPOSE_PROFILES=https
|
||||
DOCSGPT_DOMAIN=docs.example.com
|
||||
AUTH_TYPE=simple_jwt
|
||||
JWT_SECRET_KEY=<a long random value, e.g. openssl rand -hex 32>
|
||||
```
|
||||
|
||||
3. Run `docker compose -f docker-compose-standalone.yaml up -d` and open
|
||||
`https://docs.example.com/`.
|
||||
|
||||
`COMPOSE_PROFILES=https` in `.env` makes every later `up`, `down` and `logs`
|
||||
include Caddy. Leave `DOCSGPT_BIND` at its default: Caddy reaches the backend
|
||||
over the Compose network.
|
||||
|
||||
### Database password
|
||||
|
||||
The Postgres password defaults to `docsgpt`; the database is only reachable
|
||||
inside the Compose network. To use your own, set `POSTGRES_PASSWORD` in `.env`
|
||||
before the first start, with URL-safe characters (e.g. `openssl rand -hex 24`).
|
||||
Postgres reads it only when its volume is created, so changing it later does
|
||||
not change the existing database's password.
|
||||
|
||||
### Upgrading from an earlier standalone file
|
||||
|
||||
Before this change the standalone file ran a separate frontend container on
|
||||
port 5173 and published both ports on every interface. After downloading the
|
||||
new file:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose-standalone.yaml pull
|
||||
docker compose -f docker-compose-standalone.yaml up -d --remove-orphans
|
||||
```
|
||||
|
||||
`--remove-orphans` removes the old frontend container. Open port 7091 instead
|
||||
of 5173. Your data volumes are unchanged. If you opened DocsGPT from other
|
||||
machines, follow [Opening it from other machines](#opening-it-from-other-machines),
|
||||
and remove `VITE_API_HOST` from `.env` if it points at `localhost`: the UI
|
||||
would otherwise keep calling the visitor's own machine.
|
||||
|
||||
## Using the Source Checkout
|
||||
|
||||
With a clone of the repository, `deployment/docker-compose-hub.yaml` runs the
|
||||
|
||||
@@ -27,13 +27,13 @@ API_KEY=YOUR_OPENAI_API_KEY
|
||||
LLM_NAME=gpt-4o
|
||||
```
|
||||
|
||||
### 2. Configuration via `settings.py` file (Advanced)
|
||||
### 2. Configuration in code (Advanced)
|
||||
|
||||
For more advanced configurations or if you prefer to manage settings directly in code, you can modify the `settings.py` file. This file is located in the `docsgpt/core` directory of your DocsGPT project.
|
||||
Every setting is defined in the `docsgpt/core/settings/` package, one module per domain (`auth.py`, `llm.py`, `embeddings.py`, ...). If you prefer to manage defaults directly in code, change them there; the `.env` file and the process environment still override whatever the code says.
|
||||
|
||||
While modifying `settings.py` offers more flexibility, it's generally recommended to use the `.env` file for basic settings and reserve `settings.py` for more complex adjustments or when you need to configure settings programmatically.
|
||||
Using the `.env` file is recommended for day-to-day configuration. Reserve code changes for new settings or for defaults you want every deployment of your fork to share.
|
||||
|
||||
**Location of `settings.py`:** `docsgpt/core/settings.py`
|
||||
The [Settings Reference](/Deploying/Settings-Reference) lists every setting with its type, default and description, generated from those definitions.
|
||||
|
||||
## Basic Settings Explained
|
||||
|
||||
@@ -289,7 +289,7 @@ DocsGPT includes a JWT (JSON Web Token) based authentication feature for managin
|
||||
|
||||
### `AUTH_TYPE` Overview
|
||||
|
||||
The `AUTH_TYPE` setting in your `.env` file or `settings.py` determines the authentication method used by DocsGPT. This allows you to control how users authenticate with your DocsGPT instance.
|
||||
The `AUTH_TYPE` setting in your `.env` file determines the authentication method used by DocsGPT. This allows you to control how users authenticate with your DocsGPT instance.
|
||||
|
||||
| Value | Description |
|
||||
| ------------- | ------------------------------------------------------------------------------------------- |
|
||||
@@ -300,7 +300,7 @@ The `AUTH_TYPE` setting in your `.env` file or `settings.py` determines the auth
|
||||
|
||||
#### How to Configure
|
||||
|
||||
Add the following to your `.env` file (or set in `settings.py`):
|
||||
Add the following to your `.env` file:
|
||||
|
||||
```env
|
||||
# Shared signing key (required in production for every authentication mode)
|
||||
@@ -461,7 +461,6 @@ These control how sources are retrieved and whether the advanced RAG features ar
|
||||
|
||||
| Setting | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `RETRIEVERS_ENABLED` | `["classic", "default"]` | Allow-list of retrievers usable instance-wide. Valid keys: `classic`, `default`, `hybrid`, `graphrag`. A per-source `retriever` must be within this list. |
|
||||
| `PER_SOURCE_RETRIEVAL_ENABLED` | `true` | Master switch for per-source retrieval config. When `false`, all sources fall back to the classic retriever regardless of their stored config. |
|
||||
| `GRAPHRAG_ENABLED` | `false` | Enable [GraphRAG](/Sources/GraphRAG). Requires `VECTOR_STORE=pgvector`. |
|
||||
| `GRAPHRAG_EXTRACTION_MODEL` | unset | Model used for ingest-time graph extraction. Unset reuses the instance default model. |
|
||||
@@ -547,11 +546,10 @@ recovers.
|
||||
|
||||
## Exploring More Settings
|
||||
|
||||
These are just the basic settings to get you started. The `settings.py` file contains many more advanced options that you can explore to further customize DocsGPT, such as:
|
||||
These are just the basic settings to get you started. DocsGPT has many more advanced options, such as:
|
||||
|
||||
- Vector store configuration (`VECTOR_STORE`, Qdrant, Milvus, LanceDB settings) If you're looking for an easy way to set up a vector store with pgvector, try [Neon](https://get.neon.com/docsgpt).
|
||||
- Retriever settings (`RETRIEVERS_ENABLED`)
|
||||
- Cache settings (`CACHE_REDIS_URL`)
|
||||
- And many more!
|
||||
- Sandbox, scheduler, guardrails and event-stream tuning
|
||||
|
||||
For a complete list of available settings and their descriptions, refer to the `settings.py` file in `docsgpt/core`. Remember to restart your Docker containers after making changes to your `.env` file or `settings.py` for the changes to take effect.
|
||||
The [Settings Reference](/Deploying/Settings-Reference) lists every setting with its type, default and description. Remember to restart your Docker containers after making changes to your `.env` file for the changes to take effect.
|
||||
@@ -13,6 +13,10 @@ DocsGPT is on PyPI as [`docsgpt`](https://pypi.org/project/docsgpt/): the API se
|
||||
`docsgpt api` serves the web UI on the same port as the API. Set `SERVE_UI=false` to run the API alone, for example behind the frontend Docker image or a UI you host yourself.
|
||||
</Callout>
|
||||
|
||||
<Callout type="info">
|
||||
With Docker available, the same package can run the whole stack for you, including Postgres and Redis: `docsgpt up`. See [Run it with `docsgpt up`](/Deploying/Docker-Deploying#run-it-with-docsgpt-up).
|
||||
</Callout>
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.12 or newer
|
||||
@@ -49,7 +53,11 @@ pipx runpip docsgpt install --force-reinstall --no-deps --index-url https://down
|
||||
|
||||
## Configure
|
||||
|
||||
DocsGPT keeps its runtime files in a **data home**: the `.env` file it reads settings from, uploaded files under `inputs/`, vector indexes under `indexes/` and downloaded embedding models under `models/`. The data home is the directory you run the commands from, or the directory `DOCSGPT_HOME` points to. `DOCSGPT_ENV_FILE` points at a `.env` kept somewhere else. Both variables must be set in the process environment, not in `.env`: they decide where `.env` is read from.
|
||||
DocsGPT keeps its runtime files in a **data home**: the `.env` file it reads settings from, uploaded files under `inputs/`, vector indexes under `indexes/` and downloaded embedding models under `models/`. The data home is `~/.docsgpt/server` (`/opt/docsgpt` when you run as root on Linux), whatever directory you run the commands from. `DOCSGPT_HOME` moves it, and `DOCSGPT_ENV_FILE` points at a `.env` kept somewhere else. Both variables must be set in the process environment, not in `.env`: they decide where `.env` is read from. In a source checkout the data home is the checkout.
|
||||
|
||||
<Callout type="warning">
|
||||
Up to 0.20 the data home of an installed package was the directory you ran the command from. If you kept `.env` and your data there, move them to `~/.docsgpt/server` or set `DOCSGPT_HOME` to that directory. `docsgpt api` and `docsgpt worker` point out a `.env` in the working directory that they no longer read.
|
||||
</Callout>
|
||||
|
||||
Create a `.env` in the data home. The minimum for a hosted LLM:
|
||||
|
||||
@@ -80,7 +88,7 @@ docsgpt worker # in a second terminal: the Celery worker, with the scheduler
|
||||
|
||||
The API applies pending migrations when it starts (`AUTO_MIGRATE`), so `docsgpt migrate` is the explicit step for deployments that want the schema in place before the first request or that run the API with a restricted database role.
|
||||
|
||||
Both commands print the data home they resolved on start-up. Run them from the same directory, or set `DOCSGPT_HOME` for both, so the worker finds the files the API stores and the API finds the indexes the worker builds.
|
||||
Both commands print the data home they resolved on start-up. They share it as long as `DOCSGPT_HOME` is the same for both (or unset), so the worker finds the files the API stores and the API finds the indexes the worker builds.
|
||||
|
||||
The worker is not optional: query embedding runs on it, so search fails without one. `docsgpt worker --help` lists the queue, concurrency and pool options; `--no-beat` starts a worker without the scheduler when another worker already runs it. On Windows the scheduler cannot be embedded, so run `docsgpt beat` in a third terminal.
|
||||
|
||||
@@ -91,6 +99,35 @@ Other commands:
|
||||
- `docsgpt verify-offline`: check that a prepared install starts with networking off.
|
||||
- `docsgpt reembed`: re-embed every index after changing `EMBEDDINGS_NAME` (see [Upgrading](/upgrading)).
|
||||
|
||||
## Run it as services, without Docker
|
||||
|
||||
`docsgpt up --native` runs the API and the worker as services on the machine itself: launchd agents on macOS, systemd user units on Linux. It does not start PostgreSQL or Redis; point it at ones you already run.
|
||||
|
||||
```bash
|
||||
docsgpt up --native \
|
||||
--postgres-uri postgresql://docsgpt:<password>@localhost:5432/docsgpt \
|
||||
--redis-url redis://localhost:6379
|
||||
```
|
||||
|
||||
Without a terminal only `--postgres-uri` is required, since Redis defaults to `redis://localhost:6379`; with one, it asks for both and for the model provider. It writes the same `.env` a Docker install uses (minus the image settings), generates `INTERNAL_KEY` and `JWT_SECRET_KEY` on the first run, applies the migrations, then starts `docsgpt-api` and `docsgpt-worker` and waits for the API to answer.
|
||||
|
||||
One Redis URL covers all three uses: the Celery broker, its result backend and the cache go on databases 0, 1 and 2 of it. Name a database in the URL and the three start there instead, so `redis://localhost:6379/5` puts them on 5, 6 and 7 — that is how you share a Redis that already holds something else.
|
||||
|
||||
The same commands manage it:
|
||||
|
||||
| Command | In native mode |
|
||||
| --- | --- |
|
||||
| `docsgpt status` | Which services run, the address, and whether the API answers |
|
||||
| `docsgpt logs [api\|worker]` | The service log files under `<stack>/logs` |
|
||||
| `docsgpt down` | Stops both services; settings stay |
|
||||
| `docsgpt uninstall [--purge]` | Removes the services; `--purge` also deletes the stack directory |
|
||||
|
||||
`uninstall` never touches the database or Redis: they were yours to begin with.
|
||||
|
||||
<Callout type="info">
|
||||
Windows has neither launchd nor systemd, so native mode is macOS and Linux only. On Windows, run DocsGPT on Docker with `docsgpt up`, or start `docsgpt api`, `docsgpt worker` and `docsgpt beat` yourself — the worker cannot run the scheduler in-process there, so `docsgpt beat` has to run alongside it for scheduled tasks to fire.
|
||||
</Callout>
|
||||
|
||||
## Upgrade
|
||||
|
||||
```bash
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: Usage Quotas
|
||||
description: Cap how many tokens or dollars each user may spend per day, week or month, with an instance default, per-team allowances and per-user overrides.
|
||||
---
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
# Usage Quotas
|
||||
|
||||
An instance admin can limit how much each user spends on language models. A quota has two independent budgets:
|
||||
|
||||
- **Tokens** — prompt plus generated tokens. Works for every model, including local ones.
|
||||
- **Cost (USD)** — tokens priced at the model's catalog rate. Only sees models that declare a price.
|
||||
|
||||
Set either, both or neither. Quotas are managed from **Admin → Quotas**, or through the [API](#api). With no quota set, nothing is limited.
|
||||
|
||||
## Layers
|
||||
|
||||
Limits are set at three layers. For each budget, the first layer that says something wins:
|
||||
|
||||
1. **User override** — one user's own limit.
|
||||
2. **Team allowance** — what each member of a team gets.
|
||||
3. **Instance default** — everyone else.
|
||||
|
||||
At each layer a budget is either *not set* (defer to the next layer), a *limit*, or *unlimited*. A limit of `0` blocks the user. The two budgets resolve separately, so a user's token limit can come from their team while their cost limit comes from the instance default.
|
||||
|
||||
### Teams
|
||||
|
||||
A team allowance is **per member**, not a pool the team shares: if the allowance is 2M tokens, each member may use 2M.
|
||||
|
||||
A user in several teams gets the **most generous** allowance among them, and allowances are never added together. Usage is always counted per user, whichever teams they belong to. To hold one person below their team's allowance, give them a user override.
|
||||
|
||||
<Callout type="info" emoji="ℹ️">
|
||||
Team membership can change without an instance admin — team admins, OIDC group sync and SCIM all add members — so joining a team can only raise a user's allowance to what you granted that team, never lower it. Only instance admins set allowances; team admins cannot.
|
||||
</Callout>
|
||||
|
||||
## Windows and enforcement
|
||||
|
||||
Usage is counted over a calendar window in UTC, chosen for the whole instance with [`QUOTA_PERIOD`](/Deploying/Settings-Reference#quotas): `day` (from 00:00), `week` (from Monday) or `month` (from the 1st, the default). Windows are worked out when a request arrives, so there is no reset job to run.
|
||||
|
||||
The quota is checked **before** a request starts. The request that crosses a limit completes; the next one is refused with HTTP `429`:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"error_code": "quota-exceeded",
|
||||
"message": "Usage quota reached (1,000,000 of 1,000,000 tokens). It resets at 2026-10-01T00:00:00+00:00.",
|
||||
"dimension": "tokens",
|
||||
"unit": "tokens",
|
||||
"usage": 1000000,
|
||||
"limit": 1000000,
|
||||
"bucket": "all",
|
||||
"source": "instance",
|
||||
"resets_at": "2026-10-01T00:00:00+00:00"
|
||||
}
|
||||
```
|
||||
|
||||
The response carries a `Retry-After` header. The check covers chat, the agent and OpenAI-compatible APIs, scheduled runs (recorded as `budget_exceeded`) and webhook runs. If the quota check itself fails, the request is allowed.
|
||||
|
||||
Who is charged:
|
||||
|
||||
| Traffic | Charged to |
|
||||
| --- | --- |
|
||||
| Chat without an agent | The user |
|
||||
| A user's own agent, its API key, webhooks and schedules | The agent's owner |
|
||||
| An agent shared with the user | The user |
|
||||
|
||||
Per-agent token and request limits still apply on top of the owner's quota.
|
||||
|
||||
Users with a quota see their usage and the reset time under **Settings → Analytics**.
|
||||
|
||||
## Pricing
|
||||
|
||||
Cost budgets use the rates in the [model catalog](/Models/cloud-providers), in USD per million tokens:
|
||||
|
||||
```yaml
|
||||
models:
|
||||
- id: my-model
|
||||
input_cost_per_million: 3.0
|
||||
output_cost_per_million: 15.0
|
||||
cached_input_cost_per_million: 0.3 # optional, prompt-cache reads
|
||||
cache_write_cost_per_million: 3.75 # optional, prompt-cache writes
|
||||
```
|
||||
|
||||
The built-in catalogs ship list prices for hosted models. Override or add rates by dropping a YAML with the same model `id` into `MODELS_CONFIG_DIR`. The cost of each call is stored with its usage row when the call is made, so later price changes do not rewrite history.
|
||||
|
||||
<Callout type="warning" emoji="⚠️">
|
||||
A model with no declared price is recorded at $0, so a cost budget cannot see it. The Quotas tab lists such models once they have been used. Either limit them with a token budget, declare their rates, or set [`QUOTA_UNPRICED_RATE_PER_MILLION`](/Deploying/Settings-Reference#quotas) to charge a fallback rate. Models a user adds with their own API key are always $0, but their tokens still count.
|
||||
</Callout>
|
||||
|
||||
## API
|
||||
|
||||
Every admin endpoint requires the admin role, and every change is written to the [audit log](/Deploying/Access-Control#audit-log) as `quota_policy_set` or `quota_policy_deleted`.
|
||||
|
||||
| Method | Path | Description |
|
||||
| --- | --- | --- |
|
||||
| `GET` | `/api/admin/quotas` | All policies by layer, the current window, and used models without a price. |
|
||||
| `PUT` `DELETE` | `/api/admin/quotas/instance` | The instance default. |
|
||||
| `GET` `PUT` `DELETE` | `/api/admin/quotas/teams/<team_id>` | A team's per-member allowance. |
|
||||
| `GET` `PUT` `DELETE` | `/api/admin/quotas/users/<user_id>` | A user's override; the user must already exist (SCIM-provisioned, or signed in once), otherwise `404`. `GET` also returns the limits the user ends up with, the layer each came from, and their usage. |
|
||||
| `GET` | `/api/user/quota` | The caller's own limits, usage and reset time. |
|
||||
|
||||
A `PUT` body sets, per budget, a limit or the unlimited flag; leave both out to defer to the next layer:
|
||||
|
||||
```json
|
||||
{ "token_limit": 2000000, "cost_unlimited": true, "note": "Research team" }
|
||||
```
|
||||
|
||||
`bucket` (default `all`) narrows a policy to `direct` traffic (chat without an agent) or `agent` traffic (anything that runs through an agent, whether or not the agent has an API key). A request must fit both its own bucket and `all`. The dashboard edits `all`.
|
||||
@@ -3,6 +3,10 @@ export default {
|
||||
"title": "⚙️ App Configuration",
|
||||
"href": "/Deploying/DocsGPT-Settings"
|
||||
},
|
||||
"Settings-Reference": {
|
||||
"title": "📖 Settings Reference",
|
||||
"href": "/Deploying/Settings-Reference"
|
||||
},
|
||||
"OIDC-SSO": {
|
||||
"title": "🔐 SSO with OIDC",
|
||||
"href": "/Deploying/OIDC-SSO"
|
||||
@@ -11,6 +15,10 @@ export default {
|
||||
"title": "👥 Access Control & Teams",
|
||||
"href": "/Deploying/Access-Control"
|
||||
},
|
||||
"Usage-Quotas": {
|
||||
"title": "📊 Usage Quotas",
|
||||
"href": "/Deploying/Usage-Quotas"
|
||||
},
|
||||
"Docker-Deploying": {
|
||||
"title": "🛳️ Docker Setup",
|
||||
"href": "/Deploying/Docker-Deploying"
|
||||
|
||||
@@ -3,6 +3,10 @@ export default {
|
||||
"title": "🔑 Getting API key",
|
||||
"href": "/Extensions/api-key-guide"
|
||||
},
|
||||
"personal-access-tokens": {
|
||||
"title": "🎟️ Personal Access Tokens",
|
||||
"href": "/Extensions/personal-access-tokens"
|
||||
},
|
||||
"chat-widget": {
|
||||
"title": "💬️ Chat Widget",
|
||||
"href": "/Extensions/chat-widget"
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
---
|
||||
title: Personal Access Tokens
|
||||
description: Scoped, revocable API tokens for managing agents, sources and other DocsGPT resources from the CLI, scripts and CI/CD pipelines.
|
||||
---
|
||||
|
||||
# Personal Access Tokens
|
||||
|
||||
A personal access token (PAT) lets a script, the [DocsGPT CLI](https://github.com/arc53/DocsGPT-cli) or a CI/CD pipeline act on your account without a browser session. Unlike an [agent API key](/Extensions/api-key-guide), which can only talk to one agent, a PAT manages resources: it can create and update agents, upload sources, edit prompts and tools, and run agents for benchmarking.
|
||||
|
||||
Every token is limited in three ways:
|
||||
|
||||
- **Scopes** decide which parts of the API the token may call.
|
||||
- **Resource restrictions** (optional) narrow a token to specific agents, sources, prompts, tools or workflows.
|
||||
- **Expiry** ends the token's life automatically.
|
||||
|
||||
## Creating a token
|
||||
|
||||
1. Open **Settings → Access Tokens** in the DocsGPT web app.
|
||||
2. Choose **Create token**, give it a name, and select the scopes it needs.
|
||||
3. Optionally restrict it to specific resources and pick an expiry.
|
||||
4. Copy the token. It starts with `dgpt_pat_` and is shown **once**. DocsGPT stores only a hash of it, so a lost token cannot be recovered. Revoke it and create a new one.
|
||||
|
||||
Tokens can only be created, regenerated and revoked from a signed-in session. A token cannot create, list, regenerate or revoke tokens, so a leaked token cannot mint a replacement for itself.
|
||||
|
||||
## Using a token
|
||||
|
||||
Send the token as a bearer credential:
|
||||
|
||||
```bash
|
||||
export DOCSGPT_URL=https://docsgpt.example.com
|
||||
export DOCSGPT_TOKEN=dgpt_pat_...
|
||||
|
||||
curl -H "Authorization: Bearer $DOCSGPT_TOKEN" "$DOCSGPT_URL/api/user/me"
|
||||
```
|
||||
|
||||
`GET /api/user/me` works with any valid token and reports what the token may do, which makes it a convenient first step in a pipeline:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"user_id": "alice@example.com",
|
||||
"roles": ["user"],
|
||||
"auth_method": "pat",
|
||||
"token": {
|
||||
"id": "0b6c...",
|
||||
"name": "ci-deploy",
|
||||
"scopes": ["agents:read", "agents:write"],
|
||||
"resource_filter": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Applying agent definitions
|
||||
|
||||
Agents can be exported to YAML and applied back, which makes them reviewable and deployable like any other configuration. With the CLI:
|
||||
|
||||
```bash
|
||||
docsgpt-cli agents export <agent-id> -o support-bot.agent.yaml
|
||||
docsgpt-cli agents apply -f support-bot.agent.yaml --dry-run
|
||||
docsgpt-cli agents apply -f support-bot.agent.yaml
|
||||
```
|
||||
|
||||
Or with the API directly (`agents:write`):
|
||||
|
||||
```bash
|
||||
curl -X POST "$DOCSGPT_URL/api/import_agent/plan" \
|
||||
-H "Authorization: Bearer $DOCSGPT_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "$(jq -Rs '{yaml: .}' support-bot.agent.yaml)"
|
||||
```
|
||||
|
||||
Sources are matched by **name**, and when several of your sources share a name the oldest one wins. A pipeline that re-uploads documentation on every push should therefore upload with `docsgpt-cli sources upload ... --wait --replace` (which removes the older same-named sources) and run `agents apply` afterwards, or the agent stays bound to the first upload.
|
||||
|
||||
`/api/import_agent/plan` is a dry run that reports whether the agent would be created or updated and how each referenced source, tool and prompt resolves. `/api/import_agent` applies it. An agent is matched by `metadata.id`, then `metadata.slug`; when nothing matches, a new draft agent is created.
|
||||
|
||||
### GitHub Actions example
|
||||
|
||||
```yaml
|
||||
jobs:
|
||||
deploy-agents:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Apply agent definitions
|
||||
env:
|
||||
DOCSGPT_URL: ${{ vars.DOCSGPT_URL }}
|
||||
DOCSGPT_TOKEN: ${{ secrets.DOCSGPT_TOKEN }}
|
||||
run: |
|
||||
docsgpt-cli sources upload docs/*.md --name "Product docs" --wait --replace --idempotency-key "docs-${{ github.sha }}"
|
||||
docsgpt-cli agents apply -f agents/
|
||||
```
|
||||
|
||||
## Scopes
|
||||
|
||||
A `write` scope includes the matching `read` scope.
|
||||
|
||||
| Scope | Allows |
|
||||
| --- | --- |
|
||||
| `agents:read` | View agents, folders, guardrail events and export agent definitions |
|
||||
| `agents:write` | Create, update, delete, share and import (apply) agents and folders |
|
||||
| `agents:keys` | Regenerate agent API keys and read incoming webhook URLs |
|
||||
| `sources:read` | View sources, their files, chunks and ingestion task status |
|
||||
| `sources:write` | Upload, ingest, sync, edit and delete sources and chunks |
|
||||
| `prompts:read` / `prompts:write` | View / create, update and delete prompts |
|
||||
| `tools:read` / `tools:write` | View / create, update and delete tools and MCP servers |
|
||||
| `models:read` / `models:write` | View models / manage custom models |
|
||||
| `workflows:read` / `workflows:write` | View / create, update and delete workflows |
|
||||
| `schedules:read` / `schedules:write` | View / create, update, run and delete agent schedules |
|
||||
| `conversations:read` / `conversations:write` | View / rename, delete and rate conversations |
|
||||
| `analytics:read` | View usage analytics and logs |
|
||||
| `teams:read` | View teams, members and resource shares |
|
||||
| `chat:run` | Ask agents and search sources (`/api/answer`, `/stream`, `/api/search`); used for benchmarking |
|
||||
|
||||
`agents:keys` is separate from `agents:write` on purpose. Creating, publishing or adopting an agent mints its API key; a token without `agents:keys` gets the key back masked (`1234...90ab`), because an agent key keeps working after the token that saw it is revoked. Put differently: a deployment token that updates agents does not need to be able to read or rotate the secrets other systems use to call them.
|
||||
|
||||
Some parts of the API are never available to a token, whatever its scopes: token management, the admin API, team management, sign-in flows, device pairing, and the interactive OAuth handshakes used by connectors and MCP servers. A token also never carries the `admin` role, even when its owner is an admin.
|
||||
|
||||
Authorization is deny by default. An endpoint that is not explicitly mapped to a scope cannot be called with a token, and answers `403` with `"error": "not_available_to_tokens"`. A mapped endpoint called without the scope answers `403` with `"error": "insufficient_scope"` and names the `required_scope`.
|
||||
|
||||
## Resource restrictions
|
||||
|
||||
A token can be narrowed to specific resources in any of these families: `agents`, `sources`, `prompts`, `tools`, `workflows`. A family that is not listed stays unrestricted within the token's scopes.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "support-bot-deploy",
|
||||
"scopes": ["agents:write", "chat:run"],
|
||||
"resource_filter": { "agents": ["3f0e8f0c-5a53-4f0e-9a39-0e5f4f8d2c11"] },
|
||||
"expires_in_days": 30
|
||||
}
|
||||
```
|
||||
|
||||
For a restricted family the token:
|
||||
|
||||
- can read, update and delete only the listed resources, and listings show only those;
|
||||
- **cannot create** new resources of that family, since a new resource would be outside the list;
|
||||
- cannot attach a resource outside the list to something else, for example set an agent's source to a source the token may not use;
|
||||
- is refused (`403`, `"error": "resource_not_allowed"`) wherever DocsGPT cannot prove the request stays inside the list:
|
||||
- **Conversations, analytics and message replay** (`/api/messages/<id>/tail`, `/api/messages/<id>/events`) are closed to every restricted token. They span all agents and contain cited source text and tool output.
|
||||
- **Schedules** run an agent with a free-form instruction and store the output. A token restricted to agents can list and create schedules for its agents; every other schedule route, and schedules altogether for tokens restricted on another family, are closed.
|
||||
- **Workflow writes** are closed to tokens restricted on sources, tools or prompts, because a workflow graph names those inside its nodes. Such a token also cannot attach a workflow to an agent unless it is restricted on workflows too, in which case only the listed workflows can be attached.
|
||||
- `/api/sources/paginated` is closed to source-restricted tokens (use `/api/sources`).
|
||||
|
||||
A restriction covers what the token *asks for*, not what an allowed resource already contains: an agent on the list runs with its own sources, prompt and tools even when the token is also restricted on those families. List an agent only if you are happy for the token to use everything that agent uses.
|
||||
|
||||
Restrictions and chat (`chat:run`):
|
||||
|
||||
- A token restricted to specific **agents** must pass exactly one `agent_id` in the request body, and it must be one of the listed agents. An agent `api_key` or an inline workflow in the body is refused.
|
||||
- A token restricted to specific **sources** only may chat against those sources with `active_docs`. It cannot run agents, because an agent brings its own sources. Restrict the token to agents instead to allow that.
|
||||
- A token restricted on **prompts** or **workflows** must also be restricted to agents to chat.
|
||||
- A token restricted on **tools** cannot use chat at all, and a tools restriction cannot be combined with `chat:run` when the token is created. Chat executes tools (an agent's own, or your default tools when there is no agent) and those cannot be held to a list.
|
||||
- A `conversation_id` must belong to the agent being run (or to no agent, for agent-less chat). Otherwise the server would continue, append to, or resume pending tool calls of another agent's conversation.
|
||||
|
||||
`agents:write` and import: applying an agent definition can create the prompt and tools it references and rewrite the agent's workflow, all under `agents:write` alone. It does not need `prompts:write`, `tools:write` or `workflows:write`, so treat `agents:write` as able to create those through an import.
|
||||
|
||||
Restrictions and `agents apply`: a token restricted to specific agents can apply a definition only when it updates one of those agents. A token restricted on sources, prompts, tools or workflows cannot import agents at all, because an import resolves those references by name and may create them.
|
||||
|
||||
## Expiry and revocation
|
||||
|
||||
- A token created without an explicit lifetime expires after `PAT_DEFAULT_LIFETIME_DAYS` (90 by default). Users can choose any lifetime up to `PAT_MAX_LIFETIME_DAYS` (365 by default).
|
||||
- Non-expiring tokens are available only when the operator sets `PAT_ALLOW_NON_EXPIRING=true`.
|
||||
- **Regenerate** in **Settings → Access Tokens** issues a new secret for the same token and resets its expiry. The name, scopes and restrictions stay; the old secret stops working immediately, so update whatever uses it. The new lifetime defaults to the one the token was last issued with, and an expired token can be renewed this way (a revoked one cannot). This is the way to rotate a secret or extend a token without rebuilding its scopes.
|
||||
- Revoking a token in **Settings → Access Tokens** takes effect on the next request.
|
||||
- Admins can list a user's tokens with `GET /api/admin/users/<user_id>/tokens` and revoke any token with `DELETE /api/admin/tokens/<token_id>`. The admin **revoke sessions** action also revokes all of that user's tokens.
|
||||
- Tokens of a deactivated user (through the admin API or SCIM) stop working immediately and work again if the user is reactivated.
|
||||
- `GET /api/user/tokens` reports a token past its expiry as `"status": "expired"`.
|
||||
- Token creation and revocation are recorded in the authentication audit log (`pat_created`, `pat_regenerated`, `pat_revoked`), visible to admins.
|
||||
|
||||
An expired token's name can be reused: creating a token with that name retires the expired one.
|
||||
|
||||
Each user may hold up to `PAT_MAX_PER_USER` live tokens (25 by default). The token list shows when and from which IP address each token was last used.
|
||||
|
||||
## Operator settings
|
||||
|
||||
| Setting | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `PAT_ENABLED` | `true` | Master switch. When `false`, tokens cannot be created **and every existing token stops authenticating immediately** |
|
||||
| `PAT_DEFAULT_LIFETIME_DAYS` | `90` | Lifetime of a token created without an explicit expiry |
|
||||
| `PAT_MAX_LIFETIME_DAYS` | `365` | Longest lifetime a user may request |
|
||||
| `PAT_ALLOW_NON_EXPIRING` | `false` | Let users create tokens that never expire |
|
||||
| `PAT_MAX_PER_USER` | `25` | Maximum number of live tokens per user |
|
||||
|
||||
Personal access tokens need a stable user identity, so they are available with `AUTH_TYPE=oidc` and with authentication disabled (single-user self-hosting). They are not available with `simple_jwt` or `session_jwt`.
|
||||
|
||||
Turning `PAT_ENABLED` off, or switching `AUTH_TYPE` to `simple_jwt` or `session_jwt`, is not limited to the settings page: every pipeline that uses a token starts getting `401` right away. Tokens are not deleted and work again once the setting is restored. See the [Settings Reference](/Deploying/Settings-Reference) for details.
|
||||
|
||||
## Management API
|
||||
|
||||
These endpoints need a signed-in session and cannot be called with a token.
|
||||
|
||||
| Endpoint | Purpose |
|
||||
| --- | --- |
|
||||
| `GET /api/user/tokens` | List your tokens, the scope catalog and the server's token policy |
|
||||
| `POST /api/user/tokens` | Create a token. Body: `name`, `scopes`, optional `resource_filter`, optional `expires_in_days` (`0` = never, when allowed). The response carries the plaintext `token` once |
|
||||
| `POST /api/user/tokens/<id>/regenerate` | New secret and new expiry for the same token. Optional body `expires_in_days`; omitted = the lifetime it was last issued with. The response carries the plaintext `token` once |
|
||||
| `DELETE /api/user/tokens/<id>` | Revoke a token |
|
||||
|
||||
## Good practice
|
||||
|
||||
- Give each pipeline its own token with the narrowest scopes that work, and name it after where it is used.
|
||||
- Store tokens in your CI system's secret store. Never commit them. The `dgpt_pat_` prefix lets secret scanners recognise them.
|
||||
- Prefer short lifetimes for tokens used by automation you can easily re-provision.
|
||||
- Revoke a token as soon as it is no longer needed or may have been exposed.
|
||||
@@ -98,9 +98,11 @@ The DocsGPT Search Bar Widget offers a range of customizable properties that all
|
||||
|-----------------|-----------|-------------------------------------|--------------------------------------------------------------------------------------------------|
|
||||
| **`apiKey`** | `string` | `"your-api-key"` | API key for authentication with your DocsGPT API. Leave empty if no authentication is required. |
|
||||
| **`apiHost`** | `string` | `"https://gptcloud.arc53.com"` | **Required.** The URL of your DocsGPT API backend. This endpoint handles vector similarity search queries. |
|
||||
| **`theme`** | `"dark" \| "light"` | `"dark"` | Color theme of the search bar. Options: `"dark"` or `"light"`. Defaults to `"dark"`. |
|
||||
| **`theme`** | `"dark" \| "light"` | `"dark"` | Color theme of the search bar and of the chat it opens. Options: `"dark"` or `"light"`. Defaults to `"dark"`. |
|
||||
| **`placeholder`** | `string` | `"Search or Ask AI..."` | Placeholder text displayed in the search input field. |
|
||||
| **`width`** | `string` | `"256px"` | Width of the search bar. Accepts any valid CSS width value (e.g., `"300px"`, `"100%"`, `"20rem"`). |
|
||||
| **`allowedFileExtensions`** | `string[]` | _unset_ | Passed to the chat opened from "Ask the AI". File extensions its composer accepts, e.g. `['.pdf', '.md']`; attachments stay off while unset. See the [chat widget page](/Extensions/chat-widget). |
|
||||
| **`showMicButton`** | `boolean` | `false` | Adds a microphone to the search field for dictating a query, and passes the same option to the chat opened from "Ask the AI". Uses the browser's Web Speech API. See the [chat widget page](/Extensions/chat-widget). |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -251,4 +251,4 @@ The main extension points in [arc53/DocsGPT](https://github.com/arc53/DocsGPT) a
|
||||
| Parsing and workers | [`docsgpt/parser/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/parser), [`docsgpt/worker.py`](https://github.com/arc53/DocsGPT/blob/main/docsgpt/worker.py), [`docsgpt/api/user/tasks.py`](https://github.com/arc53/DocsGPT/blob/main/docsgpt/api/user/tasks.py) |
|
||||
| Models and vector stores | [`docsgpt/llm/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/llm), [`docsgpt/vectorstore/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/vectorstore) |
|
||||
| Storage and events | [`docsgpt/storage/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/storage), [`docsgpt/streaming/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/streaming), [`docsgpt/events/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/events) |
|
||||
| Configuration, UI, and deployment | [`docsgpt/core/settings.py`](https://github.com/arc53/DocsGPT/blob/main/docsgpt/core/settings.py), [`frontend/`](https://github.com/arc53/DocsGPT/tree/main/frontend), [`deployment/`](https://github.com/arc53/DocsGPT/tree/main/deployment) |
|
||||
| Configuration, UI, and deployment | [`docsgpt/core/settings/`](https://github.com/arc53/DocsGPT/tree/main/docsgpt/core/settings), [`frontend/`](https://github.com/arc53/DocsGPT/tree/main/frontend), [`deployment/`](https://github.com/arc53/DocsGPT/tree/main/deployment) |
|
||||
@@ -19,7 +19,7 @@ The compression system operates on a "summarize and truncate" principle:
|
||||
|
||||
## Configuration
|
||||
|
||||
You can configure the compression behavior in your `.env` file or `docsgpt/core/settings.py`:
|
||||
You can configure the compression behavior in your `.env` file or `docsgpt/core/settings/agents.py`:
|
||||
|
||||
| Setting | Default | Description |
|
||||
| :--- | :--- | :--- |
|
||||
|
||||
@@ -115,8 +115,6 @@ Requests are also bounded: `chunks` is clamped to 0–500, and `0` still means
|
||||
Keyword search for the **hybrid** retriever is currently implemented only for the **pgvector** vector store. On other stores (FAISS, Qdrant, Milvus, etc.) the keyword half returns nothing, so `hybrid` quietly behaves like `classic` (vector-only).
|
||||
</Callout>
|
||||
|
||||
Operators can restrict which retrievers are usable instance-wide with the `RETRIEVERS_ENABLED` setting; a per-source `retriever` value must be within that allow-list.
|
||||
|
||||
### Exposure: prefetch vs. agentic tool
|
||||
|
||||
`exposure` controls *how* a source's content is delivered to the model:
|
||||
|
||||
@@ -11,6 +11,73 @@ The notable changes in each release. Every release on GitHub also carries
|
||||
[auto-generated notes](https://github.com/arc53/DocsGPT/releases) listing every merged pull
|
||||
request, and [Upgrading](/upgrading) covers the steps an existing deployment has to take.
|
||||
|
||||
## Unreleased
|
||||
|
||||
### A development loop in one command
|
||||
|
||||
`docsgpt dev` runs this checkout's API and worker as children of one terminal, both restarting when
|
||||
you save, with their output interleaved and Ctrl-C stopping them together. `--ui` adds the Vite dev
|
||||
server and `--mock-llm` runs the bundled mock model, so a working loop needs no API key.
|
||||
`docsgpt doctor` checks PostgreSQL, its schema version, Redis, the model provider and the port;
|
||||
`docsgpt restart` bounces the services without touching settings; `docsgpt logs -f` now follows a
|
||||
native install; and `docsgpt env set` applies itself to a running native install instead of asking
|
||||
you to run `docsgpt up` again. See
|
||||
[Setting up a development environment](/Deploying/Development-Environment).
|
||||
|
||||
### Run DocsGPT without Docker
|
||||
|
||||
`docsgpt up --native` runs the API and the worker as services on the machine itself, launchd on
|
||||
macOS and systemd user units on Linux, against a PostgreSQL and Redis you already have
|
||||
(`--postgres-uri`, `--redis-url`). `status`, `logs`, `down` and `uninstall` work on such an install
|
||||
the same way they do on a Docker one, and never touch the database or Redis. See
|
||||
[Run it as services, without Docker](/Deploying/Pip-Install#run-it-as-services-without-docker).
|
||||
|
||||
### Back up and restore an install
|
||||
|
||||
`docsgpt backup` writes a dump of the database and a tar of each data volume into one archive, and
|
||||
`docsgpt restore <archive>` puts them back. The settings file is left out unless
|
||||
`--with-settings` asks for it, since it holds the install's secrets, and a backup from a newer
|
||||
DocsGPT is refused unless you pass `--force`. The archive is written readable only by its owner,
|
||||
and the backend and the worker pause while it is made so the dump and the volume tars match. See
|
||||
[Backups](/Deploying/Docker-Deploying#backups).
|
||||
|
||||
## 0.21.0
|
||||
|
||||
### Install with one command
|
||||
|
||||
`curl -fsSL https://docs.ac/install | bash` on macOS and Linux, or `irm https://docs.ac/install.ps1 | iex`
|
||||
in Windows PowerShell, installs uv and the `docsgpt` package and runs `docsgpt up`. Running it again
|
||||
upgrades and keeps your settings. On Linux it offers to install Docker when it is missing. Both
|
||||
scripts are attached to every release. See the [Quickstart](/quickstart).
|
||||
|
||||
### `docsgpt up` runs DocsGPT on Docker
|
||||
|
||||
The Python package now sets up and runs the Docker stack: `uv tool install docsgpt`, then
|
||||
`docsgpt up`. The first run asks who should reach DocsGPT (this computer, the network with an
|
||||
access token, or a domain with HTTPS) and which model provider to use, writes the settings and
|
||||
secrets to `~/.docsgpt/server/.env`, and starts the images of the installed version. `docsgpt status`,
|
||||
`logs`, `token`, `upgrade`, `down` and `uninstall` manage it afterwards. See
|
||||
[Run it with `docsgpt up`](/Deploying/Docker-Deploying#run-it-with-docsgpt-up).
|
||||
|
||||
### An installed package keeps its data in `~/.docsgpt/server`
|
||||
|
||||
Outside a source checkout, the data home (`.env`, uploads, indexes, models) was the directory
|
||||
the command ran from, so starting `docsgpt api` from another folder silently used other
|
||||
settings. It is now `~/.docsgpt/server`, or `/opt/docsgpt` for root on Linux; `DOCSGPT_HOME`
|
||||
still overrides it. See [Upgrading](/upgrading#pip-installs-data-home-moved).
|
||||
|
||||
### The standalone Docker stack runs on one port
|
||||
|
||||
The `arc53/docsgpt` image now serves the web UI next to the API, the way `docsgpt api` does from
|
||||
the Python package. `docker-compose-standalone.yaml` no longer runs a frontend container: the UI
|
||||
and the API share port 7091, published on `127.0.0.1` by default. The UI takes its API address
|
||||
from the page it was loaded from, so opening the stack from another machine works without
|
||||
setting `VITE_API_HOST`. New Compose settings: `DOCSGPT_BIND` and `DOCSGPT_PORT` for where the
|
||||
port is published, `POSTGRES_PASSWORD`, and an `https` profile that puts Caddy with an automatic
|
||||
certificate in front of a public domain. The `arc53/docsgpt-fe` image is still published for the
|
||||
checkout Compose files and Kubernetes. See
|
||||
[Upgrading from an earlier standalone file](/Deploying/Docker-Deploying#upgrading-from-an-earlier-standalone-file).
|
||||
|
||||
## 0.20.0
|
||||
|
||||
### DocsGPT installs from PyPI
|
||||
|
||||
+74
-67
@@ -1,40 +1,91 @@
|
||||
---
|
||||
title: Quickstart - Launching DocsGPT Web App
|
||||
description: Get started with DocsGPT quickly by launching the web application using the setup script.
|
||||
description: Install and start DocsGPT with one command, or from a clone with the setup script.
|
||||
---
|
||||
|
||||
import { Callout } from 'nextra/components'
|
||||
|
||||
# Quickstart
|
||||
|
||||
**Prerequisites:**
|
||||
|
||||
* **Docker:** Ensure you have Docker installed and running on your system.
|
||||
* **Docker:** DocsGPT runs on Docker, with Docker Compose 2.24 or newer. On macOS and Windows install [Docker Desktop](https://docs.docker.com/desktop/) (or [OrbStack](https://orbstack.dev) on macOS); on Linux, [Docker Engine](https://docs.docker.com/engine/install/). On Linux the installer offers to install Docker for you.
|
||||
|
||||
## Launching DocsGPT (macOS and Linux)
|
||||
## Install with one command
|
||||
|
||||
The easiest way to launch DocsGPT is using the provided `setup.sh` script. This script automates the configuration process and offers several setup options.
|
||||
**macOS and Linux:**
|
||||
|
||||
**Steps:**
|
||||
```bash
|
||||
curl -fsSL https://docs.ac/install | bash
|
||||
```
|
||||
|
||||
1. **Download the DocsGPT Repository:**
|
||||
**Windows (PowerShell):**
|
||||
|
||||
First, you need to download the DocsGPT repository to your local machine. You can do this using Git:
|
||||
```powershell
|
||||
irm https://docs.ac/install.ps1 | iex
|
||||
```
|
||||
|
||||
The installer:
|
||||
|
||||
1. Checks for Docker.
|
||||
2. Installs [uv](https://docs.astral.sh/uv/) if it is missing or too old. uv installs Python packages and brings its own Python when the system has none.
|
||||
3. Installs the `docsgpt` Python package with `uv tool install`.
|
||||
4. Runs `docsgpt up`, which asks two questions:
|
||||
* **Who should reach DocsGPT:** only this computer; other machines on your network (plain HTTP, with an access token); or a domain name with HTTPS (a certificate from Let's Encrypt, with an access token).
|
||||
* **Which model provider:** the DocsGPT public API (no key needed), OpenAI, Anthropic, Google Gemini, OpenRouter, Groq, or an OpenAI-compatible server such as Ollama or vLLM.
|
||||
|
||||
It then starts DocsGPT and prints its address, [http://localhost:7091](http://localhost:7091) for a local install. Settings and generated secrets are in `~/.docsgpt/server/.env`, or `/opt/docsgpt/.env` when the installer runs as root on Linux; `docsgpt up --dir` or `DOCSGPT_HOME` choose another folder.
|
||||
|
||||
<Callout type="info">
|
||||
To read the script before running it, download it first: `curl -fsSL https://docs.ac/install -o install.sh`, then `bash install.sh`. On Windows: `irm https://docs.ac/install.ps1 -OutFile install.ps1`, then `.\install.ps1`.
|
||||
</Callout>
|
||||
|
||||
**Options.** Arguments after `bash -s --` go to `docsgpt up`, so a server can be set up without questions:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://docs.ac/install | bash -s -- --yes --domain docs.example.com --provider openai --api-key "$OPENAI_API_KEY"
|
||||
```
|
||||
|
||||
`DOCSGPT_VERSION` installs a specific release, and `DOCSGPT_NO_MODIFY_PATH=1` leaves your shell profile alone. `docsgpt up --help` lists every option.
|
||||
|
||||
**Afterwards:**
|
||||
|
||||
| Command | What it does |
|
||||
| --- | --- |
|
||||
| `docsgpt status` | Version, address, and whether DocsGPT answers |
|
||||
| `docsgpt logs -f` | Follow the logs |
|
||||
| `docsgpt token` | The access token, for installs reachable beyond this computer |
|
||||
| `docsgpt up --reconfigure` | Ask the setup questions again |
|
||||
| `docsgpt upgrade` | Upgrade to the latest release, keeping your settings and data |
|
||||
| `docsgpt down` | Stop DocsGPT |
|
||||
| `docsgpt uninstall` | Remove it; `--purge` also deletes settings and data |
|
||||
|
||||
Running the install command again also upgrades. See [Run it with `docsgpt up`](/Deploying/Docker-Deploying#run-it-with-docsgpt-up) for the details.
|
||||
|
||||
## From a clone, with the setup script
|
||||
|
||||
To work from the source tree, for example to build the images yourself, use `setup.sh` (macOS and Linux) or `setup.ps1` (Windows).
|
||||
|
||||
1. **Clone the repository:**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/arc53/DocsGPT.git
|
||||
cd DocsGPT
|
||||
```
|
||||
|
||||
2. **Run the `setup.sh` script:**
|
||||
|
||||
Navigate to the DocsGPT directory in your terminal and execute the `setup.sh` script:
|
||||
2. **Run the setup script:**
|
||||
|
||||
```bash
|
||||
./setup.sh
|
||||
```
|
||||
|
||||
3. **Follow the interactive setup:**
|
||||
On Windows:
|
||||
|
||||
The `setup.sh` script will guide you through an interactive menu with the following options:
|
||||
```powershell
|
||||
PowerShell -ExecutionPolicy Bypass -File .\setup.ps1
|
||||
```
|
||||
|
||||
3. **Follow the interactive setup:**
|
||||
|
||||
```
|
||||
Welcome to DocsGPT Setup!
|
||||
@@ -47,76 +98,32 @@ The easiest way to launch DocsGPT is using the provided `setup.sh` script. This
|
||||
Choose option (1-5):
|
||||
```
|
||||
|
||||
Let's break down each option:
|
||||
* **1) Use DocsGPT Public API Endpoint (simple and free):** This is the simplest option to get started. It utilizes the DocsGPT public API, requiring no API keys or local model downloads.
|
||||
|
||||
* **1) Use DocsGPT Public API Endpoint (simple and free):** This is the simplest option to get started. It utilizes the DocsGPT public API, requiring no API keys or local model downloads. Choose this for a quick and easy setup.
|
||||
* **2) Serve Local (with Ollama):** Runs a Large Language Model locally using [Ollama](https://ollama.com/). You'll be prompted to choose between CPU or GPU for Ollama and select a model to download.
|
||||
|
||||
* **2) Serve Local (with Ollama):** This option allows you to run a Large Language Model locally using [Ollama](https://ollama.com/). You'll be prompted to choose between CPU or GPU for Ollama and select a model to download. This is a good option for local processing and experimentation.
|
||||
* **3) Connect Local Inference Engine:** If you already run a local inference engine like Llama.cpp, Text Generation Inference (TGI), vLLM, or others, choose this option and provide the connection details.
|
||||
|
||||
* **3) Connect Local Inference Engine:** If you are already running a local inference engine like Llama.cpp, Text Generation Inference (TGI), vLLM, or others, choose this option. You'll be asked to select your engine and provide the necessary connection details. This is for users with existing local LLM infrastructure.
|
||||
* **4) Connect Cloud API Provider:** Connect DocsGPT to a Cloud API provider such as OpenAI, Google (Vertex AI/Gemini), Anthropic (Claude), Groq, HuggingFace Inference API, or Azure OpenAI. You will need an API key from your chosen provider.
|
||||
|
||||
* **4) Connect Cloud API Provider:** This option lets you connect DocsGPT to a commercial Cloud API provider such as OpenAI, Google (Vertex AI/Gemini), Anthropic (Claude), Groq, HuggingFace Inference API, or Azure OpenAI. You will need an API key from your chosen provider. Select this if you prefer to use a powerful cloud-based LLM.
|
||||
* **5) Modify DocsGPT's source code and rebuild the Docker images locally.** Instead of pulling prebuilt images from Docker Hub, you build the backend and frontend from source, to customize how DocsGPT works internally or to run it in an environment without internet access.
|
||||
|
||||
* **5) Modify DocsGPT's source code and rebuild the Docker images locally.** Instead of pulling prebuilt images from Docker Hub or using the hosted/public API, you build the entire backend and frontend from source, customizing how DocsGPT works internally, or run it in an environment without internet access.
|
||||
After selecting an option and providing any required information (like API keys or model names), the script configures your `.env` file and starts DocsGPT using Docker Compose.
|
||||
|
||||
After selecting an option and providing any required information (like API keys or model names), the script will configure your `.env` file and start DocsGPT using Docker Compose.
|
||||
4. **Access DocsGPT in your browser:** open [http://localhost:5173/](http://localhost:5173/).
|
||||
|
||||
4. **Access DocsGPT in your browser:**
|
||||
|
||||
Once the setup is complete and Docker containers are running, navigate to [http://localhost:5173/](http://localhost:5173/) in your web browser to access the DocsGPT web application.
|
||||
|
||||
5. **Stopping DocsGPT:**
|
||||
|
||||
To stop DocsGPT, simply open a new terminal in the `DocsGPT` directory and run:
|
||||
5. **Stopping DocsGPT:** in the `DocsGPT` directory, run the `docker compose down` command the script printed at the end, for example:
|
||||
|
||||
```bash
|
||||
docker compose -f deployment/docker-compose-hub.yaml down
|
||||
```
|
||||
(or the specific `docker compose` command shown at the end of the `setup.sh` execution, which may include optional compose files depending on your choices).
|
||||
|
||||
## Launching DocsGPT (Windows)
|
||||
**Important for Windows:** Ensure Docker Desktop is installed and running before you start. The script tries to start Docker if it is not running, but you may need to start it manually.
|
||||
|
||||
For Windows users, we provide a PowerShell script that offers the same functionality as the macOS/Linux setup script.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Download the DocsGPT Repository:**
|
||||
|
||||
First, you need to download the DocsGPT repository to your local machine. You can do this using Git:
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/arc53/DocsGPT.git
|
||||
cd DocsGPT
|
||||
```
|
||||
|
||||
2. **Run the `setup.ps1` script:**
|
||||
|
||||
Execute the PowerShell setup script:
|
||||
|
||||
```powershell
|
||||
PowerShell -ExecutionPolicy Bypass -File .\setup.ps1
|
||||
```
|
||||
|
||||
3. **Follow the interactive setup:**
|
||||
|
||||
Just like the Linux/macOS script, the PowerShell script will guide you through setting DocsGPT.
|
||||
The script will handle environment configuration and start DocsGPT based on your selections.
|
||||
|
||||
4. **Access DocsGPT in your browser:**
|
||||
|
||||
Once the setup is complete and Docker containers are running, navigate to [http://localhost:5173/](http://localhost:5173/) in your web browser to access the DocsGPT web application.
|
||||
|
||||
5. **Stopping DocsGPT:**
|
||||
|
||||
To stop DocsGPT run the Docker Compose down command displayed at the end of the setup script's execution.
|
||||
|
||||
**Important for Windows:** Ensure Docker Desktop is installed and running correctly on your Windows system before proceeding. The script will attempt to start Docker if it's not running, but you may need to start it manually if there are issues.
|
||||
|
||||
**Alternative Method:**
|
||||
If you prefer a more manual approach, you can follow our [Docker Deployment documentation](/Deploying/Docker-Deploying) for detailed instructions on setting up DocsGPT on Windows using Docker commands directly.
|
||||
**Alternative Method:** To run the pre-built images with Docker Compose yourself, follow the [Docker Deployment documentation](/Deploying/Docker-Deploying).
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
For more advanced customization of DocsGPT settings, such as configuring vector stores, embedding models, and other parameters, please refer to the [DocsGPT Settings documentation](/Deploying/DocsGPT-Settings). This guide explains how to modify the `.env` file or `settings.py` for deeper configuration.
|
||||
For more advanced customization of DocsGPT settings, such as configuring vector stores, embedding models, and other parameters, please refer to the [DocsGPT Settings documentation](/Deploying/DocsGPT-Settings). This guide explains how to configure DocsGPT through the `.env` file, and links to the full settings reference.
|
||||
|
||||
Enjoy using DocsGPT!
|
||||
@@ -11,6 +11,14 @@ import { Callout } from 'nextra/components'
|
||||
**Upgrading from 0.16.x?** User data moved from MongoDB to Postgres in 0.17.0. Follow the [Postgres Migration guide](/Deploying/Postgres-Migration) before running `docker compose pull` or `git pull` — existing deployments will not start cleanly without it.
|
||||
</Callout>
|
||||
|
||||
## pip installs: data home moved
|
||||
|
||||
An installed package (`pip install docsgpt`, pipx, `uv tool`) used to keep its data home, meaning `.env`, `inputs/`, `indexes/` and `models/`, in the directory you ran `docsgpt api` and `docsgpt worker` from. It is now `~/.docsgpt/server` (`/opt/docsgpt` for root on Linux). Either move those files there, or set `DOCSGPT_HOME` to the old directory in the environment of both commands. Both commands print the data home they use, and point out a `.env` in the working directory that they no longer read. Source checkouts and the Docker images are not affected.
|
||||
|
||||
## Standalone Compose file: one port
|
||||
|
||||
The standalone Compose file (`docker-compose-standalone.yaml`) no longer runs a frontend container. The backend image serves the web UI on port 7091, and the port is published on `127.0.0.1` unless you set `DOCSGPT_BIND`. After downloading the new file, start it with `--remove-orphans` to remove the old frontend container, then open port 7091 instead of 5173. If you opened DocsGPT from other machines, see [Upgrading from an earlier standalone file](/Deploying/Docker-Deploying#upgrading-from-an-earlier-standalone-file). The checkout Compose files and the Kubernetes manifests are unchanged.
|
||||
|
||||
## Embedding models
|
||||
|
||||
DocsGPT now runs embeddings through [FastEmbed](https://github.com/qdrant/fastembed) (ONNX Runtime) instead of SentenceTransformer. The models are the same and the vectors are identical, so **your existing index needs no action** — `all-mpnet-base-v2` keeps working exactly as before.
|
||||
@@ -113,8 +121,9 @@ alias, so nothing breaks on upgrade, but update these before the alias goes:
|
||||
and vectors under `application/` in the checkout, where they already are.
|
||||
- The backend is also a package now (`pip install docsgpt`, see
|
||||
[Install with pip](/Deploying/Pip-Install)). Runtime data lives in a data
|
||||
home: `DOCSGPT_HOME`, else the checkout, else the directory the process
|
||||
starts in. One consequence for a source checkout: the embedded Milvus
|
||||
home: `DOCSGPT_HOME`, else the checkout, else `~/.docsgpt/server`
|
||||
(`/opt/docsgpt` for root on Linux; see
|
||||
[pip installs: data home moved](#pip-installs-data-home-moved)). One consequence for a source checkout: the embedded Milvus
|
||||
(`MILVUS_URI`) and LanceDB (`LANCEDB_PATH`) default paths now resolve under
|
||||
the checkout instead of the start directory. If you use either store at its
|
||||
default path and start DocsGPT from another directory, the old data is at
|
||||
|
||||
@@ -320,7 +320,7 @@ redis-cli -n 2 DEL user:<id>:stream
|
||||
|
||||
## Settings reference
|
||||
|
||||
Everything in `docsgpt/core/settings.py`:
|
||||
Everything in `docsgpt/core/settings/events.py`:
|
||||
|
||||
| Setting | Default | Purpose |
|
||||
| --------------------------------------------- | ------- | --------------------------------------------- |
|
||||
|
||||
Reference in new issue
Block a user