Files
laya-hook/README.zh-CN.md

141 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Laya Router Hook
[English](README.md)
本地常驻 [Laya](https://github.com/NandhaKishorM/laya) multilingual 模型。Codex 或 Claude Code 收到 prompt 之前,hook 会补上一条 System-1 提示:任务复杂度,以及要不要做计划、读仓库、查文档、仔细推理。
它不切换模型。当前会话用哪一个模型,仍由 Codex / Claude Code 自己的配置决定。
```text
Prompt
-> UserPromptSubmit hook(只依赖标准库,失败则放行)
-> http://127.0.0.1:8765
-> Laya multilingual
-> additionalContext
-> Codex / Claude Code
```
浏览器打开 [http://127.0.0.1:8765/](http://127.0.0.1:8765/) 可以按会话看每次判断。页面用服务端事件实时追加。
Cursor 会加载 Claude Code 的 hook,但当前事件无法把上下文注入对话。Hook 发现 `CURSOR_VERSION` 时直接返回。
## 安装
需要 macOS、[uv](https://docs.astral.sh/uv/getting-started/installation/) 和 Python 3.10+。
```bash
./install.sh
```
脚本会:
1. 在 `~/.laya-router/.venv` 创建虚拟环境,并把本仓库安装进去
2. 下载 `convaiinnovations/laya` 的 `multilingual` 权重
3. 注册 launchd 用户服务 `com.laya-router`(登录自启,进程退出后拉起)
4. 检测到 Codex 或 Claude Code 时写入 hook
安装的是普通副本,不是可编辑安装。仓库如果在 `~/Documents` 下,launchd 直接 import 那个目录会卡在文件打开上。`laya-router restart` 会把当前仓库同步进虚拟环境再重启。
只注册一边:
```bash
./install.sh --only codex
./install.sh --only claude
```
Codex 第一次会要求信任 hook。启动 `codex` 后运行 `/hooks`。命令字符串不变时,修改 Python 不会再次要求审查。
## 日常命令
命令在 `~/.laya-router/.venv/bin`。
```bash
laya-router status
laya-router logs
laya-router logs -f
laya-router route "帮我把这个函数的变量名改掉"
laya-router restart
laya-router stop
laya-router start
```
卸掉 hook 和服务,保留运行目录:
```bash
./uninstall.sh
```
连同配置、日志、虚拟环境一起删除:
```bash
./uninstall.sh --purge
```
## 配置
`~/.laya-router/config.toml` 在首次安装时生成,之后不会被覆盖。
| 键 | 含义 |
| --- | --- |
| `host` | 监听地址。保持 `127.0.0.1`。 |
| `port` | 默认 `8765`。 |
| `device` | `auto`、`mps`、`cuda` 或 `cpu`。`auto` 预热失败会回退。 |
| `log_prompts` | 是否把原文写入 `data/routes.jsonl`。 |
| `request_timeout` | Hook 等待服务的秒数,默认 `2.5`。 |
| `max_prompt_chars` | 送进模型的最大字符数。超长时保留头尾。 |
改完配置或服务端代码后执行 `laya-router restart`。
## 一次判断里有什么
一次前向同时问五个问题:
- `task_level`:`simple`、`normal`、`complex`
- `needs_plan`、`needs_repo`、`needs_web`、`needs_deep_reasoning`:0 到 1 的概率
`laya-multilingual` 没有自带温度校准,界面上的 0.90 不是校准后的 90%。注入给 Agent 的文本也写明了这只是提示。没有使用 ordinal `score`,Laya 自己的基准里它是最弱的一种输出。
每次调用追加到 `~/.laya-router/data/routes.jsonl`(时间、客户端、目录、会话、prompt、分数、耗时、问题版本)。关掉原文记录后只留 SHA-256。这份日志是以后按自己的编程任务做微调的材料。
服务挂了时,hook 输出 `{}` 并退出 0,Codex 和 Claude Code 照常工作。原因写在 `~/.laya-router/logs/hook.log`。
## 开发
```bash
PYTHONPATH=src uv run --no-project --with pytest python -m pytest
```
单元测试不加载模型。服务起来之后,用 `laya-router route` 做真实推理。
| 文件 | 作用 | 生效 |
| --- | --- | --- |
| `src/laya_router/questions.py` | 问题措辞。改措辞时把 `QUESTIONS_VERSION` 加一。 | `laya-router restart` |
| `src/laya_router/render.py` | 注入给 Agent 的文本 | `laya-router restart`,然后下一条 prompt |
| `src/laya_router/hook.py` | 超时、跳过斜杠命令、失败放行 | `laya-router restart`,然后下一条 prompt |
| `src/laya_router/server.py` | 加载模型、`/route`、看板 | `laya-router restart` |
| `src/laya_router/dashboard.html` | 浏览器页面 | `laya-router restart` |
不要给服务加 `--reload`。开发模式会再起进程,把模型加载多次。
## 安全
这个仓库里没有 API Key、账号 token 或模型权重。安装程序也不会上传 `~/.claude/settings.json` 或 `~/.codex`。
服务没有鉴权,默认只听 `127.0.0.1`。`/route` 接受任意 prompt,看板会显示已经记下的原文。把 `host` 改成其他地址后,谁能访问这个端口,谁就能看到 prompt 并调用模型。如果绑定地址不是回环地址,进程会在标准错误里警告。不要把这个端口暴露到公网,也不要在没有自行加上鉴权之前做反向代理。
`routes.jsonl` 默认保存完整 prompt,包括你贴进 Codex 或 Claude Code 的内容。`log_prompts = false` 时只保存 SHA-256。运行目录是仓库外面的 `~/.laya-router/`,不要把它提交进 git。
安装程序会改写 `~/.codex/hooks.json`,并往 `~/.claude/settings.json` 合并一条 `UserPromptSubmit`。Claude 的这个文件里常常有 API 凭证。程序会保留原有字段,改文件前写一份带时间戳的 `*.bak-*`,卸载时只删自己的 hook。公开任何本机配置之前先看 diff。
其他网站的页面读不到这些接口:服务没有发送 `Access-Control-Allow-Origin`。监听地址仍然应该保持默认。
Hook 只附加分数和建议,不会把用户 prompt 再抄进注入指令里。
## 限度
multilingual 基础模型适合按领域微调,不是开箱即用的编程路由器。公开的 typed-decision 数字里,基础 checkpoint 在微调之前接近随机。复杂请求被标成 `simple` 是预期中的情况。先积累日志再微调,然后再考虑用它来选模型。
## 许可证
仓库里还没有许可证文件。公开发布前需要补上。Laya 模型和库是 Apache-2.0;本项目的许可证需要单独选择。