In this example we register `AskLLM` as an asynchronous user defined function and invoke it via the DataFrame API and SQL
()
| 43 | /// In this example we register `AskLLM` as an asynchronous user defined function |
| 44 | /// and invoke it via the DataFrame API and SQL |
| 45 | pub async fn async_udf() -> Result<()> { |
| 46 | // Use a hard coded parallelism level of 4 so the explain plan |
| 47 | // is consistent across machines. |
| 48 | let config = SessionConfig::new().with_target_partitions(4); |
| 49 | let ctx = |
| 50 | SessionContext::from(SessionStateBuilder::new().with_config(config).build()); |
| 51 | |
| 52 | // Similarly to regular UDFs, you create an AsyncScalarUDF by implementing |
| 53 | // `AsyncScalarUDFImpl` and creating an instance of `AsyncScalarUDF`. |
| 54 | let async_equal = AskLLM::new(); |
| 55 | let udf = AsyncScalarUDF::new(Arc::new(async_equal)); |
| 56 | |
| 57 | // Async UDFs are registered with the SessionContext, using the same |
| 58 | // `register_udf` method as regular UDFs. |
| 59 | ctx.register_udf(udf.into_scalar_udf()); |
| 60 | |
| 61 | // Create a table named 'animal' with some sample data |
| 62 | ctx.register_batch("animal", animal()?)?; |
| 63 | |
| 64 | // You can use the async UDF as normal in SQL queries |
| 65 | // |
| 66 | // Note: Async UDFs can currently be used in the select list and filter conditions. |
| 67 | let results = ctx |
| 68 | .sql("select * from animal a where ask_llm(a.name, 'Is this animal furry?')") |
| 69 | .await? |
| 70 | .collect() |
| 71 | .await?; |
| 72 | |
| 73 | assert_batches_eq!( |
| 74 | [ |
| 75 | "+----+------+", |
| 76 | "| id | name |", |
| 77 | "+----+------+", |
| 78 | "| 1 | cat |", |
| 79 | "| 2 | dog |", |
| 80 | "+----+------+", |
| 81 | ], |
| 82 | &results |
| 83 | ); |
| 84 | |
| 85 | // While the interface is the same for both normal and async UDFs, you can |
| 86 | // use `EXPLAIN` output to see that the async UDF uses a special |
| 87 | // `AsyncFuncExec` node in the physical plan: |
| 88 | let results = ctx |
| 89 | .sql("explain select * from animal a where ask_llm(a.name, 'Is this animal furry?')") |
| 90 | .await? |
| 91 | .collect() |
| 92 | .await?; |
| 93 | |
| 94 | assert_batches_eq!( |
| 95 | [ |
| 96 | "+---------------+------------------------------------------------------------------------------------------------------------------------------+", |
| 97 | "| plan_type | plan |", |
| 98 | "+---------------+------------------------------------------------------------------------------------------------------------------------------+", |
| 99 | "| logical_plan | SubqueryAlias: a |", |
| 100 | "| | Filter: ask_llm(CAST(animal.name AS Utf8View), Utf8View(\"Is this animal furry?\")) |", |
| 101 | "| | TableScan: animal projection=[id, name] |", |
| 102 | "| physical_plan | FilterExec: __async_fn_0@2, projection=[id@0, name@1] |", |
no test coverage detected
searching dependent graphs…