Skip to content

Commit

Permalink
feat: replaced openai client with chat completion api
Browse files Browse the repository at this point in the history
  • Loading branch information
irfanuddinahmad committed Jun 12, 2024
1 parent 91491d7 commit 2f6dc17
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 37 deletions.
44 changes: 31 additions & 13 deletions taxonomy/openai/client.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,43 @@
"""openai client"""
"""CHAT_COMPLETION_API client"""
import logging

import openai
import requests
from requests.exceptions import ConnectTimeout

from django.conf import settings

openai.api_key = settings.OPENAI_API_KEY
log = logging.getLogger(__name__)


def chat_completion(prompt):
"""
Use chatGPT https://api.openai.com/v1/chat/completions endpoint to generate a response.
Pass message list to chat endpoint, as defined by the CHAT_COMPLETION_API setting.
Arguments:
prompt (str): chatGPT prompt
"""
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[
{"role": "user", "content": prompt},
]
)
completion_endpoint = getattr(settings, 'CHAT_COMPLETION_API', None)
completion_endpoint_key = getattr(settings, 'CHAT_COMPLETION_API_KEY', None)
if completion_endpoint and completion_endpoint_key:
headers = {'Content-Type': 'application/json', 'x-api-key': completion_endpoint_key}
connect_timeout = getattr(settings, 'CHAT_COMPLETION_API_CONNECT_TIMEOUT', 1)
read_timeout = getattr(settings, 'CHAT_COMPLETION_API_READ_TIMEOUT', 15)
try:
response = requests.post(
completion_endpoint,
headers=headers,
data=prompt,
timeout=(connect_timeout, read_timeout)
)
chat = response.json()
except (ConnectTimeout, ConnectionError) as e:
error_message = str(e)
connection_message = 'Failed to connect to chat completion API.'
log.error(
'%(connection_message)s %(error)s',
{'connection_message': connection_message, 'error': error_message}
)
chat = connection_message
else:
chat = 'Completion endpoint is not defined.'

content = response['choices'][0]['message']['content']
return content
return chat
3 changes: 2 additions & 1 deletion test_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ def root(*args):
SKILLS_IGNORED_THRESHOLD = 10
SKILLS_IGNORED_RATIO_THRESHOLD = 0.8

OPENAI_API_KEY = 'I am a key'
CHAT_COMPLETION_API = 'test chat completion api'
CHAT_COMPLETION_API_KEY = 'test chat completion api key'

JOB_DESCRIPTION_PROMPT = 'Generate a description for {job_name} job role.'
JOB_TO_JOB_DESCRIPTION_PROMPT = 'How can a {current_job_name} switch to {future_job_name} job role.'
18 changes: 4 additions & 14 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,41 +346,31 @@ def test_string_representation(self):
assert expected_repr == job.__repr__()

@pytest.mark.use_signals
@patch('taxonomy.openai.client.openai.ChatCompletion.create')
@patch('taxonomy.openai.client.requests.post')
@patch('taxonomy.utils.generate_and_store_job_description', wraps=generate_and_store_job_description)
@patch('taxonomy.signals.handlers.generate_job_description.delay', wraps=generate_job_description)
def test_chat_completion_is_called( # pylint: disable=invalid-name
self,
mocked_generate_job_description_task,
mocked_generate_and_store_job_description,
mocked_chat_completion
mock_requests
):
"""
Verify that complete flow works as expected when a Job model object is created.
"""
ai_response = 'One who manages a Computer Network.'
mocked_chat_completion.return_value = {
'choices': [{
'message': {
'content': ai_response
}
}]
}
mock_requests.return_value.json.return_value = ai_response

job_external_id = '1111'
job_name = 'Network Admin'
prompt = settings.JOB_DESCRIPTION_PROMPT.format(job_name=job_name)

Job(external_id=job_external_id, name=job_name).save()
job = Job.objects.get(external_id=job_external_id)

assert job.description == ai_response
mocked_generate_job_description_task.assert_called_once_with(job_external_id, job_name)
mocked_generate_and_store_job_description.assert_called_once_with(job_external_id, job_name)
mocked_chat_completion.assert_called_once_with(
model='gpt-3.5-turbo',
messages=[{'role': 'user', 'content': prompt}]
)
mock_requests.assert_called_once()

@pytest.mark.use_signals
@patch('taxonomy.utils.chat_completion')
Expand Down
12 changes: 3 additions & 9 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,27 +646,21 @@ def setUp(self) -> None:
self.client.login(username=self.user.username, password=USER_PASSWORD)
self.view_url = '/api/v1/job-path/'

@patch('taxonomy.openai.client.openai.ChatCompletion.create')
@patch('taxonomy.openai.client.requests.post')
@patch(
'taxonomy.api.v1.serializers.generate_and_store_job_to_job_description',
wraps=generate_and_store_job_to_job_description
)
def test_job_path_api( # pylint: disable=invalid-name
self,
mocked_generate_and_store_job_to_job_description,
mocked_chat_completion
mock_requests
):
"""
Verify that job path API returns the expected response.
"""
ai_response = 'You can not switch from your current job to future job'
mocked_chat_completion.return_value = {
'choices': [{
'message': {
'content': ai_response
}
}]
}
mock_requests.return_value.json.return_value = ai_response

query_params = {
'current_job': self.current_job.external_id,
Expand Down

0 comments on commit 2f6dc17

Please sign in to comment.