gisk

package module
v0.0.0-...-fe6ac7f Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 28, 2024 License: Apache-2.0 Imports: 11 Imported by: 0

README

gisk风控策略引擎

gisk是独立的即插即用的轻量级决策引擎,支持json和yaml格式DSL。支持自定义运算符,自定义函数,自定义动作开放灵活的扩展适用更多的业务场景。

功能列表

  • 基础值
    • 变量
    • 输入值
    • 函数
  • 决策(规则)
  • 决策集
  • 决策流
  • 分流决策流
  • 赋值决策流
  • 评分卡
  • 支持数据类型:number, string, bool, array, map
  • 支持运算符号(支持自定义,覆盖默认运算符):eq, neq, gt, lt, gte, lte, in, notIn, like, notLike
  • 支持函数(支持自定义,函数支持嵌套):内置函数rand、sum
  • 支持决策动作(支持自定义):内置动作 赋值,访问url
  • 支持串行并行执行
  • DSL支持历史版本控制(提供获取接口,实现不同介质DSL储存。内置文件存储)
  • DSL支持json和yaml格式

快速开始

  • 环境准备

    go version go1.2+

  • 安装

go get -u -v gitee.com/sreeb/gisk
  • 基础使用
package main

import (
  "fmt"
  "gitee.com/sreeb/gisk"
)

func main() {
  elementType := gisk.RULES //规则
  rulesKey := "rules1" //规则唯一key
  version := "1" //规则版本

  g := gisk.New() //创建gisk实例
  g.SetDslFormat(gisk.JSON) //设置dsl格式
  err := g.Parse(elementType, rulesKey, version) //解析规则
  if err != nil {
    //错误处理
  }
  //获取所有被初始化的变量值
  variates := g.GetVariates()
  fmt.Println(variates)
}

  • 注册dsl获取接口

dsl接口获取器,可以根据提供的类型和key和版本获取dsl字符串。 dsl接口获取器需要实现gisk.DslGetterInterface接口,返回dsl字符串。

type DslGetterInterface interface {
	GetDsl(elementType ElementType, key string, version string) (string, error)
}

示例:

type fileDslGetter struct {
}

func (getter *fileDslGetter) GetDsl(elementType gisk.ElementType, key string, version string) (string, error) {
	path := "./dsl/" + elementType + "_" + key + "_" + version + ".json"
	bytes, err := os.ReadFile(path)
	if err != nil {
		return "", err
	}
	return  string(bytes), nil
}

func main() {
    //创建gisk实例
    g := gisk.New()
    //设置dsl获取器
    g.SetDslGetter(&fileDslGetter{})
    //...
}
  • 注册比较符

系统实现默认的比较符 eq, neq, gt, lt, gte, lte,in,notIn,like,notLike如果需要自定义比较符,可以调用RegisterOperation方法。自定义比较符优先级高于系统内置的比较符,可以注册和系统同名比较符实现复写。

package main

import (
	"errors"
	"gitee.com/sreeb/gisk"
	"regexp"
)

func main() {
	//自定义正则匹配比较符
	gisk.RegisterOperation("reg", func(left gisk.Value, operator gisk.Operator, right gisk.Value) (result bool, err error) {
		if left.ValueType != gisk.STRING || right.ValueType != gisk.STRING {
			err = errors.New("left and right must be string")
			return
		}
		// 正则表达式匹配
		reg := regexp.MustCompile(right.Value.(string))
		if reg.MatchString(left.Value.(string)) {
			result = true
		}
		return
	})

	g := gisk.New()
	//...
}
  • 注册函数

系统实现默认的函数 randsum,如果需要自定义函数,可以调用RegisterFunction方法。自定义函数优先级高于系统内置的函数,可以注册和系统同名函数实现复写。*

package main

import (
  "gitee.com/sreeb/gisk"
  "github.com/gogf/gf/v2/util/gconv"
)

