tim-peyeeye opened a new pull request, #13300:
URL: https://github.com/apache/apisix/pull/13300

   ## What this PR adds
   
   A new AI plugin, `ai-peyeeye`, that performs PII redaction on the request 
body sent upstream to an LLM and rehydrates the LLM's response before it 
reaches the client. It is designed to sit alongside `ai-proxy` / 
`ai-proxy-multi` on the same route, at priority `1074` (ahead of `ai-proxy`'s 
`1040`), and calls the peyeeye.ai HTTP API:
   
   - `POST /v1/redact` — pre-call, replaces detected entities with 
deterministic tokens (e.g. `[EMAIL_1]`, `[CARD_2]`).
   - `POST /v1/rehydrate` — post-call, swaps the tokens in the LLM's response 
back to the original values.
   - `DELETE /v1/sessions/<id>` — best-effort cleanup for stateful sessions.
   
   ### Behavior
   
   - **Pre-call redact (`access` phase)**: extracts text from the OpenAI-style 
`messages[].content` array (string or content-part `text`), batches it to 
`/v1/redact`, and rewrites the body in place. The detection engine is regex + 
checksum-validated (Luhn for cards, mod-97 for IBAN, SSN/IP shape) on the 
peyeeye side, so the gateway just sends/receives strings.
   - **Post-call rehydrate (`body_filter` phase)**: buffers the upstream 
response, then calls `/v1/rehydrate` with the buffered body and the session id 
(or sealed `skey_…` blob).
   - **Two session modes**:
     - `stateful` (default): peyeeye returns a `ses_…` session id; the plugin 
stores it on the request context and `DELETE`s it after rehydrate.
     - `stateless`: peyeeye returns an AES-GCM-sealed `skey_…` blob containing 
the token map; nothing is retained server-side.
   - **Fail-closed length-guard**: if `/v1/redact` returns a different number 
of texts than were sent, the request is failed with HTTP 500. Unredacted text 
is never forwarded upstream.
   - **Fail-closed shape-guard**: if `/v1/redact` returns an unexpected 
response shape (missing `texts`, missing session/key for the chosen mode), the 
request is failed with HTTP 500.
   - **Best-effort rehydrate**: if `/v1/rehydrate` fails (network, 5xx), the 
redacted output is preserved rather than risking PII leakage by falling back to 
the raw upstream response.
   - **Auth required**: missing `api_key` (in config or `PEYEEYE_API_KEY` env 
var) fails schema validation.
   - **Empty-body short-circuit**: requests with no extractable text skip the 
redact call entirely.
   
   ## Files added
   
   - `apisix/plugins/ai-peyeeye.lua` — the plugin (546 lines)
   - `apisix/cli/config.lua` — registration in the default plugin list
   - `conf/config.yaml.example` — example entry
   - `t/admin/plugins.t` — admin plugin list assertion
   - `t/plugin/ai-peyeeye.t` — test suite (445 lines), follows the 
`ai-prompt-guard` / `ai-aliyun-content-moderation` pattern: mocks the peyeeye 
HTTP API and a fake LLM upstream so the tests have no external dependencies. 
Covers:
     - schema validation (3 cases)
     - stateful redact + rehydrate end-to-end
     - stateless mode (sealed `skey_…`)
     - length-guard fail-closed branch
     - unexpected-response-shape fail-closed branch
     - empty-body short-circuit
   - `docs/en/latest/plugins/ai-peyeeye.md` + `docs/en/latest/config.json`
   - `docs/zh/latest/plugins/ai-peyeeye.md` + `docs/zh/latest/config.json`
   
   ## Test status — please read
   
   I want to be transparent here: **I was not able to run 
`t/plugin/ai-peyeeye.t` locally**, because APISIX's test framework requires a 
custom `apisix-runtime` build (custom OpenResty plus a `toolkit.json` Lua 
module) that I could not reproduce on macOS — `toolkit.json` is not packaged in 
any public OpenResty/LuaRocks artifact I could find, and the `make deps` path 
against stock OpenResty fails before the test runner can start. I'm relying on 
this PR's CI (`apache/apisix`'s test workflow) to actually exercise the suite.
   
   Static checks that **did** pass locally:
   
   - `luacheck apisix/plugins/ai-peyeeye.lua t/plugin/ai-peyeeye.t` — clean, no 
warnings.
   - `luajit -bl apisix/plugins/ai-peyeeye.lua` — parses cleanly (no syntax 
errors).
   
   If CI surfaces issues, I'll iterate on this PR. If a maintainer can point me 
at a working local test setup for macOS (or a CI job I can self-trigger on the 
fork), I'd appreciate it.
   
   ## Disclosure
   
   I'm the maintainer of [peyeeye.ai](https://peyeeye.ai). Happy to adjust API 
surface, naming, or test coverage to match your conventions.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to