moonming commented on code in PR #12036:
URL: https://github.com/apache/apisix/pull/12036#discussion_r1996534643


##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |

Review Comment:
   ```suggestion
   | prompt                    | Yes          | String   | The prompt send to 
LLM service.                                                              |
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway

Review Comment:
   ```suggestion
     - AI Gateway
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.

Review Comment:
   ```suggestion
   The `ai-request-rewrite` plugin intercepts client requests before they are 
forwarded to the upstream service. It sends a predefined prompt, along with the 
original request body, to a specified LLM service. The LLM processes the input 
and returns a modified request body, which is then used for the upstream 
request. This allows dynamic transformation of API requests based on 
AI-generated content.
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |

Review Comment:
   need examples of `model`



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |
+| override.endpoint         | No           | String   | To be specified to 
override the endpoint of the AI service                          |
+| timeout                   | No           | Integer  | Timeout in 
milliseconds for requests to AI service. Range: 1 - 60000. Default: 3000        
 |
+| keepalive                 | No           | Boolean  | Enable keepalive for 
requests to AI service. Default: true                                  |
+| keepalive_timeout         | No           | Integer  | Keepalive timeout in 
milliseconds for requests to AI service. Minimum: 1000. Default: 60000 |
+| keepalive_pool            | No           | Integer  | Keepalive pool size 
for requests to AI service. Minimum: 1. Default: 30                     |
+| ssl_verify                | No           | Boolean  | SSL verification for 
requests to AI service. Default: true                                  |
+
+## How it works
+
+![image](https://github.com/user-attachments/assets/c7288e4f-00fc-46ca-b69e-d3d74d7085ca)
+
+## Example usage
+
+Create a route with the `ai-request-rewrite` plugin like:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes/1"; -X PUT \
+  -H "X-API-KEY: ${ADMIN_API_KEY}" \
+  -d '{
+    "uri": "/anything",
+    "plugins": {
+      "ai-request-rewrite": {
+        "prompt": "Given a JSON request body, identify and mask any sensitive 
information such as credit card numbers, social security numbers, and personal 
identification numbers (e.g., passport or driver'\''s license numbers). Replace 
detected sensitive values with a masked format (e.g., \"*** **** **** 1234\") 
for credit card numbers. Ensure the JSON structure remains unchanged.",
+        "provider": "openai",
+        "auth": {
+          "header": {
+            "Authorization": "Bearer <some-token>"
+          }
+        },
+        "options": {
+          "model": "gpt-4"
+        }
+      }
+    },
+    "upstream": {
+      "type": "roundrobin",
+      "nodes": {
+        "httpbin.org:80": 1
+      }
+    }
+  }'
+```
+
+Now send a request:
+
+```shell
+curl "http://127.0.0.1:9080/anything"; \
+  -H "Content-Type: application/json" \
+  -d '{
+    "name": "John Doe",
+    "email": "[email protected]",
+    "credit_card": "4111 1111 1111 1111",
+    "ssn": "123-45-6789",
+    "address": "123 Main St"
+  }'
+```
+
+The request body for AI Service is as follows:

Review Comment:
   ```suggestion
   The request body send to the LLM Service is as follows:
   ```



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)

Review Comment:
   ```suggestion
       local response_table, err = core.json.decode(res_body)
   ```



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end

Review Comment:
   do we need to log the llm response here?



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end
+
+    if not response_table.choices then
+        return nil, "'choices' not in llm response"
+    end
+
+    return response_table.choices[1].message.content, nil

Review Comment:
   what will happen if response_table.choices[1].message is nil?



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |
+| override.endpoint         | No           | String   | To be specified to 
override the endpoint of the AI service                          |
+| timeout                   | No           | Integer  | Timeout in 
milliseconds for requests to AI service. Range: 1 - 60000. Default: 3000        
 |
+| keepalive                 | No           | Boolean  | Enable keepalive for 
requests to AI service. Default: true                                  |
+| keepalive_timeout         | No           | Integer  | Keepalive timeout in 
milliseconds for requests to AI service. Minimum: 1000. Default: 60000 |
+| keepalive_pool            | No           | Integer  | Keepalive pool size 
for requests to AI service. Minimum: 1. Default: 30                     |
+| ssl_verify                | No           | Boolean  | SSL verification for 
requests to AI service. Default: true                                  |
+
+## How it works
+
+![image](https://github.com/user-attachments/assets/c7288e4f-00fc-46ca-b69e-d3d74d7085ca)
+
+## Example usage
+
+Create a route with the `ai-request-rewrite` plugin like:
+
+```shell
+curl "http://127.0.0.1:9180/apisix/admin/routes/1"; -X PUT \
+  -H "X-API-KEY: ${ADMIN_API_KEY}" \
+  -d '{
+    "uri": "/anything",
+    "plugins": {
+      "ai-request-rewrite": {
+        "prompt": "Given a JSON request body, identify and mask any sensitive 
information such as credit card numbers, social security numbers, and personal 
identification numbers (e.g., passport or driver'\''s license numbers). Replace 
detected sensitive values with a masked format (e.g., \"*** **** **** 1234\") 
for credit card numbers. Ensure the JSON structure remains unchanged.",
+        "provider": "openai",
+        "auth": {
+          "header": {
+            "Authorization": "Bearer <some-token>"
+          }
+        },
+        "options": {
+          "model": "gpt-4"
+        }
+      }
+    },
+    "upstream": {
+      "type": "roundrobin",
+      "nodes": {
+        "httpbin.org:80": 1
+      }
+    }
+  }'
+```
+
+Now send a request:
+
+```shell
+curl "http://127.0.0.1:9080/anything"; \
+  -H "Content-Type: application/json" \
+  -d '{
+    "name": "John Doe",
+    "email": "[email protected]",
+    "credit_card": "4111 1111 1111 1111",
+    "ssn": "123-45-6789",
+    "address": "123 Main St"
+  }'
+```
+
+The request body for AI Service is as follows:
+
+```json
+{
+  "messages": [
+     {
+       "role": "system",
+       "content": "Given a JSON request body, identify and mask any sensitive 
information such as credit card numbers, social security numbers, and personal 
identification numbers (e.g., passport or driver's license numbers). Replace 
detected sensitive values with a masked format (e.g., '*** **** **** 1234') for 
credit card numbers). Ensure the JSON structure remains unchanged."
+     },
+     {
+       "role": "user",
+       "content": "{\n\"name\":\"John 
Doe\",\n\"email\":\"[email protected]\",\n\"credit_card\":\"4111 1111 1111 
1111\",\n\"ssn\":\"123-45-6789\",\n\"address\":\"123 Main St\"\n}"
+     }
+   ]
+}
+
+```
+
+The upstream service will receive a request like this:

Review Comment:
   ```suggestion
   The LLM processes the input and returns a modified request body, which 
replace detected sensitive values with a masked format then used for the 
upstream request:
   ```



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"

Review Comment:
   read or send timeout?



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |

Review Comment:
   ```suggestion
   | provider                  | Yes          | String   | Name of the LLM 
service.                                                     |
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.

Review Comment:
   need to desc the feature of this plugin.



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |
+| override.endpoint         | No           | String   | To be specified to 
override the endpoint of the AI service                          |
+| timeout                   | No           | Integer  | Timeout in 
milliseconds for requests to AI service. Range: 1 - 60000. Default: 3000        
 |

Review Comment:
   timeout only 3 seconds? the read timeout or connect timeout?



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |
+| override.endpoint         | No           | String   | To be specified to 
override the endpoint of the AI service                          |

Review Comment:
   ditto



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."

Review Comment:
   need a more detail desc and examples



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end
+
+    if not response_table.choices then
+        return nil, "'choices' not in llm response"
+    end
+
+    return response_table.choices[1].message.content, nil

Review Comment:
   ```suggestion
       return response_table.choices[1].message.content
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |

Review Comment:
   And need to give the scope of `provider`: openai, deekseek or others.



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end
+
+    if not response_table.choices then
+        return nil, "'choices' not in llm response"
+    end
+
+    return response_table.choices[1].message.content, nil
+end
+
+
+function _M.check_schema(conf)
+    -- openai-compatible should be used with override.endpoint
+    if conf.provider == "openai-compatible" then
+        local override = conf.override
+
+        if not override or not override.endpoint then
+            return false, "override.endpoint is required for openai-compatible 
provider"
+        end
+    end
+
+    return core.schema.check(schema, conf)
+end
+
+
+function _M.access(conf, ctx)
+    local client_request_table, err = core.request.get_body()
+    if not client_request_table then
+        core.log.error("failed to get request body: ", err)
+        return bad_request, err
+    end
+
+    -- Prepare request for LLM service
+    local ai_request_table = {
+        messages = {
+            {
+                role = "system",
+                content = conf.prompt
+            },
+            {
+                role = "user",
+                content = client_request_table
+            }
+        },
+        stream = false
+    }
+
+    -- Send request to LLM service
+    local res, err, httpc = proxy_request_to_llm(conf, ai_request_table, ctx)
+    if not res then
+        core.log.error("failed to send request to LLM service: ", err)
+        return internal_server_error
+    end
+
+    -- Handle LLM response
+    if res.status >= 400 then
+        core.log.error("LLM service returned error status: ", res.status)

Review Comment:
   need to log detail error message



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end

Review Comment:
   ```suggestion
       if not response_table then 
           return nil, "failed to decode llm response " .. ", err: " .. err
       end
   ```



##########
docs/en/latest/plugins/ai-request-rewrite.md:
##########
@@ -0,0 +1,167 @@
+---
+title: ai-request-rewrite
+keywords:
+  - Apache APISIX
+  - API Gateway
+  - Plugin
+  - ai-request-rewrite
+description: This document contains information about the Apache APISIX 
ai-request-rewrite Plugin.
+---
+
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+-->
+
+## Description
+
+The `ai-request-rewrite` plugin leverages predefined prompts and AI services 
to intelligently modify client requests, enabling AI-powered content 
transformation before forwarding to upstream services.
+
+## Plugin Attributes
+
+| **Field**                 | **Required** | **Type** | **Description**        
                                                              |
+| ------------------------- | ------------ | -------- | 
------------------------------------------------------------------------------------
 |
+| prompt                    | Yes          | String   | The prompt send to AI 
service.                                                              |
+| provider                  | Yes          | String   | Type of the AI 
service.                                                     |
+| auth                      | Yes          | Object   | Authentication 
configuration                                                         |
+| auth.header               | No           | Object   | Authentication 
headers. Key must match pattern `^[a-zA-Z0-9._-]+$`.                  |
+| auth.query                | No           | Object   | Authentication query 
parameters. Key must match pattern `^[a-zA-Z0-9._-]+$`.         |
+| options                   | No           | Object   | Key/value settings for 
the model                                                     |
+| options.model             | No           | String   | Model to execute.      
                                                              |
+| override.endpoint         | No           | String   | To be specified to 
override the endpoint of the AI service                          |

Review Comment:
   when we need endpoint?



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end
+
+    if not response_table.choices then
+        return nil, "'choices' not in llm response"
+    end
+
+    return response_table.choices[1].message.content, nil
+end
+
+
+function _M.check_schema(conf)
+    -- openai-compatible should be used with override.endpoint
+    if conf.provider == "openai-compatible" then
+        local override = conf.override
+
+        if not override or not override.endpoint then
+            return false, "override.endpoint is required for openai-compatible 
provider"
+        end
+    end
+

Review Comment:
   can json-schema do this job?



##########
apisix/plugins/ai-request-rewrite.lua:
##########
@@ -0,0 +1,212 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one or more
+-- contributor license agreements.  See the NOTICE file distributed with
+-- this work for additional information regarding copyright ownership.
+-- The ASF licenses this file to You under the Apache License, Version 2.0
+-- (the "License"); you may not use this file except in compliance with
+-- the License.  You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+local core = require("apisix.core")
+local ngx = ngx
+
+local require = require
+
+local plugin_name = "ai-request-rewrite"
+
+local bad_request = ngx.HTTP_BAD_REQUEST
+local internal_server_error = ngx.HTTP_INTERNAL_SERVER_ERROR
+
+
+local auth_item_schema = {
+    type = "object",
+    patternProperties = {
+        ["^[a-zA-Z0-9._-]+$"] = {
+            type = "string"
+        }
+    }
+}
+
+local auth_schema = {
+    type = "object",
+    properties = {
+        header = auth_item_schema,
+        query = auth_item_schema
+    },
+    additionalProperties = false
+}
+
+local model_options_schema = {
+    description = "Key/value settings for the model",
+    type = "object",
+    properties = {
+        model = {
+            type = "string",
+            description = "Model to execute."
+        }
+    },
+    additionalProperties = true
+}
+
+local schema = {
+    type = "object",
+    properties = {
+        prompt = {
+            type = "string",
+            description = "The prompt to rewrite client request."
+        },
+        provider = {
+            type = "string",
+            description = "Name of the AI service provider.",
+            enum = {"openai", "openai-compatible", "deepseek"} -- add more 
providers later
+        },
+        auth = auth_schema,
+        options = model_options_schema,
+        timeout = {
+            type = "integer",
+            minimum = 1,
+            maximum = 60000,
+            default = 30000,
+            description = "timeout in milliseconds"
+        },
+        keepalive = {
+            type = "boolean",
+            default = true
+        },
+        keepalive_pool = {
+            type = "integer",
+            minimum = 1,
+            default = 30
+        },
+        ssl_verify = {
+            type = "boolean",
+            default = true
+        },
+        override = {
+            type = "object",
+            properties = {
+                endpoint = {
+                    type = "string",
+                    description = "To be specified to override " ..
+                    "the endpoint of the AI service provider."
+                }
+            }
+        }
+    },
+    required = {"prompt", "provider", "auth"}
+}
+
+local _M = {
+    version = 0.1,
+    priority = 1073,
+    name = plugin_name,
+    schema = schema
+}
+
+local function proxy_request_to_llm(conf, request_table, ctx)
+    local ai_driver = require("apisix.plugins.ai-drivers." .. conf.provider)
+
+    local extra_opts = {
+        endpoint = core.table.try_read_attr(conf, "override", "endpoint"),
+        query_params = conf.auth.query or {},
+        headers = (conf.auth.header or {}),
+        model_options = conf.options
+    }
+
+    local res, err, httpc = ai_driver:request(conf, request_table, extra_opts)
+
+    if not res then return nil, err, nil end
+    return res, nil, httpc
+end
+
+
+local function parse_llm_response(res_body)
+    local response_table = core.json.decode(res_body)
+
+    if not response_table then return nil, "failed to decode llm response" end
+
+    if not response_table.choices then
+        return nil, "'choices' not in llm response"
+    end
+
+    return response_table.choices[1].message.content, nil
+end
+
+
+function _M.check_schema(conf)
+    -- openai-compatible should be used with override.endpoint
+    if conf.provider == "openai-compatible" then
+        local override = conf.override
+
+        if not override or not override.endpoint then
+            return false, "override.endpoint is required for openai-compatible 
provider"
+        end
+    end
+
+    return core.schema.check(schema, conf)
+end
+
+
+function _M.access(conf, ctx)
+    local client_request_table, err = core.request.get_body()
+    if not client_request_table then
+        core.log.error("failed to get request body: ", err)
+        return bad_request, err
+    end
+
+    -- Prepare request for LLM service
+    local ai_request_table = {
+        messages = {
+            {
+                role = "system",
+                content = conf.prompt
+            },
+            {
+                role = "user",
+                content = client_request_table
+            }
+        },
+        stream = false
+    }
+
+    -- Send request to LLM service
+    local res, err, httpc = proxy_request_to_llm(conf, ai_request_table, ctx)
+    if not res then
+        core.log.error("failed to send request to LLM service: ", err)
+        return internal_server_error
+    end
+
+    -- Handle LLM response
+    if res.status >= 400 then
+        core.log.error("LLM service returned error status: ", res.status)
+        return internal_server_error

Review Comment:
   return 500 or return llm's response status?



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