Skip to content

Commit 0c0fa80

Browse files
authored
feat(ai-proxy): add provider-aware max_tokens override with priority control (#13251)
1 parent 4c67a31 commit 0c0fa80

18 files changed

Lines changed: 840 additions & 31 deletions

File tree

apisix/plugins/ai-protocols/init.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ function _M.get(name)
6565
end
6666

6767

68+
6869
--- Find a converter that can bridge from client_protocol to a protocol
6970
-- supported by the driver. Delegates to the converters registry.
7071
-- @param client_protocol string The detected client protocol

apisix/plugins/ai-providers/aimlapi.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
1826
return require("apisix.plugins.ai-providers.base").new(
1927
{
2028
host = "api.aimlapi.com",
2129
port = 443,
2230
capabilities = {
23-
["openai-chat"] = { path = "/chat/completions" },
31+
["openai-chat"] = {
32+
path = "/chat/completions",
33+
rewrite_request_body = rewrite_chat_request_body,
34+
},
2435
},
2536
}
2637
)

apisix/plugins/ai-providers/anthropic.lua

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,36 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
26+
27+
local function rewrite_messages_request_body(body, override, force)
28+
if override.max_tokens then
29+
if force or body.max_tokens == nil then
30+
body.max_tokens = override.max_tokens
31+
end
32+
end
33+
end
34+
1835
return require("apisix.plugins.ai-providers.base").new(
1936
{
2037
host = "api.anthropic.com",
2138
port = 443,
2239
capabilities = {
23-
["openai-chat"] = { path = "/v1/chat/completions" },
24-
["anthropic-messages"] = { path = "/v1/messages" },
40+
["openai-chat"] = {
41+
path = "/v1/chat/completions",
42+
rewrite_request_body = rewrite_chat_request_body,
43+
},
44+
["anthropic-messages"] = {
45+
path = "/v1/messages",
46+
rewrite_request_body = rewrite_messages_request_body,
47+
},
2548
},
2649
}
2750
)

apisix/plugins/ai-providers/azure-openai.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
1826
return require("apisix.plugins.ai-providers.base").new(
1927
{
2028
port = 443,
2129
remove_model = true,
2230
capabilities = {
23-
["openai-chat"] = { path = "/completions" },
31+
["openai-chat"] = {
32+
path = "/completions",
33+
rewrite_request_body = rewrite_chat_request_body,
34+
},
2435
},
2536
}
2637
)

apisix/plugins/ai-providers/base.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function _M.build_request(self, ctx, conf, request_body, opts)
173173
or opts.target_host or self.host,
174174
}
175175

176-
-- Inject model options
176+
-- Inject model options (flat overwrite)
177177
if opts.model_options then
178178
for opt, val in pairs(opts.model_options) do
179179
if request_body[opt] ~= nil then
@@ -182,6 +182,15 @@ function _M.build_request(self, ctx, conf, request_body, opts)
182182
request_body[opt] = val
183183
end
184184
end
185+
186+
-- Apply request body override via provider capability hook
187+
if opts.override_request_body then
188+
local cap = self.capabilities and self.capabilities[ctx.ai_target_protocol]
189+
if cap and cap.rewrite_request_body then
190+
cap.rewrite_request_body(request_body, opts.override_request_body,
191+
opts.request_body_force_override)
192+
end
193+
end
185194
params.body = request_body
186195

187196
if self.remove_model then

apisix/plugins/ai-providers/deepseek.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
1826
return require("apisix.plugins.ai-providers.base").new(
1927
{
2028
host = "api.deepseek.com",
2129
port = 443,
2230
capabilities = {
23-
["openai-chat"] = { path = "/chat/completions" },
31+
["openai-chat"] = {
32+
path = "/chat/completions",
33+
rewrite_request_body = rewrite_chat_request_body,
34+
},
2435
},
2536
}
2637
)

apisix/plugins/ai-providers/gemini.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_completion_tokens == nil then
21+
body.max_completion_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
1826
return require("apisix.plugins.ai-providers.base").new(
1927
{
2028
host = "generativelanguage.googleapis.com",
2129
port = 443,
2230
capabilities = {
23-
["openai-chat"] = { path = "/v1beta/openai/chat/completions" },
31+
["openai-chat"] = {
32+
path = "/v1beta/openai/chat/completions",
33+
rewrite_request_body = rewrite_chat_request_body,
34+
},
2435
},
2536
}
2637
)

apisix/plugins/ai-providers/openai-compatible.lua

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,33 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
26+
27+
local function rewrite_responses_request_body(body, override, force)
28+
if override.max_tokens then
29+
if force or body.max_output_tokens == nil then
30+
body.max_output_tokens = override.max_tokens
31+
end
32+
end
33+
end
34+
1835
return require("apisix.plugins.ai-providers.base").new({
1936
capabilities = {
20-
["openai-chat"] = { path = "/v1/chat/completions" },
21-
["openai-responses"] = { path = "/v1/responses" },
37+
["openai-chat"] = {
38+
path = "/v1/chat/completions",
39+
rewrite_request_body = rewrite_chat_request_body,
40+
},
41+
["openai-responses"] = {
42+
path = "/v1/responses",
43+
rewrite_request_body = rewrite_responses_request_body,
44+
},
2245
["openai-embeddings"] = { path = "/v1/embeddings" },
2346
},
2447
})

apisix/plugins/ai-providers/openai.lua

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,37 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or (body.max_completion_tokens == nil and body.max_tokens == nil) then
21+
body.max_completion_tokens = override.max_tokens
22+
body.max_tokens = nil
23+
end
24+
end
25+
end
26+
27+
28+
local function rewrite_responses_request_body(body, override, force)
29+
if override.max_tokens then
30+
if force or body.max_output_tokens == nil then
31+
body.max_output_tokens = override.max_tokens
32+
end
33+
end
34+
end
35+
1836
return require("apisix.plugins.ai-providers.base").new(
1937
{
2038
host = "api.openai.com",
2139
port = 443,
2240
capabilities = {
23-
["openai-chat"] = { path = "/v1/chat/completions" },
24-
["openai-responses"] = { path = "/v1/responses" },
41+
["openai-chat"] = {
42+
path = "/v1/chat/completions",
43+
rewrite_request_body = rewrite_chat_request_body,
44+
},
45+
["openai-responses"] = {
46+
path = "/v1/responses",
47+
rewrite_request_body = rewrite_responses_request_body,
48+
},
2549
["openai-embeddings"] = { path = "/v1/embeddings" },
2650
},
2751
}

apisix/plugins/ai-providers/openrouter.lua

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,23 @@
1515
-- limitations under the License.
1616
--
1717

18+
local function rewrite_chat_request_body(body, override, force)
19+
if override.max_tokens then
20+
if force or body.max_tokens == nil then
21+
body.max_tokens = override.max_tokens
22+
end
23+
end
24+
end
25+
1826
return require("apisix.plugins.ai-providers.base").new(
1927
{
2028
host = "openrouter.ai",
2129
port = 443,
2230
capabilities = {
23-
["openai-chat"] = { path = "/api/v1/chat/completions" },
31+
["openai-chat"] = {
32+
path = "/api/v1/chat/completions",
33+
rewrite_request_body = rewrite_chat_request_body,
34+
},
2435
},
2536
}
2637
)

0 commit comments

Comments
 (0)