Skip to content

Commit 66d15ef

Browse files
committed
Skeleton ok
1 parent 8028305 commit 66d15ef

File tree

9 files changed

+571
-26
lines changed

9 files changed

+571
-26
lines changed

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ classifiers = [
1717
"Programming Language :: Python :: 3.13",
1818
"Topic :: Software Development :: Libraries :: Python Modules",
1919
]
20+
dependencies = [
21+
"openai>=1.58.1",
22+
"pydantic>=2.10.4",
23+
]
2024

2125
[project.urls]
2226
Homepage = "https://sarus-tech.github.io/structured-logprobs/"
@@ -35,6 +39,7 @@ dev = [
3539
"mkdocs>=1.4.2",
3640
"mkdocs-material>=8.5.10",
3741
"mkdocstrings[python]>=0.26.1",
42+
"python-dotenv>=1.0.1",
3843
]
3944

4045
[build-system]

structured_logprobs/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .main import add_logprobs as add_logprobs

structured_logprobs/foo.py

Lines changed: 0 additions & 17 deletions
This file was deleted.

structured_logprobs/main.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from typing import TypeVar
2+
3+
from openai.types.chat.chat_completion import ChatCompletion
4+
from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
5+
6+
CC = TypeVar("CC", bound=ChatCompletion)
7+
8+
9+
def add_logprobs(chat_completion_response: CC) -> CC:
10+
"""Summary line.
11+
12+
Extended description of function.
13+
14+
Args:
15+
bar: Description of input argument.
16+
17+
Returns:
18+
Description of return value
19+
"""
20+
21+
# TODO NG: add the useful code there
22+
if isinstance(chat_completion_response, ParsedChatCompletion):
23+
# Process the Parsed case
24+
pass
25+
else:
26+
# The default case
27+
pass
28+
29+
return chat_completion_response
30+
31+
32+
if __name__ == "__main__": # pragma: no cover
33+
pass

