Skip to content

Add OpenAI Chat Completions API #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 17, 2025
Merged

Add OpenAI Chat Completions API #75

merged 7 commits into from
Jun 17, 2025

Conversation

huiwengoh
Copy link
Collaborator

@huiwengoh huiwengoh commented Jun 12, 2025

Sample usage for create:

from cleanlab_tlm.utils.chat_completions import TLMChatCompletion

tlm = TLMChatCompletion(options={"log": ["explanation"]})
chat_response = tlm.create(
    model="gpt-4o-mini",
    messages=[{"content": "What is 1+1?","role": "user"}],
)

chat_response
>> ChatCompletion(id='chatcmpl-BhQL54McqQIGsJNQgLA7HzMhs6EoR', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='1 + 1 equals 2.', refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=None))], created=1749689051, model='gpt-4o-mini-2024-07-18', object='chat.completion', service_tier=None, system_fingerprint='fp_34a54ae93c', usage=CompletionUsage(completion_tokens=8, prompt_tokens=14, total_tokens=22, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0)), _request_id='req_e6b39046487f484f59b92a8191ec6f59', tlm_metadata={'log': {'explanation': 'Did not find a reason to doubt trustworthiness.'}, 'trustworthiness_score': 0.9020307464477912})

chat_response.choices[0].message.content
>> '1 + 1 equals 2.'

chat_response.tlm_metadata
>> {'log': {'explanation': 'Did not find a reason to doubt trustworthiness.'}, 'trustworthiness_score': 0.9020307464477912}

Sample usage for score:

import openai
from cleanlab_tlm.utils.chat_completions import TLMChatCompletion

openai_kwargs = {
    "model":"gpt-4o-mini",
    "messages":[{ "content": "What is 1+1?","role": "user"}]
}
openai_completion = openai.chat.completions.create(
  **openai_kwargs
)

openai_completion
>> ChatCompletion(id='chatcmpl-BhQLXqDrvjPr1o2W7GqHXeQwLqOqc', choices=[Choice(finish_reason='stop', index=0, logprobs=None, message=ChatCompletionMessage(content='1 + 1 equals 2.', refusal=None, role='assistant', annotations=[], audio=None, function_call=None, tool_calls=None))], created=1749689079, model='gpt-4o-mini-2024-07-18', object='chat.completion', service_tier='default', system_fingerprint='fp_62a23a81ef', usage=CompletionUsage(completion_tokens=8, prompt_tokens=14, total_tokens=22, completion_tokens_details=CompletionTokensDetails(accepted_prediction_tokens=0, audio_tokens=0, reasoning_tokens=0, rejected_prediction_tokens=0), prompt_tokens_details=PromptTokensDetails(audio_tokens=0, cached_tokens=0)))

tlm = TLMChatCompletion(options={"log": ["explanation"]})
score_response = tlm.score(
    response=openai_completion,
    **openai_kwargs
)

score_response
>> {'trustworthiness_score': 0.918869698047638, 'log': {'explanation': 'Did not find a reason to doubt trustworthiness.'}}

@huiwengoh huiwengoh requested a review from jwmueller June 12, 2025 00:46
tools = openai_kwargs.get("tools", None)

prompt_text = form_prompt_string(messages, tools)
response_text = _get_string_response(response)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you save a ticket for future PR:

we should try to extract token-probs out of response object if they are in there and include them in the score, like in TLMLite

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when the user does: TLMChatCompletions.create()

the resulting scores should also be including token-probs (can save for future PR too)


if not isinstance(response, ChatCompletion):
raise TypeError("The response is not an OpenAI ChatCompletion object.")
if response.choices[0].message.content is None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will tool call output / structured output be here too if OpenAI chose to return that?

if not, can you save a ticket for future PR that we should get those outputs and use the appropriate TLM scoring for them

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this code does not do that yet, I believe I can add rudimentary support for that pretty easily tho

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@huiwengoh do you still plan to add the support in this PR or in a followup ticket?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created ticket!

@@ -0,0 +1,123 @@
import asyncio
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my recommended tutorial to make for this is here:

#74 (comment)

would be good to investigate whether the better monkey-patch version of workflow 2 in that link can be made to work with this API

Copy link
Member

@jwmueller jwmueller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API LGTM. Leaving underlying code review to @jas2600

Note I suggested the ways this should be tested and how our eventual tutorial for it should look:

#74 (comment)

@jwmueller jwmueller requested a review from jas2600 June 12, 2025 02:00
@huiwengoh huiwengoh requested a review from jas2600 June 13, 2025 19:43
Comment on lines +88 to +90
tools = openai_kwargs.get("tools", None)

prompt_text = form_prompt_string(messages, tools)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] cleaner to just pass openai_kwargs.get("tools", None) directly instead of creating an additional variable

@jas2600
Copy link
Collaborator

jas2600 commented Jun 13, 2025

don't forget to release a new version

huiwengoh and others added 2 commits June 17, 2025 13:27
@huiwengoh huiwengoh merged commit a24f881 into main Jun 17, 2025
3 checks passed
@huiwengoh huiwengoh deleted the chat-completions-api branch June 17, 2025 19:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants