
# 技术原理
特性在SQL引擎中添加新的系统函数llm_query/llm_embed/llm_rerank，当用户在SQL中使用上述函数时，GaussDB内核进行的处理如下图所示：
图1特性执行流程   
![](https://support.huaweicloud.com/centralized-devg-v10-gaussdb/figure/zh-cn_image_0000002590364648.png "点击放大")
GaussDB的SQL引擎执行的步骤如下：
1. GaussDB的parser识别出SQL中调用的函数和对应的参数，生成对应的查询计划和其中的表达式。
2. GaussDB SQL优化器根据查询优化规则对查询计划进行优化。
3. GaussDB SQL执行器在算子中调用llm_query、llm_embed、llm_rerank函数，在算子中的每行数据上执行。
4. 对于每行数据，执行器从系统表中获取到该函数所调用的模型服务相关信息，根据系统表中记录的请求参数和函数中定义的prompt，生成模型服务调用的JSON请求。
5. JSON请求通过https请求传递到外部的模型服务的端口上。
6. 模型服务返回的结果在算子中生成对应的返回结果，在执行器中传递生成最终的查询结果。
功能在执行器执行线程里执行模型调用的请求，为避免模型服务的高延时造成对执行的阻塞，其通过如下两个优化方式提升系统的吞吐率并控制资源：
1. 设置超时时间：针对单次模型服务的调用设置超时时间。超过设定的时间则终止该查询的执行。模型超时时间通过GUC参数endpoint_timeout_limit进行设置。
2. 控制连接池的并发数：在单个查询中，针对多条数据，使用连接池控制整体连接的并发度。连接池使用libcurl中的多句柄机制实现。在libcurl中可以通过创建多个句柄，实现在单个线程之内并发处理多个异步请求，句柄的数量由guc参数llm_max_connections控制。
另外当查询计划存在同一个语义函数（仅支持llm_embed和llm_rerank）在表上多次调用时，会改写标准project算子生成批量调用请求。
例如当用户输入下列SQL命令：
```
select llm_embed('bge-embedding', 'Summarize the review below'||T.content) from T
```
默认的查询计划会对该表上每一行数据生成一次模型调用请求，示意查询计划如下所示：
```
Result [
llm_embed(concat('Summarize the review below: ', T.content))
]
└── SeqScan on T
```
当模型服务支持批量推理接口时，针对标准的Result\[\]算子，BATCH优化规则在查询计划里做如下改动：
1. 添加Row To Vector 算子，将多行数据聚集成一个Chunk。
2. 添加Vector执行算子，将一个Chunk中所有的行合并成对应的批调用请求，进行模型调用。
3. 添加Vector To Row算子，在模型服务返回结果之后，将批请求的结果展开成对应的行数据。
例如上述的查询在执行查询优化之后，示意的查询计划如下所示：
```
Result
└── Vector to Row
└── Vector Result [
newspaper = llm_embed(concat('Summarize the review below: ', T.content))
]
└── Row To Vector on T
└── SeqScan on T
```
