Skip to content

Commit b3d3465

Browse files
committed
[owl] Add tests for column output execute normally when input value is null (#813)
* Test column output for input value is null
1 parent a5099fb commit b3d3465

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

services/api/tests/gen_table/test_row_ops_v2.py

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,3 +2149,163 @@ def test_multiturn_regen(
21492149
chat = row.columns["AI"].content.strip()
21502150
assert chat != "How are you?", f"{row.columns=}"
21512151
assert "10" in chat, f"{row.columns=}"
2152+
2153+
2154+
@pytest.mark.parametrize("table_type", TABLE_TYPES)
2155+
@pytest.mark.parametrize("stream", **STREAM_PARAMS)
2156+
def test_null_input_llm_output(
2157+
setup: ServingContext,
2158+
table_type: TableType,
2159+
stream: bool,
2160+
):
2161+
"""
2162+
Test that LLM output columns handle null input values correctly.
2163+
When an input column is None:
2164+
- For non-file columns (str, int, float): interpolated as "None" string
2165+
- For file columns (document, image, audio): interpolated as empty string ""
2166+
The LLM execution should complete normally without errors in both cases.
2167+
"""
2168+
client = JamAI(user_id=setup.superuser_id, project_id=setup.project_id)
2169+
cols = [
2170+
ColumnSchemaCreate(id="input_text", dtype="str"),
2171+
ColumnSchemaCreate(id="input_int", dtype="int"),
2172+
ColumnSchemaCreate(id="input_float", dtype="float"),
2173+
ColumnSchemaCreate(id="input_document", dtype="document"),
2174+
ColumnSchemaCreate(id="input_image", dtype="image"),
2175+
ColumnSchemaCreate(id="input_audio", dtype="audio"),
2176+
ColumnSchemaCreate(
2177+
id="llm_output",
2178+
dtype="str",
2179+
gen_config=LLMGenConfig(
2180+
model=setup.lorem_llm_model_id,
2181+
system_prompt="You are a helpful assistant.",
2182+
prompt=(
2183+
"Input text: ${input_text}, Input int: ${input_int}, Input float: ${input_float}. "
2184+
"Document: ${input_document}, Image: ${input_image}, Audio: ${input_audio}. "
2185+
"Respond with 'OK'."
2186+
),
2187+
max_tokens=10,
2188+
),
2189+
),
2190+
]
2191+
with create_table(client, table_type, cols=cols) as table:
2192+
# Test with various combinations of null and non-null inputs
2193+
data = [
2194+
# All null inputs
2195+
{
2196+
"input_text": None,
2197+
"input_int": None,
2198+
"input_float": None,
2199+
"input_document": None,
2200+
"input_image": None,
2201+
"input_audio": None,
2202+
},
2203+
# All non-null inputs
2204+
{
2205+
"input_text": "test",
2206+
"input_int": 42,
2207+
"input_float": 3.14,
2208+
"input_document": setup.document_uri,
2209+
"input_image": setup.image_uri,
2210+
"input_audio": setup.audio_uri,
2211+
},
2212+
# Mixed: null primitives, non-null files
2213+
{
2214+
"input_text": None,
2215+
"input_int": None,
2216+
"input_float": None,
2217+
"input_document": setup.document_uri,
2218+
"input_image": setup.image_uri,
2219+
"input_audio": setup.audio_uri,
2220+
},
2221+
# Mixed: non-null primitives, null files
2222+
{
2223+
"input_text": "test",
2224+
"input_int": 10,
2225+
"input_float": 2.5,
2226+
"input_document": None,
2227+
"input_image": None,
2228+
"input_audio": None,
2229+
},
2230+
]
2231+
response = add_table_rows(
2232+
client, table_type, table.id, data, stream=stream, check_usage=False
2233+
)
2234+
assert len(response.rows) == len(data)
2235+
2236+
# Verify all rows completed without errors
2237+
rows = list_table_rows(client, table_type, table.id)
2238+
assert rows.total == len(data)
2239+
2240+
for i, row in enumerate(rows.values):
2241+
llm_output = row["llm_output"]
2242+
assert llm_output is not None, f"Row {i}: LLM output should not be None"
2243+
assert not llm_output.startswith("[ERROR]"), (
2244+
f"Row {i}: LLM output should not contain error: {llm_output}"
2245+
)
2246+
assert len(llm_output) > 0, f"Row {i}: LLM output should not be empty"
2247+
2248+
2249+
@pytest.mark.parametrize("stream", **STREAM_PARAMS)
2250+
async def test_null_input_python_fixed_function(
2251+
setup: ServingContext,
2252+
stream: bool,
2253+
):
2254+
"""
2255+
Test that Python fixed function output columns handle null input values correctly.
2256+
The Python code should be able to handle None values in the row data gracefully.
2257+
"""
2258+
table_type = TableType.ACTION
2259+
client = JamAI(user_id=setup.superuser_id, project_id=setup.project_id)
2260+
2261+
# Python code that handles null values
2262+
python_code = """
2263+
if row.get('input_str') is None:
2264+
row['output'] = 'Input was None'
2265+
else:
2266+
row['output'] = f"Input was: {row['input_str']}"
2267+
"""
2268+
2269+
cols = [
2270+
ColumnSchemaCreate(id="input_str", dtype="str"),
2271+
ColumnSchemaCreate(id="input_int", dtype="int"),
2272+
ColumnSchemaCreate(
2273+
id="output",
2274+
dtype="str",
2275+
gen_config=PythonGenConfig(python_code=python_code),
2276+
),
2277+
]
2278+
with create_table(client, table_type, cols=cols) as table:
2279+
data = [
2280+
{"input_str": None, "input_int": None},
2281+
{"input_str": "test value", "input_int": 42},
2282+
{"input_str": None, "input_int": 10},
2283+
{"input_str": "", "input_int": None},
2284+
]
2285+
response = add_table_rows(
2286+
client, table_type, table.id, data, stream=stream, check_usage=False
2287+
)
2288+
assert len(response.rows) == len(data)
2289+
2290+
rows = list_table_rows(client, table_type, table.id)
2291+
row_ids = [r.row_id for r in response.rows]
2292+
assert rows.total == len(data)
2293+
2294+
assert rows.values[0]["output"] == "Input was None"
2295+
assert rows.values[1]["output"] == "Input was: test value"
2296+
assert rows.values[2]["output"] == "Input was None"
2297+
assert rows.values[3]["output"] == "Input was: "
2298+
2299+
# Test regen with null values
2300+
response = regen_table_rows(
2301+
client, table_type, table.id, row_ids, stream=stream, check_usage=False
2302+
)
2303+
assert len(response.rows) == len(data)
2304+
2305+
rows = list_table_rows(client, table_type, table.id)
2306+
assert rows.total == len(data)
2307+
2308+
assert rows.values[0]["output"] == "Input was None"
2309+
assert rows.values[1]["output"] == "Input was: test value"
2310+
assert rows.values[2]["output"] == "Input was None"
2311+
assert rows.values[3]["output"] == "Input was: "

0 commit comments

Comments
 (0)