xxyyue/llm-observer-proxy-go

GitHub: xxyyue/llm-observer-proxy-go

该项目是一个基于 Go 的运行级 LLM 观察代理,通过内嵌 Bifrost 数据平面记录兼容 OpenAI 和 Anthropic 格式的 LLM 流量,为评估与编排平台提供零外部依赖的可观测性支持。

Stars: 2 | Forks: 0

# LLM Observer Proxy [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/xxyyue/llm-observer-proxy-go/actions/workflows/ci.yml) LLM Observer Proxy 为每次评估或 agent 运行嵌入了一个 Bifrost data plane,并在稳定的 `run_id` 下存储其可观测的 LLM 流量。该观察器会记录请求、响应、流式输出、工具调用、token 使用情况、成本估算、错误以及 provider 可见的推理内容。它不需要 Python、LiteLLM、Docker 或独立的 Bifrost 进程。 它可以独立安装,并通过其 HTTP API 嵌入到任何评估平台、agent 运行器或编排服务中。 ## 工作原理 存在两个 HTTP 层: 1. **控制平面** 默认在端口 `8790` 监听。编排器使用它来创建、检查和停止运行级别的 proxy。 2. 每个 **data plane** 在独立且自动分配的端口上监听。agent 将返回的 URL 用作兼容 OpenAI 或兼容 Anthropic 的 LLM endpoint。 一个控制平面进程可以使用 goroutine 管理多个并发的 data plane。停止 data plane 会保留其在磁盘上的历史记录,并且在控制平面重启后该历史记录依然可读。 该观察器只能记录上游 API 暴露的信息。它无法获取 provider 未返回的隐藏的思维链(chain-of-thought)。 ## 环境要求 - Go 1.26.4 或更高版本,这是 Bifrost Core 的要求 - 上游 API key 和模型目录(model catalog) - 具有绑定控制平面和 data plane 端口的本地权限 较旧的 Go 安装如果配置了 `GOTOOLCHAIN=auto`,可以自动下载 `go.mod` 中声明的工具链。 ## 安装 从 GitHub 安装命令: ``` go install github.com/xxyyue/llm-observer-proxy-go/cmd/llm-observer-proxy@latest ``` 仓库和模块路径名为 `llm-observer-proxy-go`;安装后的命令和服务名为 `llm-observer-proxy`。确保 `$(go env GOPATH)/bin` 包含在 `PATH` 中,然后验证安装: ``` llm-observer-proxy --version ``` 对于源码检出,请运行或构建相同的命令: ``` go run ./cmd/llm-observer-proxy go build -o llm-observer-proxy ./cmd/llm-observer-proxy ``` ## 快速开始 内置的回退目录包含 `gpt-5.5`,并会从环境中读取 OpenAI 凭证: ``` export OPENAI_API_KEY=your-openai-api-key llm-observer-proxy ``` 在另一个终端中,检查控制平面: ``` curl http://127.0.0.1:8790/healthz ``` 为运行创建一个 data plane: ``` curl -X POST http://127.0.0.1:8790/api/runs/run-001/proxy \ -H 'Content-Type: application/json' \ -d '{}' ``` 该 data plane 会服务所选目录中的每个模型。每个 LLM 请求通过其自身的 `model` 字段来选择模型。创建响应包含一个动态分配的基础 `base_url`,例如 `http://127.0.0.1:45678`,以及 `openai_base_url` (`http://127.0.0.1:45678/v1`) 和 `anthropic_base_url` (`http://127.0.0.1:45678`)。为客户端 SDK 使用明确的 URL,或直接调用 endpoint: ``` curl http://127.0.0.1:45678/v1/chat/completions \ -H 'Content-Type: application/json' \ -d '{ "model": "gpt-5.5", "messages": [{"role": "user", "content": "Reply with one short sentence."}] }' ``` 读取标准化历史记录: ``` curl http://127.0.0.1:8790/api/runs/run-001/history ``` 停止 data plane 但不删除其历史记录: ``` curl -X DELETE http://127.0.0.1:8790/api/runs/run-001/proxy ``` ## 配置 该命令接受以下选项: ``` --host HOST Control-plane bind host (default: 127.0.0.1) --port PORT Control-plane port (default: 8790) --env-file PATH KEY=VALUE file loaded before startup (default: .env) --artifact-root PATH Artifact storage root --model-catalog PATH Model catalog JSON --log-level LEVEL Bifrost log level --version Print the build version ``` 路径按以下顺序解析: 1. `--artifact-root` 和 `--model-catalog` 2. `LLM_OBSERVER_PROXY_ARTIFACT_ROOT` 和 `LLM_OBSERVER_PROXY_MODEL_CATALOG_PATH` 3. 工作目录中的 `./artifacts` 和 `./config/models.json` 4. 二进制文件中无内置密钥的嵌入式模型目录 相对路径根据进程工作目录进行解析。可选的 `.env` 文件会在基于环境的路径和凭证解析之前加载,且现有的进程环境变量优先级更高。 ### Bifrost Data Plane 该服务嵌入了 Bifrost Core `v1.6.3` 以及官方的 OpenAI 和 Anthropic provider 包。它不会启动完整的 Bifrost 服务器、Docker 容器或其他进程。该 data plane 保留了公开的兼容 OpenAI 的 `/v1/*` 路由和兼容 Anthropic 的 `/v1/messages` 路由,并将精确的请求和响应 payload 记录在 `events.jsonl` 中,包括 Anthropic 的 system 内容块和 cache-control 标记。 HTTP 路径决定了请求的协议:`/v1/messages` 使用 Anthropic adapter,而其他 `/v1/*` 路径使用 OpenAI adapter。目录中的每个模型都可以通过任一格式接受,因此支持这两种格式的上游可以根据需要进行转换。 ### 模型目录 模型目录具有以下结构: ``` { "llm_observer_proxy": { "base_url": "https://api.openai.com", "api_key": "os.environ/OPENAI_API_KEY" }, "models": [ { "id": "gpt-5.5", "upstream_api": "openai" } ] } ``` `id` 是 data plane 接受的公开模型名称。为了目录兼容性,`upstream_api` 必须是 `openai` 或 `anthropic`,但请求路径会在运行时选择 adapter。`pricing` 下可选的每百万 token 价格用于本地成本估算。其他模型属性将被忽略。`api_key` 接受文字值、`os.environ/NAME`、`env.NAME` 或 `${NAME}`。目前,目录中的所有模型共享同一个上游 `base_url` 和凭证。完整示例请参见 `config/models.example.json`。 当不存在 `llm_observer_proxy` 时,旧版的顶层目录键 `llm_proxy` 依然会被接受。 ## 控制 API | 方法 | 路径 | 用途 | | --- | --- | --- | | `GET` | `/healthz` | 检查控制平面健康状况 | | `GET` | `/api/proxies` | 列出进程本地正在运行和已停止的 proxy | | `POST` | `/api/runs/{run_id}/proxy` | 创建一个运行级别的 data plane | | `GET` | `/api/runs/{run_id}/proxy` | 读取 proxy 状态 | | `DELETE` | `/api/runs/{run_id}/proxy` | 停止一个 data plane | | `GET` | `/api/runs/{run_id}/history` | 读取标准化历史记录 | | `GET` | `/api/runs/{run_id}/conversation` | 读取最新对话 | 创建 payload 可以为空。可选的活动字段包括 `port` 和 `bind_host`。兼容性字段(包括 `model`、`mode`、`backend`、`litellm_config_path`、`litellm_env` 和 `strip_callbacks`)会被接受并忽略,未知字段也会被忽略。完整的请求和响应契约记录在 `docs/control-plane-api.md` 中。 ## Artifacts 每次运行会写入: ``` artifacts/runs//platform/llm/ config.json conversation_snapshot.json events.jsonl bifrost.log ``` `events.jsonl` 保留原始的请求和响应、流式传输主体、使用情况、工具调用、可见的推理内容、错误以及标准化摘要。`conversation_snapshot.json` 包含最新重构的对话。`config.json` 包含非机密的运行元数据,`bifrost.log` 作为兼容性路径被保留。 传入的 `Authorization` 和 `x-api-key` header 在 artifacts 中会被脱敏。请求和响应主体会被特意保留,其中可能包含敏感数据,因此请对 artifact 根目录应用适当的文件系统权限、访问控制和保留策略。 ## 支持范围 受支持的 data plane 接口为兼容 OpenAI 的 `/v1/*` 路由和 Anthropic 的 `/v1/messages`,以及上述文档中提到的控制和历史 API。Bifrost 的管理服务器、管理 UI、数据库持久化、插件、治理功能、其他 provider 和 MCP runtime 不属于本项目兼容性契约的一部分。Bifrost 的共享 schema 包导入了 MCP 类型,因此即使没有配置或执行任何 MCP 代码,`mcp-go` 依然是一个传递性的编译依赖项。 ## 故障排除 - **Proxy 创建返回 `400`:** 检查 run ID、请求的端口、绑定地址、目录以及文件系统权限。 - **Proxy 创建返回 `409`:** 该 `run_id` 已经有一个正在运行的 data plane。 - **LLM 请求失败:** 确认上游 `base_url`、凭证环境变量、请求路径和模型名称。Provider 错误会记录在 `events.jsonl` 中。 - **历史记录为空:** 确认 agent 使用的是返回的 data plane URL,而不是直接使用 provider 的 URL。 - **安装后未找到 `llm-observer-proxy`:** 将 `$(go env GOPATH)/bin` 添加到 `PATH` 中。 ## 安全 控制 API 是一个管理接口:它可以启动 listener、选择监听端口并存储 LLM 流量。版本 0.1.x 没有内置身份验证。请将其绑定到 loopback 或受信任的专用网络,并在远程部署前阅读 `.github/SECURITY.md`。 历史记录可能包含 prompt、模型输出、工具输出和凭证。请对 artifact 根目录应用适当的文件系统权限、访问控制和保留策略。 ## 开发 ``` test -z "$(gofmt -l cmd internal)" go mod tidy git diff --exit-code -- go.mod go.sum go vet ./... go test -race ./... go build -trimpath ./cmd/llm-observer-proxy ``` ## 许可证 Apache-2.0。请参见 `LICENSE` 和 `NOTICE`。 ## 作者 - Shuqiao Zhang - Yue Xiong
标签:AI监控, DLL 劫持, EVTX分析, Go语言, LLM可观测性, Petitpotam, Python脚本, 大语言模型, 数据平面, 日志审计, 流量代理, 程序破解