tests/conftest.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from pathlib import Path
2+
3+
import pytest
4+
from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
5+
from pydantic import BaseModel
6+
7+
8+
class CalendarEvent(BaseModel):
9+
name: str
10+
date: str
11+
participants: list[str]
12+
13+
14+
@pytest.fixture
15+
def simple_parsed_completion(pytestconfig) -> ParsedChatCompletion[CalendarEvent] | None:
16+
base_path = Path(pytestconfig.rootdir) # Base directory where pytest was run
17+
with open(base_path / "tests" / "simple_parsed_completion.json") as f:
18+
return ParsedChatCompletion[CalendarEvent].model_validate_json(f.read())
19+
return None
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
{
2+
"id": "chatcmpl-AigSM81aLFRN07IUezlC3zlZ9zdaU",
3+
"choices": [
4+
{
5+
"finish_reason": "stop",
6+
"index": 0,
7+
"logprobs": {
8+
"content": [
9+
{
10+
"token": "{\"",
11+
"bytes": [123, 34],
12+
"logprob": -0.000012590794,
13+
"top_logprobs": []
14+
},
15+
{
16+
"token": "name",
17+
"bytes": [110, 97, 109, 101],
18+
"logprob": 0.0,
19+
"top_logprobs": []
20+
},
21+
{
22+
"token": "\":\"",
23+
"bytes": [34, 58, 34],
24+
"logprob": -6.704273e-7,
25+
"top_logprobs": []
26+
},
27+
{
28+
"token": "Science",
29+
"bytes": [83, 99, 105, 101, 110, 99, 101],
30+
"logprob": -0.00012964146,
31+
"top_logprobs": []
32+
},
33+
{
34+
"token": " Fair",
35+
"bytes": [32, 70, 97, 105, 114],
36+
"logprob": -0.000058603408,
37+
"top_logprobs": []
38+
},
39+
{
40+
"token": "\",\"",
41+
"bytes": [34, 44, 34],
42+
"logprob": -0.0018461747,
43+
"top_logprobs": []
44+
},
45+
{
46+
"token": "date",
47+
"bytes": [100, 97, 116, 101],
48+
"logprob": 0.0,
49+
"top_logprobs": []
50+
},
51+
{
52+
"token": "\":\"",
53+
"bytes": [34, 58, 34],
54+
"logprob": -4.9617593e-6,
55+
"top_logprobs": []
56+
},
57+
{
58+
"token": "Friday",
59+
"bytes": [70, 114, 105, 100, 97, 121],
60+
"logprob": -0.09504829,
61+
"top_logprobs": []
62+
},
63+
{
64+
"token": "\",\"",
65+
"bytes": [34, 44, 34],
66+
"logprob": -0.0026011032,
67+
"top_logprobs": []
68+
},
69+
{
70+
"token": "participants",
71+
"bytes": [
72+
112, 97, 114, 116, 105, 99, 105, 112, 97, 110, 116,
73+
115
74+
],
75+
"logprob": -1.9361265e-7,
76+
"top_logprobs": []
77+
},
78+
{
79+
"token": "\":[\"",
80+
"bytes": [34, 58, 91, 34],
81+
"logprob": 0.0,
82+
"top_logprobs": []
83+
},
84+
{
85+
"token": "Alice",
86+
"bytes": [65, 108, 105, 99, 101],
87+
"logprob": 0.0,
88+
"top_logprobs": []
89+
},
90+
{
91+
"token": "\",\"",
92+
"bytes": [34, 44, 34],
93+
"logprob": -1.2664457e-6,
94+
"top_logprobs": []
95+
},
96+
{
97+
"token": "Bob",
98+
"bytes": [66, 111, 98],
99+
"logprob": -7.89631e-7,
100+
"top_logprobs": []
101+
},
102+
{
103+
"token": "\"]",
104+
"bytes": [34, 93],
105+
"logprob": -1.9361265e-7,
106+
"top_logprobs": []
107+
},
108+
{
109+
"token": "}",
110+
"bytes": [125],
111+
"logprob": 0.0,
112+
"top_logprobs": []
113+
}
114+
],
115+
"refusal": null
116+
},
117+
"message": {
118+
"content": "{\"name\":\"Science Fair\",\"date\":\"Friday\",\"participants\":[\"Alice\",\"Bob\"]}",
119+
"refusal": null,
120+
"role": "assistant",
121+
"audio": null,
122+
"function_call": null,
123+
"tool_calls": [],
124+
"parsed": {
125+
"name": "Science Fair",
126+
"date": "Friday",
127+
"participants": ["Alice", "Bob"]
128+
}
129+
}
130+
}
131+
],
132+
"created": 1735212998,
133+
"model": "gpt-4o-2024-08-06",
134+
"object": "chat.completion",
135+
"service_tier": null,
136+
"system_fingerprint": "fp_5f20662549",
137+
"usage": {
138+
"completion_tokens": 18,
139+
"prompt_tokens": 92,
140+
"total_tokens": 110,
141+
"completion_tokens_details": {
142+
"accepted_prediction_tokens": 0,
143+
"audio_tokens": 0,
144+
"reasoning_tokens": 0,
145+
"rejected_prediction_tokens": 0
146+
},
147+
"prompt_tokens_details": {
148+
"audio_tokens": 0,
149+
"cached_tokens": 0
150+
}
151+
}
152+
}

tests/test_foo.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

tests/test_main.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import pytest
2+
from dotenv import load_dotenv
3+
from openai import OpenAI
4+
from openai.types.chat.parsed_chat_completion import ParsedChatCompletion
5+
from pydantic import BaseModel
6+
7+
from structured_logprobs import add_logprobs
8+
9+
# Your token should be in a .env file OPENAI_API_KEY="..."
10+
load_dotenv()
11+
12+
13+
@pytest.mark.skip(reason="We do not want to automate this as no OPENAI_API_KEY is on github yet")
14+
def test_simple_parsed_completion_with_openai():
15+
client = OpenAI()
16+
17+
# A simple data model
18+
class CalendarEvent(BaseModel):
19+
name: str
20+
date: str
21+
participants: list[str]
22+
23+
# A request with structured output
24+
completion = client.beta.chat.completions.parse(
25+
model="gpt-4o-2024-08-06",
26+
messages=[
27+
{"role": "system", "content": "Extract the event information."},
28+
{"role": "user", "content": "Alice and Bob are going to a science fair on Friday."},
29+
],
30+
logprobs=True,
31+
response_format=CalendarEvent,
32+
)
33+
completion = add_logprobs(completion)
34+
event = completion.choices[0].message.parsed
35+
print(event)
36+
# Test if logprobs are there in the expected way (when they will be)
37+
assert event.name == "Science Fair"
38+
39+
40+
def test_simple_parsed_completion(simple_parsed_completion):
41+
assert isinstance(simple_parsed_completion, ParsedChatCompletion)
42+
completion = add_logprobs(simple_parsed_completion)
43+
event = completion.choices[0].message.parsed
44+
print(event)
45+
# Test if logprobs are there in the expected way (when they will be)
46+
assert event.name == "Science Fair"

0 commit comments

Comments
 (0)