Steps - wildberries-tech/universal-harvester GitHub Wiki
Шаги являются основным контентом Universal Harvester, который требует точного соотвествия информационному ландшафту, а значит и рефакторинга при его изменении. Шаги отвечаю за получение или обработку данных на функции выбранного источника (source) по заранее определённым или генерируемым параметрам. Результатом каждого шага является [] (list), который при наличии данных содержит "строки" данных (dict). Очевидно, что редактирование шага повлечёт за собой изменения во всех сценариях, где этот шаг используется.
Для написания шага нам потребуется:
- Корректный источник данных (с ключами при необходимости).
- Определить исполняемую функцию источника (определены в app/engine/engine.py ENGINE_SOURCES_AND_FUNCTIONS_MAP).
- Определить параметры, включая генерацию параметров или применение в качестве параметров других данных (apply).
- Определить блок query (основной блок данных запроса).
- Определить тестовые значения параметров для валидации написанного шага.
Step fields
{
"description": "", # описание шага
"example": "", # пример получения данных, например, сохранённый запрос в elastic
"llm": # блок, описывающий данные для LLM (если предполагается обработка данных с помощью LLM)
{
"preprompt": "",
"postprompt": ""
},
"source_function": "generic_query", # идентификатор функции источника
"input_parameters": # входные параметры, определённые шага
{
"...":"..."
},
"query": # данные, которыми оперирует функция-исполнитель шага, сюда возможно инъектирование параметров
{
"...": "..."
},
"apply": # опциональный блок применение уже полученных данных, сюда возможно инъектирование параметров
{
"...":{}
},
"generate_parameters": # опциональный блок генерации параметров
{
"...":{}
}
}
input_parameters
Входные параметры шага определяются в ноде input_parameters шага. Возможные типы данных параметров, обязательные поля и варианты автозаполнения определены в app/engine/steps.py TYPE_MAP. type -- тип данных параметра description -- описание параметра required -- флаг обязательности параметра (если false, то при его отсутствии он будет сгенерирован автоматически по полю default) default -- значение параметра по умолчанию (или функция автозаполнения) max_length -- только для string, максимальная длина строки format -- только для datetime, формат принимаемого параметра времени
Примеры входных параметров
"input_parameters":{
"string_parameter":
{
"type": "string",
"max_length": 100,
"required": false,
"default": "default_string",
"description": ""
},
"datetime_parameter":
{
"type": "datetime",
"format": "%Y-%m-%dT%H:%M:%S.%f%z",
"required": true,
"default": "now",
"description": ""
},
"integer_parameter":
{
"type": "integer",
"required": true,
"default": 0,
"description": ""
},
"ip_address_parameter":
{
"type": "ip_address",
"required": false,
"default": "127.0.0.1",
"description": ""
},
"float_parameter":
{
"type": "float",
"required": false,
"default": 0.0,
"description": ""
},
"boolean_parameter":
{
"type": "boolean",
"required": false,
"default": true,
"description": ""
},
"list_parameter":
{
"type": "list",
"required": false,
"default":
[
"list"
],
"description": ""
},
"dict_parameter":
{
"type": "dict",
"required": false,
"default":
{
"dict": "dict"
},
"description": ""
}
}
generate_parameters
Генерация параметров применяется для создания новых параметров из имеющихся. Определены 3 функции генерации: -timedelta, +timedelta, copy. Копирование параметра обычно применяется для назначении параметру нового имени. Имя ноды определяет имя сгенерированного параметра. type -- тип генерации нового параметра timestamp_field -- имя параметра времени для типов -timedelta и +timedelta, от которого будет определяться смещение delta_field -- имя параметра (integer) для смещения в секундах output_format -- формат времени сгенерированного параметра copy_source -- существующий параметр для копирования, тип данных наследуется
Примеры генерации параметров:
"generate_parameters":{
"gte":
{
"type": "-timedelta",
"timestamp_field": "timestamp",
"delta_field": "delta",
"output_format": "%Y-%m-%dT%H:%M:%S.%f%z"
},
"lte":
{
"type": "+timedelta",
"timestamp_field": "timestamp",
"delta_field": "delta",
"output_format": "%Y-%m-%dT%H:%M:%S.%f%z"
},
"copied":
{
"type": "copy",
"copy_source": "other_parameter"
}
}
apply
Применение данных в качестве параметров (apply) Universal Harvester имеет возможность применять данные, полученные в одних запрос, для подготовки других запросов. Для этого применятся нода шага apply. Имеется возможность использования результатов только одного уже выполненного шага. Применение apply определяет зависимость выполняемого шага от другого и влияет на очерёдность выполнения шагов в рамках сценария.
target_data -- уникальный идентификатор данных в рамках сценария или опредеяемый в специальном параметре outervision target_parameters -- список генерируемых параметров по столбцам данных target_data output_unique_fields -- (опционально) удаление дубликатов по указанным полям
Для каждого параметра необходимо указать: column_name -- имя колонки в применяемых данных as -- имя нового параметра в шаге
Опционально: format -- формат вывода, если это datetime pattern -- применение дополнительного паттерна инъектирования параметра
"apply":{
"target_data": "target_data_name",
"target_parameters":
[
{
"column_name": "column_in_target_data_1",
"as": "parameter_name_1"
},
{
"column_name": "column_in_target_data_2_datetime",
"as": "parameter_name_2",
"format": "%Y-%m-%dT%H:%M:%S.%f%z"
},
{
"column_name": "timestamp_stop",
"as": "timestamp_stop",
"pattern": "='%(__pattern_value__)s'"
}
],
"output_unique_fields":
[
"field_1",
"field_2"
]
}
Инъектирование параметров
Инъектирование параметров производится для блоков шага query и apply до выполнения шага. Таким образом происходит доставка параметров и конфигурирование запросов к системам. Это значит, что указав в тексте блок %(parameter)[sifbldx], параметр parameter будет инъектирован в шаг по правилам типа инъекции [sifbldx].
s -- вместо блока %(parameter)s подставляется str(value) ("data":"text %(parameter)s text" -> "data":"text value text" при value = "value")
i -- вместо блока %(parameter)i подставляется int(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)i" -> "data":0 при value = 0)
f -- вместо блока %(parameter)f подставляется float(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)f" -> "data":0.0 при value = 0.0)
b -- вместо блока %(parameter)b подставляется bool(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)b" -> "data":true при value = true)
l -- вместо блока %(parameter)l подставляется json.dumps(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)l" -> "data":[] при value = [])
d -- вместо блока %(parameter)d подставляется json.dumps(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)d" -> "data":{} при value = {})
x -- вместо блока %(parameter)x подставляется str(value), если инъекция обрамляется ", то они будут опущены ("data":"%(parameter)x" -> "data":value_ при value = "value_")
Обязательно убедитесь в том, что после инъектирования у вас получится корректный JSON.
Injection string | Type | Test value | Original string | Result | Comment |
---|---|---|---|---|---|
%(parameter)s | string | test | "data":"query data %(parameter)s" | "data":"query data test" | |
%(parameter)i | integer | 12 | "data":"query data %(parameter)i" | "data":"query data 12" | |
"data":"%(parameter)i" | "data":12 | ||||
%(parameter)f | float | 12.34 | "data":"query data %(parameter)f" | "data":"query data 12.340000000" | "{0:0.9f}".format(value) |
"data":"%(parameter)f" | "data":12.340000000 | ||||
%(parameter)b | boolean | true | "data":"query data %(parameter)b" | "data":"query data true" | |
"data":"%(parameter)b" | "data":true | ||||
%(parameter)l | list | ["test"] | "data":"query data %(parameter)l" | "data":"query data ["test"]" | |
"data":"%(parameter)l" | "data":["test"] | ||||
%(parameter)d | dict | {"foo":"bar"} | "data":"query data %(parameter)d" | "data":"query data {"foo":"bar"}" | |
"data":"%(parameter)d" | "data":{"foo":"bar"} | ||||
%(parameter)x | e__x__tended | "["test"]" | "data":"query data %(parameter)x" | "data":"query data ["test"]" | |
"data":"%(parameter)x" | "data":["test"] | Прямое инъектирование, JSON должен быть валидным |