func main() {
    //注册求和函数
    gisk.RegisterFunc("sum", func(parameters ...gisk.Value) (gisk.Value, error) {
      var v float64
      for _, parameter := range parameters {
        v += gconv.Float64(parameter.Value)
      }
      return gisk.Value{ValueType: gisk.NUMBER, Value: v}, nil
    })
	
    g := gisk.New()
    //...
}

DSL语法

基础值

基础值包含变量,输入值,函数。在dsl中用字符串表示。基础值

变量

表示法:variate_age_1

解释:variate表示为变量类型,age表示变量唯一key(key可以有下划线),1表示变量版本号。

变量DSL:

{
    "key": "age",
    "name": "年龄",
    "desc": "用户年龄",
    "version": "1",
    "value_type": "number",
    "default": 20,
    "is_input": false
}

变量结构体:

type Variate struct {
	Key       string      `json:"key" yaml:"key"`               //唯一标识
	Name      string      `json:"name" yaml:"name"`             //变量名称(前端页面使用,不涉及逻辑)
	Desc      string      `json:"desc" yaml:"desc"`             //描述(前端页面使用,不涉及逻辑)
	Version   string      `json:"version" yaml:"version"`       //版本
	ValueType ValueType   `json:"value_type" yaml:"value_type"` //值类型(number:转成float64, string, bool, array:以,分割转成array, map:json字符串转成map)
	Default   interface{} `json:"default" yaml:"default"`       //默认值
	IsInput   bool        `json:"is_input" yaml:"is_input"`     //是否要从输入值中匹配(true时会从输入值中匹配相同key的值进行赋值)
}
输入值

表示法:input_1_number

解释:input表示为输入值类型,1表示输入值,number表示输入值数据类型。

输入值没有DSL

函数

表示法:func_rand(input_1_number,func_sum(input_10_number,input_20_string))

解释:函数支持嵌套,函数参数只能是基础值。上述表达式解释为:rand(1,sum(10,20)),rand函数两个参数1和sum函数,sum函数两个参数10和20。 注册函数需要实现 type Func func(parameters ...Value) (Value, error)类型。

函数无DSL

规则(决策)

规则是基于多个比较条件通过逻辑运算符进行组合,最终得到一个布尔值。可以根据最终布尔值进行后续动作执行,赋值,访问url,发送消息,连接数据库等等操作。规则支持括号运算,支持串行并行执行

规则dsl

{
  "key": "rule1",   //唯一key
  "name": "用户筛选", //规则名称
  "desc": "用户筛选", //规则描述
  "version": "1",  //规则版本
  "parallel": true, //是否并行执行(并行执行会先并发获取比较条件组所有结果,再用规则表达式进行逻辑运算)
  "compares": {     
    "年龄小于40": {
      "left": "variate_年龄_1", //比较条件左边
      "operator": "lt", //比较条件运算符
      "right": "input_40_number" //比较条件右边
    },
    "性别女": {
      "left": "variate_性别_1",
      "operator": "eq",
      "right": "input_女_string"
    },
    "身高大于等于170": {
      "left": "variate_身高_1",
      "operator": "gte",
      "right": "input_170_number"
    }
  },  //比较条件组
  "expression": "年龄小于40 && (性别女 || 身高大于等于170)", //规则表达式
  "action_true": [
    {
      "action_type": "assignment",  //赋值操作
      "variate": "variate_命中结果_1", //赋值变量
      "value": "input_true_bool" //赋值值
    },
    {
      "action_type": "geturl", //访问url
      "url": "https://xxx.com" //url
    }
  ],  //true执行动作
  "action_false": [
    {
      "action_type": "assignment", //赋值操作
      "variate": "variate_命中结果_1", //赋值变量
      "value": "input_false_bool" //赋值值
    }
  ] //false执行动作
}

上述规则解释为:如果年龄小于40且性别为女或者身高大于等于170,则命中,否则未命中。命中时执行动作:变量命中结果赋值为true时,访问url。未命中时,赋值变量命中结果为false。

规则结构体:

type Rule struct {
	Key         string              `json:"key" yaml:"key"`                //唯一标识
	Name        string              `json:"name" yaml:"name"`              //名称
	Desc        string              `json:"desc" yaml:"desc"`              //描述
	Version     string              `json:"version" yaml:"version"`        //版本
	Parallel    bool                `json:"parallel" yaml:"parallel"`      //是否并发执行
	Compares    map[string]*Compare `json:"compares" yaml:"compares"`      //比较
	Expression  string              `json:"expression"  yaml:"expression"` //计算公式
	ActionTure  []RawMessage        `json:"action_true" yaml:"action_true"` //命中执行动作
	ActionFalse []RawMessage        `json:"action_false" yaml:"action_false"` //未命中执行动作
}
type Compare struct {
  Left     string   `json:"left" yaml:"left"`
  Operator Operator `json:"operator" yaml:"operator"` // 比较符号(可自定义注册)
  Right    string   `json:"right" yaml:"right"`
}

规则集(决策集)

规则集是多个规则的集合,支持串行并行执行和中断。并行模式下规则的先后顺序和中断不生效

规则集dsl:

{
  "key": "ruleset", //唯一key
  "name": "决策集1", //规则集名称
  "desc": "决策集1", //规则集描述
  "version": "1", //规则集版本
  "parallel": false, //是否并行执行(串行执行:顺序执行规则,中断后不执行后续规则。 并行执行:并发执行规则,不考虑顺序和中断)
  "rules": [ 
    {
      "rule_key": "rule1", //规则key
      "rule_version": "1", //规则版本
      "break_mode": "hit_break" //中断模式:hit_break命中中断,miss_break未命中中断。中断表示不执行后续的规则
    },
    {
      "rule_key": "rule2",
      "rule_version": "1",
      "break_mode": "miss_break"
    },
    {
      "rule_key": "rule3",
      "rule_version": "1",
      "break_mode": "miss_break"
    }
  ]//规则集规则
}

规则集结构体:

type Ruleset struct {
	Key      string         `json:"key" yaml:"key"`           //唯一标识
	Name     string         `json:"name" yaml:"name"`         //名称
	Desc     string         `json:"desc" yaml:"desc"`         //描述
	Version  string         `yaml:"version" json:"version"`   //版本
	Parallel bool           `json:"parallel" yaml:"parallel"` //是否并发执行
	Rules    []*rulesetRule `json:"rules" yaml:"rules"`       //规则集规则
}

type rulesetRule struct {
	RuleKey     string    `json:"rule_key" yaml:"rule_key"` //规则key
	RuleVersion string    `json:"rule_version" yaml:"rule_version"` //规则版本
	BreakMode   BreakMode `json:"break_mode" yaml:"break_mode"` //中断模式
}

决策流

决策流支持普通节点,分流节点和动作节点

普通节点

普通节点可以执行一个元素,元素可为规则,规则集等

type generalFlowNode struct {
	NodeKey    string       `json:"node_key" yaml:"node_key"`               //节点key
	NodeType   FlowNodeType `json:"node_type" yaml:"node_type"`             //节点类型
	EleType    ElementType  `json:"element_type" yaml:"element_type"`       //元素类型
	EleKey     string       `json:"element_key" yaml:"element_key"`         //元素key
	EleVersion string       `json:"element_version" yaml:"element_version"` //元素版本
	NextNode   string       `json:"next_node" yaml:"next_node"`             //下一个节点
}

分流节点

分流节点通过比较条件进行分流

type branchFlowNode struct {
	NodeKey  string       `json:"node_key" yaml:"node_key"`   //节点key
	NodeType FlowNodeType `json:"node_type" yaml:"node_type"` //节点类型
	Left     string       `json:"left" yaml:"left"`           //左侧
	Branches []struct {
		Operator Operator `json:"operator" yaml:"operator"`   // 比较符号
		Right    string   `json:"right" yaml:"right"`         // 右侧
		NextNode string   `json:"next_node" yaml:"next_node"` // 下一个节点
	} `json:"branches" yaml:"branches"` // 分支
}

