nic-6443 commented on code in PR #13231:
URL: https://github.com/apache/apisix/pull/13231#discussion_r3092801306


##########
apisix/core/json.lua:
##########
@@ -34,14 +36,47 @@ cjson.decode_array_with_array_mt(true)
 local _M = {
     version = 0.1,
     array_mt = cjson.array_mt,
-    decode = cjson.decode,
+    null = cjson_null,
     -- This method produces the same encoded string when the input is not 
changed.
     -- Different calls with cjson.encode will produce different string because
     -- it doesn't maintain the object key order.
     stably_encode = require("dkjson").encode
 }
 
 
+local function strip_nulls(t)
+    for k, v in pairs(t) do
+        if v == cjson_null then
+            t[k] = nil
+        elseif type(v) == "table" then
+            strip_nulls(v)
+        end
+    end

Review Comment:
   Good observation about array holes. In practice, AI API responses use `null` 
exclusively in object fields (`prompt_tokens_details: null`, `usage: null`, 
`message: null`), not as array elements — `choices`, `content`, `tool_calls` 
arrays never contain `null` entries per the OpenAI/Anthropic specs. The 
`ipairs` concern is theoretical here but I'll add a doc comment noting this 
behavior.



##########
apisix/plugins/ai-providers/base.lua:
##########
@@ -209,7 +209,7 @@ function _M.parse_response(self, ctx, res, client_proto, 
converter)
     ctx.var.llm_time_to_first_token = math.floor((ngx_now() - 
ctx.llm_request_start_time) * 1000)
     ctx.var.apisix_upstream_response_time = ctx.var.llm_time_to_first_token
 
-    local res_body, decode_err = core.json.decode(raw_res_body)
+    local res_body, decode_err = core.json.decode(raw_res_body, { null_as_nil 
= true })

Review Comment:
   The mentioned call sites are intentionally not using `null_as_nil`:
   - `anthropic-messages-to-openai-chat.lua:244` decodes 
`tc["function"].arguments` — a JSON string embedded in the already-decoded 
response (function call args from the LLM). The outer response was already 
decoded with `null_as_nil` in `base.lua:parse_response`.
   - `ai-aliyun-content-moderation.lua` is a separate plugin (content 
moderation), not part of the AI proxy/protocol conversion pipeline that 
triggered this bug. Its responses have a different schema.
   
   The scope is specifically the AI proxy pipeline where Anthropic/OpenAI 
protocol conversion happens.



-- 
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