Skip to content

Commit 6617ddf

Browse files
committed
Add support for new api
1 parent 2b1c914 commit 6617ddf

7 files changed

Lines changed: 154 additions & 118 deletions

File tree

examples/cookbook.ipynb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,13 @@
326326
"for key, value in query_response.items(): print(f\"{key}: {value}\")"
327327
]
328328
},
329+
{
330+
"cell_type": "markdown",
331+
"metadata": {},
332+
"source": [
333+
"## A/B Testing with Function Versions"
334+
]
335+
},
329336
{
330337
"cell_type": "markdown",
331338
"metadata": {},

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ authors = [
1010
]
1111
description = "A client facing API for interacting with the WeCo AI function builder service."
1212
readme = "README.md"
13-
version = "0.1.5"
13+
version = "0.1.6"
1414
license = {text = "MIT"}
1515
requires-python = ">=3.8"
1616
dependencies = ["asyncio", "httpx[http2]", "pillow"]

tests/test_asynchronous.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
@pytest.mark.asyncio
99
async def test_abuild(text_evaluator, image_evaluator, text_and_image_evaluator):
1010
for evaluator in [text_evaluator, image_evaluator, text_and_image_evaluator]:
11-
fn_name, fn_desc = await evaluator
11+
fn_name, version_number, fn_desc = await evaluator
1212
assert isinstance(fn_name, str)
13+
assert isinstance(version_number, int)
1314
assert isinstance(fn_desc, str)
1415

1516

@@ -23,34 +24,37 @@ async def assert_query_response(query_response):
2324

2425
@pytest.fixture
2526
async def text_evaluator():
26-
fn_name, fn_desc = await abuild(
27-
task_description="Evaluate the sentiment of the given text. Provide a json object with 'sentiment' and 'explanation' keys."
27+
fn_name, version_number, fn_desc = await abuild(
28+
task_description="Evaluate the sentiment of the given text. Provide a json object with 'sentiment' and 'explanation' keys.",
29+
multimodal=False
2830
)
29-
return fn_name, fn_desc
31+
return fn_name, version_number, fn_desc
3032

3133

3234
@pytest.mark.asyncio
3335
async def test_text_aquery(text_evaluator):
34-
fn_name, _ = await text_evaluator
35-
query_response = await aquery(fn_name=fn_name, text_input="I love this product!")
36+
fn_name, version_number, _ = await text_evaluator
37+
query_response = await aquery(fn_name=fn_name, version_number=version_number, text_input="I love this product!")
3638

3739
await assert_query_response(query_response)
3840
assert set(query_response["output"].keys()) == {"sentiment", "explanation"}
3941

4042

4143
@pytest.fixture
4244
async def image_evaluator():
43-
fn_name, fn_desc = await abuild(
44-
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys."
45+
fn_name, version_number, fn_desc = await abuild(
46+
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys.",
47+
multimodal=True
4548
)
46-
return fn_name, fn_desc
49+
return fn_name, version_number, fn_desc
4750

4851

4952
@pytest.mark.asyncio
5053
async def test_image_aquery(image_evaluator):
51-
fn_name, _ = await image_evaluator
54+
fn_name, version_number, _ = await image_evaluator
5255
query_response = await aquery(
5356
fn_name=fn_name,
57+
version_number=version_number,
5458
images_input=[
5559
"https://www.integratedtreatmentservices.co.uk/wp-content/uploads/2013/12/Objects-of-Reference.jpg",
5660
"https://t4.ftcdn.net/jpg/05/70/90/23/360_F_570902339_kNj1reH40GFXakTy98EmfiZHci2xvUCS.jpg",
@@ -63,17 +67,19 @@ async def test_image_aquery(image_evaluator):
6367

6468
@pytest.fixture
6569
async def text_and_image_evaluator():
66-
fn_name, fn_desc = await abuild(
67-
task_description="Evaluate, solve and arrive at a numerical answer for the image provided. Provide a json object with 'answer' and 'explanation' keys."
70+
fn_name, version_number, fn_desc = await abuild(
71+
task_description="Evaluate, solve and arrive at a numerical answer for the image provided. Provide a json object with 'answer' and 'explanation' keys.",
72+
multimodal=True
6873
)
69-
return fn_name, fn_desc
74+
return fn_name, version_number, fn_desc
7075

7176

7277
@pytest.mark.asyncio
7378
async def test_text_and_image_aquery(text_and_image_evaluator):
74-
fn_name, _ = await text_and_image_evaluator
79+
fn_name, version_number, _ = await text_and_image_evaluator
7580
query_response = await aquery(
7681
fn_name=fn_name,
82+
version_number=version_number,
7783
text_input="Find x and y.",
7884
images_input=[
7985
"https://i.ytimg.com/vi/cblHUeq3bkE/hq720.jpg?sqp=-oaymwEhCK4FEIIDSFryq4qpAxMIARUAAAAAGAElAADIQj0AgKJD&rs=AOn4CLAKn3piY91QRCBzRgnzAPf7MPrjDQ"

tests/test_batching.py

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,62 +5,71 @@
55

66
# Internally, these functions use the WecoAI client
77
# therefore, we can test both the client and functional forms here
8-
# We do NOT need to test for a list of function names here since interally
9-
# we cast the input to a list of function names to match the fn_input size
108
@pytest.fixture
119
def ml_task_evaluator():
12-
fn_name, _ = build(
13-
task_description="I want to evaluate the feasibility of a machine learning task. Give me a json object with three keys - 'feasibility', 'justification', and 'suggestions'."
10+
fn_name, version_number, _ = build(
11+
task_description="I want to evaluate the feasibility of a machine learning task. Give me a json object with three keys - 'feasibility', 'justification', and 'suggestions'.",
12+
multimodal=False
1413
)
15-
return fn_name
14+
return fn_name, version_number
1615

1716

1817
@pytest.fixture
1918
def ml_task_inputs():
2019
return [
2120
{"text_input": "I want to train a model to predict house prices using the Boston Housing dataset hosted on Kaggle."},
22-
{
23-
"text_input": "I want to train a model to classify digits using the MNIST dataset hosted on Kaggle using a Google Colab notebook."
24-
},
21+
{"text_input": "I want to train a model to classify digits using the MNIST dataset hosted on Kaggle using a Google Colab notebook."},
2522
]
2623

2724

2825
@pytest.fixture
2926
def image_evaluator():
30-
fn_name, _ = build(
31-
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys."
27+
fn_name, version_number, _ = build(
28+
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys.",
29+
multimodal=True
3230
)
33-
return fn_name
31+
return fn_name, version_number
3432

3533

3634
@pytest.fixture
3735
def image_inputs():
3836
return [
39-
{
40-
"images_input": [
41-
"https://www.integratedtreatmentservices.co.uk/wp-content/uploads/2013/12/Objects-of-Reference.jpg"
42-
]
43-
},
37+
{"images_input": ["https://www.integratedtreatmentservices.co.uk/wp-content/uploads/2013/12/Objects-of-Reference.jpg"]},
4438
{"images_input": ["https://t4.ftcdn.net/jpg/05/70/90/23/360_F_570902339_kNj1reH40GFXakTy98EmfiZHci2xvUCS.jpg"]},
4539
]
4640

4741

48-
def test_batch_query(ml_task_evaluator, ml_task_inputs, image_evaluator, image_inputs):
49-
fn_names = [ml_task_evaluator, ml_task_evaluator, image_evaluator, image_evaluator]
50-
batch_inputs = ml_task_inputs + image_inputs
42+
def test_batch_query_text(ml_task_evaluator, ml_task_inputs):
43+
fn_name, version_number = ml_task_evaluator
44+
batch_inputs = ml_task_inputs
5145

52-
query_responses = batch_query(fn_names=fn_names, batch_inputs=batch_inputs)
46+
query_responses = batch_query(fn_name=fn_name, version_number=version_number, batch_inputs=batch_inputs)
5347

5448
assert len(query_responses) == len(batch_inputs)
5549

56-
for i, query_response in enumerate(query_responses):
50+
for query_response in query_responses:
5751
assert isinstance(query_response["output"], dict)
5852
assert isinstance(query_response["in_tokens"], int)
5953
assert isinstance(query_response["out_tokens"], int)
6054
assert isinstance(query_response["latency_ms"], float)
6155

6256
output = query_response["output"]
63-
if i < len(ml_task_inputs):
64-
assert set(output.keys()) == {"feasibility", "justification", "suggestions"}
65-
else:
66-
assert set(output.keys()) == {"description", "objects"}
57+
assert set(output.keys()) == {"feasibility", "justification", "suggestions"}
58+
59+
60+
def test_batch_query_image(image_evaluator, image_inputs):
61+
fn_name, version_number = image_evaluator
62+
batch_inputs = image_inputs
63+
64+
query_responses = batch_query(fn_name=fn_name, version_number=version_number, batch_inputs=batch_inputs)
65+
66+
assert len(query_responses) == len(batch_inputs)
67+
68+
for query_response in query_responses:
69+
assert isinstance(query_response["output"], dict)
70+
assert isinstance(query_response["in_tokens"], int)
71+
assert isinstance(query_response["out_tokens"], int)
72+
assert isinstance(query_response["latency_ms"], float)
73+
74+
output = query_response["output"]
75+
assert set(output.keys()) == {"description", "objects"}

tests/test_synchronous.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
# therefore, we can test both the client and functional forms here
88
def test_build(text_evaluator, image_evaluator, text_and_image_evaluator):
99
for evaluator in [text_evaluator, image_evaluator, text_and_image_evaluator]:
10-
fn_name, fn_desc = evaluator
10+
fn_name, version_number, fn_desc = evaluator
1111
assert isinstance(fn_name, str)
12+
assert isinstance(version_number, int)
1213
assert isinstance(fn_desc, str)
1314

1415

@@ -22,32 +23,35 @@ def assert_query_response(query_response):
2223

2324
@pytest.fixture
2425
def text_evaluator():
25-
fn_name, fn_desc = build(
26-
task_description="Evaluate the sentiment of the given text. Provide a json object with 'sentiment' and 'explanation' keys."
26+
fn_name, version_number, fn_desc = build(
27+
task_description="Evaluate the sentiment of the given text. Provide a json object with 'sentiment' and 'explanation' keys.",
28+
multimodal=False
2729
)
28-
return fn_name, fn_desc
30+
return fn_name, version_number, fn_desc
2931

3032

3133
def test_text_query(text_evaluator):
32-
fn_name, _ = text_evaluator
33-
query_response = query(fn_name=fn_name, text_input="I love this product!")
34+
fn_name, version_number, _ = text_evaluator
35+
query_response = query(fn_name=fn_name, version_number=version_number, text_input="I love this product!")
3436

3537
assert_query_response(query_response)
3638
assert set(query_response["output"].keys()) == {"sentiment", "explanation"}
3739

3840

3941
@pytest.fixture
4042
def image_evaluator():
41-
fn_name, fn_desc = build(
42-
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys."
43+
fn_name, version_number, fn_desc = build(
44+
task_description="Describe the contents of the given images. Provide a json object with 'description' and 'objects' keys.",
45+
multimodal=True
4346
)
44-
return fn_name, fn_desc
47+
return fn_name, version_number, fn_desc
4548

4649

4750
def test_image_query(image_evaluator):
48-
fn_name, _ = image_evaluator
51+
fn_name, version_number, _ = image_evaluator
4952
query_response = query(
5053
fn_name=fn_name,
54+
version_number=version_number,
5155
images_input=[
5256
"https://www.integratedtreatmentservices.co.uk/wp-content/uploads/2013/12/Objects-of-Reference.jpg",
5357
"https://t4.ftcdn.net/jpg/05/70/90/23/360_F_570902339_kNj1reH40GFXakTy98EmfiZHci2xvUCS.jpg",
@@ -60,16 +64,18 @@ def test_image_query(image_evaluator):
6064

6165
@pytest.fixture
6266
def text_and_image_evaluator():
63-
fn_name, fn_desc = build(
64-
task_description="Evaluate, solve and arrive at a numerical answer for the image provided. Perform any additional things if instructed. Provide a json object with 'answer' and 'explanation' keys."
67+
fn_name, version_number, fn_desc = build(
68+
task_description="Evaluate, solve and arrive at a numerical answer for the image provided. Perform any additional things if instructed. Provide a json object with 'answer' and 'explanation' keys.",
69+
multimodal=True
6570
)
66-
return fn_name, fn_desc
71+
return fn_name, version_number, fn_desc
6772

6873

6974
def test_text_and_image_query(text_and_image_evaluator):
70-
fn_name, _ = text_and_image_evaluator
75+
fn_name, version_number, _ = text_and_image_evaluator
7176
query_response = query(
7277
fn_name=fn_name,
78+
version_number=version_number,
7379
text_input="Find x and y.",
7480
images_input=[
7581
"https://i.ytimg.com/vi/cblHUeq3bkE/hq720.jpg?sqp=-oaymwEhCK4FEIIDSFryq4qpAxMIARUAAAAAGAElAADIQj0AgKJD&rs=AOn4CLAKn3piY91QRCBzRgnzAPf7MPrjDQ"

0 commit comments

Comments
 (0)