动作节点

动作节点执行动作,公用规则动作,可以自定义

type actionFlowNode struct {
	NodeKey  string       `json:"node_key" yaml:"node_key"`   //节点key
	NodeType FlowNodeType `json:"node_type" yaml:"node_type"` //节点类型
	Actions  []RawMessage `json:"actions" yaml:"actions"`     //动作
	NextNode string       `json:"next_node" yaml:"next_node"` //下一个节点
}

复杂的决策流:

{
    "key": "flow1",
    "name": "普通决策流",
    "desc": "普通决策流",
    "version": "1",
    "nodes": [
        {
            "node_key": "start",
            "node_type": "general_flow_node",
            "element_type": "ruleset",
            "element_key": "ruleset",
            "element_version": "1",
            "next_node": "branch_node"
        },
        {
            "node_key": "branch_node",
            "node_type": "branch_flow_node",
            "left": "func_rand(input_1_number,input_100_number)",
            "branches": [
                {
                    "operator": "lte",
                    "right": "input_20_number",
                    "next_node": ""
                },
                {
                    "operator": "gt",
                    "right": "input_20_number",
                    "next_node": ""
                }
            ]
        },
        {
            "node_key": "branch_node",
            "node_type": "branch_flow_node",
            "left": "func_rand(input_1_number,input_100_number)",
            "branches": [
                {
                    "operator": "lte",
                    "right": "input_20_number",
                    "next_node": "action_flow_node1"
                },
                {
                    "operator": "gt",
                    "right": "input_20_number",
                    "next_node": "action_flow_node2"
                }
            ]
        },
        {
            "node_key": "action_flow_node1",
            "node_type": "action_flow_node",
            "next_node": "",
            "actions": [
                {
                    "action_type": "assignment",
                    "variate": "variate_决策流分流_1",
                    "value": "input_20%_string"
                }
            ]
        },
        {
            "node_key": "action_flow_node2",
            "node_type": "action_flow_node",
            "next_node": "",
            "actions": [
                {
                    "action_type": "assignment",
                    "variate": "variate_决策流分流_1",
                    "value": "input_80%_string"
                }
            ]
        }
    ]
}

解释为: 决策流图

Documentation

Index

Constants

View Source
const (
	HitBreak  = "hit_break"  //规则命中中断后续规则
	MissBreak = "miss_break" //规则未命中中断后续规则
)
View Source
const (
	JSON = "json"
	YAML = "yaml"
)
View Source
const FlowStartNodeKey = "start"

Variables

This section is empty.

Functions

func ConvertValueType

func ConvertValueType(value interface{}, valueType ValueType) (Value interface{}, err error)

ConvertValueType 转换值数据类型

func InfixToRPN

func InfixToRPN(parts []string) ([]string, error)

InfixToRPN 将算公式转换为逆波兰表达式

func Operation

func Operation(left Value, operator Operator, right Value) (result bool, err error)

Operation 运算

func RegisterAction

func RegisterAction(name string, actionStruct ActionInterface)

func RegisterFunc

func RegisterFunc(name string, function Func)

func RegisterOperation

func RegisterOperation(name Operator, op OperationFunc)

Types

type ActionInterface

type ActionInterface interface {
	Parse(gisk *Gisk) error
}

type ActionType

type ActionType struct {
	ActionType string `json:"action_type" yaml:"action_type"`
}

type Assignment

type Assignment struct {
	ActionType ActionType
	Variate    string `json:"variate" yaml:"variate"`
	Value      string `json:"value" yaml:"value"`
}

func (*Assignment) Parse

func (a *Assignment) Parse(gisk *Gisk) error

