diff --git a/plugins/wasm-go/extensions/ai-prompt-decorator/README.md b/plugins/wasm-go/extensions/ai-prompt-decorator/README.md index 78f545cf9..4feb71252 100644 --- a/plugins/wasm-go/extensions/ai-prompt-decorator/README.md +++ b/plugins/wasm-go/extensions/ai-prompt-decorator/README.md @@ -66,4 +66,70 @@ curl http://localhost/test \ } ] } -``` \ No newline at end of file +``` + + +# 基于geo-ip插件的能力,扩展AI提示词装饰器插件携带用户地理位置信息 +如果需要在LLM的请求前后加入用户地理位置信息,请确保同时开启geo-ip插件和AI提示词装饰器插件。并且在相同的请求处理阶段里,geo-ip插件的优先级必须高于AI提示词装饰器插件。首先geo-ip插件会根据用户ip计算出用户的地理位置信息,然后通过请求属性传递给后续插件。比如在默认阶段里,geo-ip插件的priority配置1000,ai-prompt-decorator插件的priority配置500。 + +geo-ip插件配置示例: +```yaml +ipProtocal: "ipv4" +``` + + + + +AI提示词装饰器插件的配置示例如下: +```yaml +prepend: +- role: system + content: "提问用户当前的地理位置信息是,国家:${geo-country},省份:${geo-province}, 城市:${geo-city}" +append: +- role: user + content: "每次回答完问题,尝试进行反问" +``` + +使用以上配置发起请求: + +```bash +curl http://localhost/test \ +-H "content-type: application/json" \ +-H "x-forwarded-for: 87.254.207.100,4.5.6.7" \ +-d '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "今天天气怎么样?" + } + ] +}' +``` + +经过插件处理后,实际请求为: + +```bash +curl http://localhost/test \ +-H "content-type: application/json" \ +-H "x-forwarded-for: 87.254.207.100,4.5.6.7" \ +-d '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "system", + "content": "提问用户当前的地理位置信息是,国家:中国,省份:北京, 城市:北京" + }, + { + "role": "user", + "content": "今天天气怎么样?" + }, + { + "role": "user", + "content": "每次回答完问题,尝试进行反问" + } + ] +}' +``` + + diff --git a/plugins/wasm-go/extensions/ai-prompt-decorator/main.go b/plugins/wasm-go/extensions/ai-prompt-decorator/main.go index 9c7a0e9ea..9baf8c856 100644 --- a/plugins/wasm-go/extensions/ai-prompt-decorator/main.go +++ b/plugins/wasm-go/extensions/ai-prompt-decorator/main.go @@ -2,6 +2,8 @@ package main import ( "encoding/json" + "fmt" + "strings" "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper" "github.com/higress-group/proxy-wasm-go-sdk/proxywasm" @@ -38,10 +40,42 @@ func onHttpRequestHeaders(ctx wrapper.HttpContext, config AIPromptDecoratorConfi return types.ActionContinue } +func replaceVariable(variable string, entry *Message) (*Message, error) { + key := fmt.Sprintf("${%s}", variable) + if strings.Contains(entry.Content, key) { + value, err := proxywasm.GetProperty([]string{variable}) + if err != nil { + return nil, err + } + entry.Content = strings.ReplaceAll(entry.Content, key, string(value)) + } + return entry, nil +} + +func decorateGeographicPrompt(entry *Message) (*Message, error) { + geoArr := []string{"geo-country", "geo-province", "geo-city", "geo-isp"} + + var err error + for _, geo := range geoArr { + entry, err = replaceVariable(geo, entry) + if err != nil { + return nil, err + } + } + + return entry, nil +} + func onHttpRequestBody(ctx wrapper.HttpContext, config AIPromptDecoratorConfig, body []byte, log wrapper.Log) types.Action { messageJson := `{"messages":[]}` for _, entry := range config.Prepend { + entry, err := decorateGeographicPrompt(&entry) + if err != nil { + log.Errorf("Failed to decorate geographic prompt in prepend, error: %v", err) + return types.ActionContinue + } + msg, err := json.Marshal(entry) if err != nil { log.Errorf("Failed to add prepend message, error: %v", err) @@ -60,6 +94,12 @@ func onHttpRequestBody(ctx wrapper.HttpContext, config AIPromptDecoratorConfig, } for _, entry := range config.Append { + entry, err := decorateGeographicPrompt(&entry) + if err != nil { + log.Errorf("Failed to decorate geographic prompt in append, error: %v", err) + return types.ActionContinue + } + msg, err := json.Marshal(entry) if err != nil { log.Errorf("Failed to add prepend message, error: %v", err)