快速上手
本章介绍如何安装 Dr Strange(用发行版二进制或从源码构建均可)、如何初始化数据库、 在命令行中发起查询,以及如何运行服务,包括本地运行和以容器镜像方式部署。
环境准备
安装发行版二进制除 curl(Windows 上为 PowerShell)之外别无所需。以下准备仅适用于
其他方式:
- 从源码构建:当前的 Rust 工具链(stable 通道),经 rustup 安装。
- Web 仪表盘:bun 编译单页应用,以及可选的 just 作为任务运行器。
- 容器工作流:Docker(Engine 24+;仅在自行构建镜像时才需要 BuildKit)。
构建通过 rustls/ring 链接 TLS,无需 OpenSSL 工具链。
安装发行版二进制
每个打了标签的发行版都会发布 Linux、macOS 与 Windows 的二进制。安装脚本会选取与宿主
平台匹配的归档包,校验其发布的 SHA-256,并将二进制置入 PATH。可安装的二进制有两个:
命令行工具与服务端 drsg,以及面向 LLM 智能体的 MCP 服务 drsg-mcp(第 8 章)。
Linux
# 命令行与服务端 —— drsg
$ curl -fsSL https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.sh | sh
# MCP 服务 —— drsg-mcp
$ curl -fsSL https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.sh | sh -s -- --bin drsg-mcp
macOS(脚本相同,Apple 芯片与 Intel 版本均有发布)
# 命令行与服务端 —— drsg
$ curl -fsSL https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.sh | sh
# MCP 服务 —— drsg-mcp
$ curl -fsSL https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.sh | sh -s -- --bin drsg-mcp
Windows,在 PowerShell 中执行。第二种写法将脚本作为代码块运行,因为以管道送入
iex 的脚本无法接收参数。
# 命令行与服务端 —— drsg
PS> irm https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.ps1 | iex
# MCP 服务 —— drsg-mcp
PS> & ([scriptblock]::Create((irm https://raw.githubusercontent.com/wangyingsm/dr-strange/master/scripts/install.ps1))) -Bin drsg-mcp
三个选项可调整安装行为,每个都有对应的环境变量,便于在非交互场景中使用:
| 选项(Windows) | 环境变量 | 作用 |
|---|---|---|
--bin drsg-mcp(-Bin) | DRSG_INSTALL_BIN | 安装哪个二进制——drsg(默认)、drsg-mcp 或 all |
--version v1.1.0(-Version) | DRSG_VERSION | 指定某个发行版本,而非最新版 |
--dir <path>(-Dir) | DRSG_INSTALL_DIR | 安装目录 |
安装目录默认为 ~/.local/bin,Windows 上为 %LOCALAPPDATA%\Programs\drsg\bin,且脚本
会将该目录加入用户 PATH。在 Linux 与 macOS 上,若该目录尚不在 PATH 中,请将其写入
shell 配置:
$ export PATH="$HOME/.local/bin:$PATH"
升级
drsg update 用与安装脚本相同的方式解析最新发行版本——走 releases/latest 的
重定向,而不是对未认证调用者有速率限制的 API——再与当前运行的构建比较。无事可做
时它会明说并停下:
$ drsg update
drsg 2.27.1 is the latest release — nothing to do
确有新版本时,它会先打印即将执行的命令,然后变成它:进程被首次安装所用的同一 个安装脚本替换,因此退出码就是安装脚本自己的退出码,也不会留下一个父进程等在一个 刚刚被覆盖掉的二进制里。
$ drsg update
drsg 2.27.0 -> 2.27.1
$ curl -fsSL https://raw.githubusercontent.com/wangyingsm/dr-strange/v2.27.1/scripts/install.sh | sh -s -- --bin 'drsg' --version 'v2.27.1' --dir '/home/me/.local/bin'
Dr Strange v2.27.1 (x86_64-unknown-linux-gnu)
downloading dr-strange-v2.27.1-x86_64-unknown-linux-gnu.tar.gz
checksum verified
installed /home/me/.local/bin/drsg
两个阶段都要穿过网络,也都遵循代理设置:版本检查是 drsg 自己发出的请求(参见
在 HTTP 代理之后工作),而它随后交棒的安装脚本由 curl
执行,读取的是同一批变量。在需要代理的网络里,最先失败的是版本检查,因此一次
够不到 GitHub 的 update 根本走不到安装脚本那一步。
它运行的安装脚本是随所装版本一起打了标签的那一份,而非 master 上的副本,
并把该版本作为 --version 一并传入:校验归档的脚本就是与它一同审阅、一同发布的
脚本,移动分支改变不了升级所执行的内容。两个安装脚本都要求归档的 .sha256
校验文件——缺失、格式不对或不匹配都是硬性失败,没有 sha256sum/shasum 可用
也是。--insecure-skip-checksum(PowerShell 中为 -InsecureSkipChecksum;两者
及 drsg update 均可用 DRSG_INSECURE_SKIP_CHECKSUM=1)会带着警告照装不误:它
是给不发布校验文件的镜像用的,名字已说明代价。
安装目录取的是正在运行的这个二进制所在的目录,而不是安装脚本的默认值——升级必须
替换 PATH 上的那一份,而不是在别处放一份更新的、让旧的继续被运行。若 drsg
装在无写权限的位置,用 --dir 覆盖。同一目录下若装有 drsg-mcp,它会随 drsg
一并更新,无需另行指定——两个二进制属于同一个发行版本,若智能体宿主拿上一版的
服务端去对接这一版的 drsg,没有任何东西会提醒它。不想这样时,用 --bin 指明
要更新的对象:drsg、drsg-mcp 或 all。
比最新发行版本更新的构建——来自源码,或来自最后一个标签之后的分支——会被告知
自己在前面,不会安装任何东西:update 从不回退。在 Windows 上则什么都不会运行,
因为正在运行的可执行文件被锁定、无法被覆盖;它转而打印出可在新终端里粘贴执行的
命令。
归档包及其校验和也可以从发行页
直接下载。安装脚本只是对同一批产物的便捷封装,两个脚本都放在
scripts/,可以在
使用前自行查看。
从源码构建
Dr Strange 是一个 Cargo 工作区。编译命令行二进制 drsg:
$ cargo build --release -p drsg
产物为 target/release/drsg。默认构建选用原生 LSM 存储引擎;遗留的 redb 后端仍可
通过特性开关启用。
Web 仪表盘由 web crate 的构建脚本在编译期嵌入二进制。若要嵌入编译好的仪表盘而非占位 页,请在构建二进制之前先编译单页应用:
$ just web-build # bun install && vite build
$ cargo build --release -p drsg
面向 LLM 智能体的 MCP 服务(第 8 章)是一个独立的二进制 drsg-mcp:
$ cargo build --release -p dr-strange-mcp
产物为 target/release/drsg-mcp。将其置于 PATH 中,或在宿主配置里以绝对路径引用它。
磁盘布局
--db 参数用于选择数据库路径。在原生后端下,数据库是一个目录,里面存放着
预写日志(WAL)与有序的 SST 文件,此外还有两个存放检索索引的伴生文件:
graph.drsg/ 数据库(WAL + SST 文件)
graph.drsg.hnsw 向量索引伴生文件
graph.drsg.bm25 关键词索引伴生文件
数据库在首次访问时创建,无需单独的初始化步骤。
创建一张图
先创建一个平面,再插入数据。openCypher 子集会编译为引擎直接执行的同一个逻辑计划:
$ drsg --db graph.drsg plane create social
$ drsg --db graph.drsg cypher --plane social \
'CREATE (a:Person {name:"Ada"}),
(b:Person {name:"Alan"}),
(a)-[:KNOWS]->(b)'
查询结果:
$ drsg --db graph.drsg cypher --plane social \
'MATCH (p:Person)-[:KNOWS]->(q:Person) RETURN q'
检视所得数据的形态与软 schema:
$ drsg --db graph.drsg stats
$ drsg --db graph.drsg catalog --plane social
向量索引与相似度检索
向量是普通的属性值。在某个 (标签, 属性) 对上声明索引,然后对其发起查询。对文本
查询做嵌入是在服务端执行的,因此进程环境中需要一个提供方密钥(例如
OPENAI_API_KEY)。针对字面量向量的查询则不需要任何提供方。
$ drsg --db graph.drsg index ensure Doc embedding --plane social
$ OPENAI_API_KEY=… drsg --db graph.drsg cypher --plane social \
'SEARCH (d:Doc) ON embedding NEAR "a friendly greeting" TOPK 5 RETURN d'
由于结果均为图节点,可从其继续遍历——即第 1 章介绍的 GraphRAG 模式。
运行服务
$ drsg --db graph.drsg serve
此命令启动 JSON-RPC 2.0 接口、WebSocket 变更流以及内嵌的仪表盘,并报告所绑定的
地址(默认 127.0.0.1:7700)。
鉴权。 未配置令牌时,只有同源的浏览器界面可以调用接口。若要允许来自 SDK 或
curl 的程序化访问,请配置一个共享令牌,并以 Bearer 凭据形式携带:
$ DRSG_TOKEN=please-change-me drsg --db graph.drsg serve
监听回环以外的任何地址时令牌是必需的:未设置 DRSG_TOKEN(或 [server] token)
的 drsg serve --addr 0.0.0.0:7700 会拒绝启动,因为离开回环后同源检查不再构成任何
保护。在这类地址上,提供的仪表盘页面也不携带令牌——浏览器每个标签页会询问一次
(见 Web 界面一章),且仪表盘自身的来源须列入 allowed_origins。HTTP 上以
Authorization: Bearer <token> 发送令牌,WebSocket 升级请求也优先如此;/ws 上的
?token= 仅为无法设置请求头的浏览器而设,查询字符串往往会被代理和浏览器记录。
连续五次以上出示错误令牌的对端会收到 429 与一个逐次加倍、至多五分钟的
Retry-After;一次正确的令牌即清除它。
经由 API 指定提供方时,名字只能是某个预设,或恰好是服务端已配置的那个
embed_provider;base URL 只从 CLI 与配置文件接受,绝不从请求接受。
配置文件
服务、日志与提供方设置也可以通过一个 TOML 配置文件提供,而非逐个使用命令行标志与
环境变量。配置文件的解析顺序为:--config <路径>,其次 $DRSG_CONFIG,再次为
当前目录下的 ./drsg.toml(若存在)。系统会拒绝未知的键。
[server]
addr = "0.0.0.0:7700" # 监听地址(命令行 --addr 覆盖此项)
token = "please-change-me" # 共享 API 令牌(→ DRSG_TOKEN);会成为进程环境变量,建议改为在启动环境中导出
max_concurrent = 1024 # 并发请求上限
write_timeout_secs = 30 # 一次写等待单写者槽位多久后以可重试的超时失败(0 表示一直等)
query_timeout_secs = 60 # 一次请求内的查询可运行多久后以同样的方式停止(0 表示跑到结束)
retain_commits = 20 # 时间旅行可回溯的提交数;更早的版本在压缩时回收(0 表示全部保留)。对每个打开数据库的 drsg 命令生效,不只是 serve
source_root = "/srv/myrepo" # grep/snippet 智能体工具读取的源码树(serve watch 会用 --dir 设置它)
mount_root = "/srv/repos" # `drsg mount` 可以从哪一个目录下打开数据库(默认:你的主目录);该目录内平面所记录的树也因此可被 grep/snippet 读取
allowed_origins = ["https://app.example.com"] # 额外允许的浏览器来源
# 把 /mcp 放到域名后面:DRSG_ALLOWED_HOSTS=memory.example.com(环境变量;仅在设置了 token 时生效,见 MCP 一章)
[server.tls] # 存在此节 ⇒ 以 HTTPS 提供服务
cert = "/etc/drsg/cert.pem" # PEM 证书链
key = "/etc/drsg/key.pem" # PEM 私钥
[logging]
dir = "/var/log/drsg" # 滚动日志文件所在目录
[llm] # 提供方密钥,导出至进程环境
OPENAI_API_KEY = "sk-…"
DEEPSEEK_API_KEY = "…"
DASHSCOPE_API_KEY = "…"
DRSG_CHAT_OMIT = "temperature,max_tokens" # 可选:对话请求中省略的字段,供拒绝它们的模型使用
[digest] # 服务端 AIgest 调优
concurrency = 8 # 并发进行的分块抽取调用数
chunk_chars = 4000 # 目标分块大小
embed_provider = "openai" # search / write_nodes / watch 重新向量化所用的嵌入提供方
embed_model = "text-embedding-3-small" # 其模型(各提供方均有默认值)
embed_key_env = "OPENAI_API_KEY" # 存放密钥的环境变量
ignore_files = ["gitignore"] # 由谁的忽略文件决定什么是源码;[] 表示两者都不读
tracked_only = false # 置为 true 则只读取 git 已跟踪的文件
code_only = false # 置为 true 则只读取处理器认领的文件(不含 Markdown/PDF)
[plugins] # 预处理沙箱调优(均可省略)
fuel = 200000000000 # 每次沙箱调用的指令预算(0 为不设限)
memory_mb = 3072 # 每次调用的线性内存上限,MiB;按照 wasm32 标准,最高支持 4096
deadline_secs = 300 # 单次调用的墙钟上限,秒(0 为不设限)
total_memory_mb = 6144 # 进程内所有调用合计可持有的线性内存,MiB(0 为 memory_mb 的两倍)
hostcall_mb = 1024 # 单次调用最多能从沙箱拷出的数据量,MiB(0 为 wasmtime 默认的 128)
[fetch] # URL 导入(第 3 章)
enabled = true # 置为 false 则彻底拒绝 URL 抓取
max_pages = 10 # 单次爬取保留的页数上限
max_depth = 3 # 请求可申请的沿链接深度上限
concurrency = 4 # 并发请求数
allow_private = [] # 见下文——通常保持为空
[network] # 本程序自身发出的请求走向何处
proxy = "http://127.0.0.1:7897" # 也可为 socks5://…;被 ALL_PROXY / HTTPS_PROXY / HTTP_PROXY 覆盖
no_proxy = ".internal, 192.168.1.10" # NO_PROXY 形式的绕行清单;被 NO_PROXY 覆盖
[fetch] 改变的是服务端的网络姿态,在启用其中任何一项之前值得先读一读。当 URL
导入处于开启状态(默认如此)时,客户端可以指定一个地址,而后由服务端去连接它。
服务端在网络中所处的位置通常更为特权,因此系统会拒绝一切不可路由的地址:回环地址、
RFC-1918 私有网段、链路本地地址(169.254.0.0/16,云实例元数据服务在此应答凭据)
等等。检查针对的是解析之后的地址而非主机名,并在每一次重定向跳转时重新执行;
一个内部携带 IPv4 地址的 IPv6 地址(v4-mapped、6to4、Teredo、NAT64 的
64:ff9b::/96)按那个 IPv4 地址判定。
allow_private 用来重新放行特定的 CIDR 网段(例如设为 ["10.0.0.0/8"],以便
读取内网 wiki)。它是上述规则唯一经过深思的例外,而不是关闭这层防护的开关:
暴露给不受信任客户端的服务端应当让它保持为空。若要完全拒绝 URL 抓取,请设置
enabled = false。
在 HTTP 代理之后工作
[network] 管辖的是 drsg 代表你发出的请求:drsg plugin install、
drsg update、drsg digest <url>、LLM 提供方,以及副本拉取快照。可以写在配置
文件里,也可以导出 ALL_PROXY、HTTPS_PROXY 或 HTTP_PROXY 中的任意一个(每个
同时按小写形式读取)。socks5:// 与 http:// 同样受支持。
其中有三条规则值得了解,因为每一条都是经过权衡的决定,而非偶然:
由调用方指定的 URL 绝不走代理。 JSON-RPC 上的 /digest/fetch 与
plugin.install 接受调用方给出的 URL,而上文所述的地址防护正是用来阻止这个 URL
指向服务端自身的回环地址或云元数据端点。代理会代替服务端解析名字并建立连接,防护
因此再无地址可供判断——它在代理之下无法生效,drsg 也不会假装它仍然生效。这些请求
保持直连并受防护约束。当配置了代理时,drsg serve 会在启动时说明这一点。
回环地址永不走代理,无论如何配置。本机模型服务——ollama 预设即
http://localhost:11434/v1——并不是任何人为访问外网而设置 https_proxy 时想要
改道的目标。除此之外的地址一律遵循配置;只有 localhost 与回环网段是自动的。
环境变量优先。 已设置的变量会覆盖配置文件,因此无需改动任何文件即可让单条命令 走另一个代理:
https_proxy=http://127.0.0.1:1080 drsg plugin install ts # 仅本次运行
https_proxy= drsg plugin install ts # 已设置但为空:直连
no_proxy 接受 NO_PROXY 形式的清单,以逗号或空格分隔:精确主机名、.suffix
或 *.suffix 通配、IP 字面量、带端口的条目(example.com:8080),或用 * 表示
全部。不支持 CIDR 网段。环境中的 NO_PROXY 会替换配置文件中的清单,而不是与
之合并。
优先级是固定的:进程中已设置的环境变量始终优先于配置文件中对应的取值,而 --addr
标志覆盖 [server].addr。提供 [server.tls] 会将服务切换为 HTTPS。
只读副本(serve --follow)
以 --follow 启动的第二个 drsg serve 会以只读方式镜像一个正在运行的实例——
用于在一组智能体之间扩展读取,而无需让每一次查询都挤过同一个进程:
$ drsg --db replica.drsg serve --addr 127.0.0.1:7701 \
--follow ws://master-host:7700 --follow-token please-change-me
无论令牌是否有效,任何写入 RPC 都会被拒绝。启动时——以及此后每次断线重连
时——副本都会从主库的 /snapshot 端点拉取一份完整、一致的快照,随后跟随其
/ws/wal 获取后续提交;每次重连都会从零开始重新同步(arch/01 §9),因此
--db 必须指向一个空目录,或指向这个副本自己曾经使用过的目录(由一个
.drsg-follower 标记文件记录)——除此之外的目录会被拒绝,而不是被静默清空。
--follow-token(或 DRSG_FOLLOW_TOKEN)是提交给主库的凭据,与这个副本自己
用来约束其下游客户端的 DRSG_TOKEN 相互独立。当主库的地址不是回环地址时,
--follow 应当指向 wss:// 而非 ws://——否则承载令牌的连接会以明文传输,
这与 [server.tls] 对入站连接的要求是同一个道理。
容器镜像
一个多架构镜像(linux/amd64 与 linux/arm64)已发布至 GitHub 容器镜像仓库
(GHCR)。直接拉取并运行,无需构建:
$ docker run -p 7700:7700 -v drsg-data:/data \
-e DRSG_TOKEN=please-change-me \
ghcr.io/wangyingsm/dr-strange:latest
docker run 会在首次使用时拉取镜像。若需可复现的部署,请以版本标签
ghcr.io/wangyingsm/dr-strange:1.0.2 替代 :latest。运行时镜像绑定到
0.0.0.0:7700,数据库存放在 /data 卷中(原生后端下数据库是一个目录,这个卷
负责把它持久化保存)。提供方密钥通过环境变量传入。
容器中 必须 设置 DRSG_TOKEN:镜像绑定 0.0.0.0,而 drsg serve 在没有令牌时
拒绝非回环绑定,不会把 API 与仪表盘开放给任何能连到该端口的人(容器会退出并
打印指出该变量的消息)。所有客户端都出示这个令牌——SDK 与 curl 作为 bearer,
仪表盘通过它的提示框。在 Docker 宿主机上以 http://localhost:7700 打开仪表盘
无需其他设置;浏览器若以其他名字访问容器——http://graph.example:7700——则该
来源必须列入 DRSG_ALLOWED_ORIGINS(逗号分隔,或 [server] allowed_origins):
离开回环后页面不再携带令牌,未列出的来源会被当作跨站请求拒绝。
对于持久化部署,docker-compose.yml 拉取同一镜像并定义了一个具名卷。它把
DRSG_TOKEN 标记为必填,未设置时 docker compose up 会带消息停下,而不是启动一个
随即退出的容器;DRSG_ALLOWED_ORIGINS 设置了就会透传:
$ DRSG_TOKEN=please-change-me docker compose up
$ DRSG_TOKEN=please-change-me DRSG_ALLOWED_ORIGINS=http://graph.example:7700 docker compose up
若想改为在本地构建镜像,仓库提供了一个多阶段 Dockerfile:它会编译仪表盘、将其
内嵌进二进制,并产出一个精简的运行时镜像:docker build -t dr-strange:latest .。
下一步
- 第 3 章 —— AI 原生: 嵌入、混合检索、自然语言查询与文档导入。
- 第 4 章 —— 查询语言: openCypher 子集及其底层的逻辑计划。
- 按访问方式:第 6 章 —— SDK(应用代码)、第 7 章 —— 嵌入式命令行(运维)、 第 8 章 —— MCP(LLM 智能体)。