type BreakMode

type BreakMode string

BreakMode 规则集规则中断模式

type Compare

type Compare struct {
	Left     string   `json:"left" yaml:"left"`
	Operator Operator `json:"operator" yaml:"operator"` // 比较符号
	Right    string   `json:"right" yaml:"right"`
}

func (*Compare) Parse

func (c *Compare) Parse(gisk *Gisk) (bool bool, err error)

type Context

type Context struct {
	// contains filtered or unexported fields
}

func (*Context) GetVariate

func (ctx *Context) GetVariate(key string) (Value Value, ok bool)

func (*Context) GetVariates

func (ctx *Context) GetVariates() map[string]Value

func (*Context) SetVariate

func (ctx *Context) SetVariate(key string, Value Value)

type DslGetter

type DslGetter struct {
	Getter DslGetterInterface
	Dsl    sync.Map
}

func (*DslGetter) GetDsl

func (getter *DslGetter) GetDsl(elementType ElementType, key string, version string) (string, error)

type DslGetterInterface

type DslGetterInterface interface {
	GetDsl(elementType ElementType, key string, version string) (string, error)
}

type ElementType

type ElementType string

ElementType 元素类型

const (
	VARIATE ElementType = "variate" //变量
	INPUT   ElementType = "input"   //输入值
	FUNC    ElementType = "func"    //函数
	RULE    ElementType = "rule"    //规则
	RULESET ElementType = "ruleset" //规则集
	FLOW    ElementType = "flow"    //决策流
)

type Flow

type Flow struct {
	Key     string       `json:"key" yaml:"key"`         //唯一标识
	Name    string       `json:"name" yaml:"name"`       //名称
	Desc    string       `json:"desc" yaml:"desc"`       //描述
	Version string       `yaml:"version" json:"version"` //版本
	Nodes   []RawMessage `json:"nodes" yaml:"nodes"`     //节点
	// contains filtered or unexported fields
}

func GetFlow

func GetFlow(gisk *Gisk, key string, version string) (*Flow, error)

func (*Flow) GetNode

func (f *Flow) GetNode(gisk *Gisk, key string) (NodeInterface, error)

func (*Flow) Parse

func (f *Flow) Parse(gisk *Gisk) error

type FlowNodeType

type FlowNodeType string

FlowNodeType 流程节点类型

const (
	GeneralFlowNode FlowNodeType = "general_flow_node"
	BranchFlowNode  FlowNodeType = "branch_flow_node"
	ActionFlowNode  FlowNodeType = "action_flow_node"
)

type Func

type Func func(parameters ...Value) (Value, error)

type Gisk

type Gisk struct {
	DslFormat string                 //dsl解析格式:json 或 yaml
	Input     map[string]interface{} //输入值
	Context   *Context               //上下文
	DslGetter *DslGetter             //dsl获取器
}

func New

func New() *Gisk

func (*Gisk) GetVariates

func (gisk *Gisk) GetVariates() map[string]interface{}

GetVariates 获取所有赋值变量

func (*Gisk) Parse

func (gisk *Gisk) Parse(elementType ElementType, key string, version string) error

func (*Gisk) SetDslFormat

func (gisk *Gisk) SetDslFormat(format string) *Gisk

SetDslFormat 设置dsl格式

func (*Gisk) SetDslGetter

func (gisk *Gisk) SetDslGetter(getter DslGetterInterface) *Gisk

SetDslGetter 设置dsl获取器

func (*Gisk) Unmarshal

func (gisk *Gisk) Unmarshal(data []byte, v any) error

type Input

type Input struct {
	ValueType ValueType
	Value     interface{}
}

func (*Input) Parse

func (input *Input) Parse(gisk *Gisk) (Value Value, err error)

type NodeInterface

type NodeInterface interface {
	Parse(gisk *Gisk, flow *Flow) ([]NodeInterface, error)
}

type OperationFunc

type OperationFunc func(left Value, operator Operator, right Value) (result bool, err error)

type Operator

type Operator string

Operator 运算符

const (
	EQ      Operator = "eq"
	NEQ     Operator = "neq"
	GT      Operator = "gt"
	LT      Operator = "lt"
	GTE     Operator = "gte"
	LTE     Operator = "lte"
	IN      Operator = "in"
	NOTIN   Operator = "notIn"
	LIKE    Operator = "like"
	NOTLIKE Operator = "notLike"
)

type RawMessage

type RawMessage []byte

func (RawMessage) MarshalJSON

func (m RawMessage) MarshalJSON() ([]byte, error)

func (RawMessage) MarshalYAML

func (m RawMessage) MarshalYAML() ([]byte, error)

func (*RawMessage) UnmarshalJSON

func (m *RawMessage) UnmarshalJSON(data []byte) error

UnmarshalJSON sets *m to a copy of data.

func (*RawMessage) UnmarshalYAML

func (m *RawMessage) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML implements the yaml.Unmarshaler interface for YAMLRawMessage.

type Rule

type Rule struct {
	Key         string              `json:"key" yaml:"key"`                //唯一标识
	Name        string              `json:"name" yaml:"name"`              //名称
	Desc        string              `json:"desc" yaml:"desc"`              //描述
	Version     string              `json:"version" yaml:"version"`        //版本
	Parallel    bool                `json:"parallel" yaml:"parallel"`      //是否并发执行
	Compares    map[string]*Compare `json:"compares" yaml:"compares"`      //比较
	Expression  string              `json:"expression"  yaml:"expression"` //计算公式
	ActionTure  []RawMessage        `json:"action_true" yaml:"action_true"`
	ActionFalse []RawMessage        `json:"action_false" yaml:"action_false"`
}

func GetRule

func GetRule(gisk *Gisk, key string, version string) (*Rule, error)

func (*Rule) Parse

func (r *Rule) Parse(gisk *Gisk) (bool, error)

type Ruleset

type Ruleset struct {
	Key      string         `json:"key" yaml:"key"`           //唯一标识
	Name     string         `json:"name" yaml:"name"`         //名称
	Desc     string         `json:"desc" yaml:"desc"`         //描述
	Version  string         `yaml:"version" json:"version"`   //版本
	Parallel bool           `json:"parallel" yaml:"parallel"` //是否并发执行
	Rules    []*rulesetRule `json:"rules" yaml:"rules"`
}

func GetRuleset

func GetRuleset(gisk *Gisk, key string, version string) (*Ruleset, error)

func (*Ruleset) Parse

func (r *Ruleset) Parse(gisk *Gisk) error

type Value

type Value struct {
	ValueType ValueType
	Value     interface{}
}

func GetValueByTrait

func GetValueByTrait(gisk *Gisk, key string) (Value, error)

GetValueByTrait 获取特征数据

type ValueInterface

type ValueInterface interface {
	Parse(gisk *Gisk) (Value, error)
}

type ValueType

type ValueType string

ValueType 值类型

const (
	NUMBER ValueType = "number"
	STRING ValueType = "string"
	ARRAY  ValueType = "array"
	MAP    ValueType = "map"
	BOOL   ValueType = "bool"
)

type Variate

type Variate struct {
	Key       string      `json:"key" yaml:"key"`               //唯一标识
	Name      string      `json:"name" yaml:"name"`             //变量名称
	Desc      string      `json:"desc" yaml:"desc"`             //描述
	Version   string      `json:"version" yaml:"version"`       //版本
	ValueType ValueType   `json:"value_type" yaml:"value_type"` //值类型
	Default   interface{} `json:"default" yaml:"default"`       //默认值
	IsInput   bool        `json:"is_input" yaml:"is_input"`     //是否要从输入值中匹配
}

func (*Variate) Parse

func (variate *Variate) Parse(gisk *Gisk) (Value Value, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL