From 4735715e434e67ee69c922d002e614de4af366ab Mon Sep 17 00:00:00 2001 From: irfanuddinahmad Date: Tue, 11 Jun 2024 17:45:55 +0500 Subject: [PATCH] feat: replaced openai client with chat completion api --- .github/workflows/mysql8-migrations.yml | 2 +- CHANGELOG.rst | 4 + requirements/ci.txt | 12 +- requirements/constraints.txt | 7 +- requirements/dev.txt | 186 +++++++++++++--------- requirements/doc.txt | 203 ++++++++++++++---------- requirements/pip-tools.txt | 13 +- requirements/pip.txt | 6 +- requirements/test.txt | 132 ++++++++------- taxonomy/__init__.py | 2 +- taxonomy/openai/client.py | 32 ++-- test_settings.py | 3 +- tests/openai/__init__.py | 0 tests/openai/test_client.py | 32 ++++ tests/test_models.py | 19 +-- tests/test_views.py | 13 +- 16 files changed, 400 insertions(+), 266 deletions(-) create mode 100644 tests/openai/__init__.py create mode 100644 tests/openai/test_client.py diff --git a/.github/workflows/mysql8-migrations.yml b/.github/workflows/mysql8-migrations.yml index 479efe72..58b04ee1 100644 --- a/.github/workflows/mysql8-migrations.yml +++ b/.github/workflows/mysql8-migrations.yml @@ -52,7 +52,7 @@ jobs: pip uninstall -y mysqlclient pip install --no-binary mysqlclient mysqlclient pip uninstall -y xmlsec - pip install --no-binary xmlsec xmlsec + pip install --no-binary xmlsec xmlsec==1.3.13 - name: Initiate Services run: | diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 0eb6b807..f8cbc3ca 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,10 @@ Change Log Unreleased +[1.51.0] - 2024-07-03 +--------------------- +* feat: Replaced client for ai chat + [1.50.0] - 2024-03-27 --------------------- * feat: Skill validation can be disbaled for a course or an organization diff --git a/requirements/ci.txt b/requirements/ci.txt index 25b2a935..0a21d07b 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -1,20 +1,20 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade # distlib==0.3.8 # via virtualenv -filelock==3.13.1 +filelock==3.15.4 # via # tox # virtualenv -packaging==24.0 +packaging==24.1 # via tox -platformdirs==4.2.0 +platformdirs==4.2.2 # via virtualenv -pluggy==1.4.0 +pluggy==1.5.0 # via tox py==1.11.0 # via tox @@ -26,5 +26,5 @@ tox==3.28.0 # via # -c requirements/constraints.txt # -r requirements/ci.in -virtualenv==20.25.1 +virtualenv==20.26.3 # via tox diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 105c7b5c..942551bb 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -13,8 +13,6 @@ django<4.0 path==13.1.0 -celery<5.0 - # latest version causing issues in discovery. algoliasearch-django<4.0.0 algoliasearch<2.0.0 @@ -28,3 +26,8 @@ sphinxcontrib-devhelp<=1.0.2 sphinxcontrib-htmlhelp<=2.0.1 sphinxcontrib-qthelp<=1.0.3 sphinxcontrib-serializinghtml<=1.1.5 +accessible-pygments<=0.0.4 +alabaster<=0.7.13 +pydata-sphinx-theme<=0.14.4 +sphinx<=7.1.2 +sphinx-book-theme<=1.0.1 diff --git a/requirements/dev.txt b/requirements/dev.txt index 7888c4ec..54b7c5a5 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade @@ -8,24 +8,24 @@ algoliasearch==1.20.0 # via # -c requirements/constraints.txt # -r requirements/test.txt -amqp==2.6.1 +amqp==5.2.0 # via # -r requirements/test.txt # kombu -annotated-types==0.6.0 +annotated-types==0.7.0 # via # -r requirements/test.txt # pydantic -anyio==4.3.0 +anyio==4.4.0 # via # -r requirements/test.txt # httpx # openai -asgiref==3.8.0 +asgiref==3.8.1 # via # -r requirements/test.txt # django -astroid==3.1.0 +astroid==3.2.3 # via # pylint # pylint-celery @@ -33,34 +33,28 @@ attrs==23.2.0 # via # -r requirements/test.txt # openedx-events -backports-zoneinfo==0.2.1 - # via - # -r requirements/test.txt - # djangorestframework beautifulsoup4==4.12.3 # via -r requirements/test.txt -billiard==3.6.4.0 +billiard==4.2.0 # via # -r requirements/test.txt # celery -boto3==1.34.67 +boto3==1.34.144 # via # -r requirements/test.txt # django-ses -botocore==1.34.67 +botocore==1.34.144 # via # -r requirements/test.txt # boto3 # s3transfer -build==1.1.1 +build==1.2.1 # via # -r requirements/pip-tools.txt # pip-tools -celery==4.4.7 - # via - # -c requirements/constraints.txt - # -r requirements/test.txt -certifi==2024.2.2 +celery==5.4.0 + # via -r requirements/test.txt +certifi==2024.7.4 # via # -r requirements/test.txt # httpcore @@ -80,24 +74,40 @@ click==8.1.7 # via # -r requirements/pip-tools.txt # -r requirements/test.txt + # celery + # click-didyoumean # click-log + # click-plugins + # click-repl # code-annotations # edx-django-utils # edx-lint # pip-tools +click-didyoumean==0.3.1 + # via + # -r requirements/test.txt + # celery click-log==0.4.0 # via edx-lint -code-annotations==1.7.0 +click-plugins==1.1.1 + # via + # -r requirements/test.txt + # celery +click-repl==0.3.0 + # via + # -r requirements/test.txt + # celery +code-annotations==1.8.0 # via # -r requirements/test.txt # edx-lint -coverage[toml]==7.4.4 +coverage[toml]==7.6.0 # via # -r requirements/test.txt # pytest-cov ddt==1.7.2 # via -r requirements/test.txt -diff-cover==8.0.3 +diff-cover==9.1.0 # via -r requirements/dev.in dill==0.3.8 # via pylint @@ -132,51 +142,60 @@ django-crum==0.7.9 # edx-django-utils django-filter==23.5 # via -r requirements/test.txt -django-model-utils==4.4.0 +django-model-utils==4.5.1 # via -r requirements/test.txt django-object-actions==4.2.0 # via -r requirements/test.txt -django-ses==3.5.2 +django-ses==4.1.0 # via -r requirements/test.txt -django-solo==2.2.0 +django-solo==2.3.0 # via -r requirements/test.txt django-waffle==4.1.0 # via # -r requirements/test.txt # edx-django-utils -djangorestframework==3.15.0 +djangorestframework==3.15.1 # via -r requirements/test.txt -edx-django-utils==5.11.0 +dnspython==2.6.1 + # via + # -r requirements/test.txt + # pymongo +edx-ccx-keys==1.3.0 + # via + # -r requirements/test.txt + # openedx-events +edx-django-utils==5.14.2 # via # -r requirements/test.txt # edx-rest-api-client # openedx-events -edx-i18n-tools==1.3.0 +edx-i18n-tools==1.6.0 # via -r requirements/dev.in -edx-lint==5.3.6 +edx-lint==5.3.7 # via -r requirements/dev.in -edx-opaque-keys[django]==2.5.1 +edx-opaque-keys[django]==2.10.0 # via # -r requirements/test.txt + # edx-ccx-keys # openedx-events -edx-rest-api-client==5.6.1 +edx-rest-api-client==5.7.1 # via -r requirements/test.txt -exceptiongroup==1.2.0 +exceptiongroup==1.2.2 # via # -r requirements/test.txt # anyio # pytest factory-boy==3.3.0 # via -r requirements/test.txt -faker==24.3.0 +faker==26.0.0 # via # -r requirements/test.txt # factory-boy -fastavro==1.9.4 +fastavro==1.9.5 # via # -r requirements/test.txt # openedx-events -filelock==3.13.1 +filelock==3.15.4 # via # -r requirements/ci.txt # tox @@ -185,7 +204,7 @@ h11==0.14.0 # via # -r requirements/test.txt # httpcore -httpcore==1.0.4 +httpcore==1.0.5 # via # -r requirements/test.txt # httpx @@ -193,13 +212,13 @@ httpx==0.27.0 # via # -r requirements/test.txt # openai -idna==3.6 +idna==3.7 # via # -r requirements/test.txt # anyio # httpx # requests -importlib-metadata==7.1.0 +importlib-metadata==8.0.0 # via # -r requirements/pip-tools.txt # build @@ -211,7 +230,7 @@ isort==5.13.2 # via # -r requirements/dev.in # pylint -jinja2==3.1.3 +jinja2==3.1.4 # via # -r requirements/test.txt # code-annotations @@ -221,12 +240,16 @@ jmespath==1.0.1 # -r requirements/test.txt # boto3 # botocore -kombu==4.6.11 +kombu==5.3.7 # via # -r requirements/test.txt # celery -lxml==5.1.0 - # via edx-i18n-tools +lxml[html-clean,html_clean]==5.2.2 + # via + # edx-i18n-tools + # lxml-html-clean +lxml-html-clean==0.1.1 + # via lxml markupsafe==2.1.5 # via # -r requirements/test.txt @@ -235,15 +258,15 @@ mccabe==0.7.0 # via pylint mock==5.1.0 # via -r requirements/test.txt -newrelic==9.7.1 +newrelic==9.12.0 # via # -r requirements/test.txt # edx-django-utils -openai==1.14.2 +openai==1.35.14 # via -r requirements/test.txt -openedx-events==9.5.2 +openedx-events==9.11.0 # via -r requirements/test.txt -packaging==24.0 +packaging==24.1 # via # -r requirements/ci.txt # -r requirements/pip-tools.txt @@ -261,12 +284,12 @@ pbr==6.0.0 # stevedore pip-tools==7.4.1 # via -r requirements/pip-tools.txt -platformdirs==4.2.0 +platformdirs==4.2.2 # via # -r requirements/ci.txt # pylint # virtualenv -pluggy==1.4.0 +pluggy==1.5.0 # via # -r requirements/ci.txt # -r requirements/test.txt @@ -275,7 +298,11 @@ pluggy==1.4.0 # tox polib==1.2.0 # via edx-i18n-tools -psutil==5.9.8 +prompt-toolkit==3.0.47 + # via + # -r requirements/test.txt + # click-repl +psutil==6.0.0 # via # -r requirements/test.txt # edx-django-utils @@ -283,29 +310,29 @@ py==1.11.0 # via # -r requirements/ci.txt # tox -pycodestyle==2.11.1 +pycodestyle==2.12.0 # via -r requirements/dev.in -pycparser==2.21 +pycparser==2.22 # via # -r requirements/test.txt # cffi -pydantic==2.6.4 +pydantic==2.8.2 # via # -r requirements/test.txt # openai -pydantic-core==2.16.3 +pydantic-core==2.20.1 # via # -r requirements/test.txt # pydantic pydocstyle==6.3.0 # via -r requirements/dev.in -pygments==2.17.2 +pygments==2.18.0 # via diff-cover pyjwt==2.8.0 # via # -r requirements/test.txt # edx-rest-api-client -pylint==3.1.0 +pylint==3.2.5 # via # edx-lint # pylint-celery @@ -319,7 +346,7 @@ pylint-plugin-utils==0.8.2 # via # pylint-celery # pylint-django -pymongo==3.13.0 +pymongo==4.8.0 # via # -r requirements/test.txt # edx-opaque-keys @@ -327,17 +354,17 @@ pynacl==1.5.0 # via # -r requirements/test.txt # edx-django-utils -pyproject-hooks==1.0.0 +pyproject-hooks==1.1.0 # via # -r requirements/pip-tools.txt # build # pip-tools -pytest==8.1.1 +pytest==8.2.2 # via # -r requirements/test.txt # pytest-cov # pytest-django -pytest-cov==4.1.0 +pytest-cov==5.0.0 # via -r requirements/test.txt pytest-django==4.8.0 # via -r requirements/test.txt @@ -345,6 +372,7 @@ python-dateutil==2.9.0.post0 # via # -r requirements/test.txt # botocore + # celery # faker python-slugify==8.0.4 # via @@ -353,7 +381,6 @@ python-slugify==8.0.4 pytz==2024.1 # via # -r requirements/test.txt - # celery # django # django-ses pyyaml==6.0.1 @@ -362,16 +389,16 @@ pyyaml==6.0.1 # code-annotations # edx-i18n-tools # responses -requests==2.31.0 +requests==2.32.3 # via # -r requirements/test.txt # algoliasearch # edx-rest-api-client # responses # slumber -responses==0.25.0 +responses==0.25.3 # via -r requirements/test.txt -s3transfer==0.10.1 +s3transfer==0.10.2 # via # -r requirements/test.txt # boto3 @@ -379,6 +406,7 @@ six==1.16.0 # via # -r requirements/ci.txt # -r requirements/test.txt + # edx-ccx-keys # edx-lint # python-dateutil # tox @@ -398,7 +426,7 @@ soupsieve==2.5 # via # -r requirements/test.txt # beautifulsoup4 -sqlparse==0.4.4 +sqlparse==0.5.1 # via # -r requirements/test.txt # django @@ -408,7 +436,7 @@ stevedore==5.2.0 # code-annotations # edx-django-utils # edx-opaque-keys -testfixtures==8.1.0 +testfixtures==8.3.0 # via -r requirements/test.txt text-unidecode==1.3 # via @@ -423,52 +451,60 @@ tomli==2.0.1 # coverage # pip-tools # pylint - # pyproject-hooks # pytest # tox -tomlkit==0.12.4 +tomlkit==0.13.0 # via pylint tox==3.28.0 # via # -c requirements/constraints.txt # -r requirements/ci.txt -tqdm==4.66.2 +tqdm==4.66.4 # via # -r requirements/test.txt # openai -typing-extensions==4.10.0 +typing-extensions==4.12.2 # via # -r requirements/test.txt - # annotated-types # anyio # asgiref # astroid + # django-solo # edx-opaque-keys - # faker + # kombu # openai # pydantic # pydantic-core # pylint -urllib3==1.26.18 +tzdata==2024.1 + # via + # -r requirements/test.txt + # celery +urllib3==1.26.19 # via # -r requirements/test.txt # botocore # requests # responses -vine==1.3.0 +vine==5.1.0 # via # -r requirements/test.txt # amqp # celery -virtualenv==20.25.1 + # kombu +virtualenv==20.26.3 # via # -r requirements/ci.txt # tox +wcwidth==0.2.13 + # via + # -r requirements/test.txt + # prompt-toolkit wheel==0.43.0 # via # -r requirements/pip-tools.txt # pip-tools -zipp==3.18.1 +zipp==3.19.2 # via # -r requirements/pip-tools.txt # importlib-metadata diff --git a/requirements/doc.txt b/requirements/doc.txt index 3e84ce7c..8f6bc22b 100644 --- a/requirements/doc.txt +++ b/requirements/doc.txt @@ -1,31 +1,35 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade # accessible-pygments==0.0.4 - # via pydata-sphinx-theme + # via + # -c requirements/constraints.txt + # pydata-sphinx-theme alabaster==0.7.13 - # via sphinx + # via + # -c requirements/constraints.txt + # sphinx algoliasearch==1.20.0 # via # -c requirements/constraints.txt # -r requirements/test.txt -amqp==2.6.1 +amqp==5.2.0 # via # -r requirements/test.txt # kombu -annotated-types==0.6.0 +annotated-types==0.7.0 # via # -r requirements/test.txt # pydantic -anyio==4.3.0 +anyio==4.4.0 # via # -r requirements/test.txt # httpx # openai -asgiref==3.8.0 +asgiref==3.8.1 # via # -r requirements/test.txt # django @@ -33,38 +37,34 @@ attrs==23.2.0 # via # -r requirements/test.txt # openedx-events -babel==2.14.0 +babel==2.15.0 # via # pydata-sphinx-theme # sphinx -backports-zoneinfo==0.2.1 - # via - # -r requirements/test.txt - # djangorestframework +backports-tarfile==1.2.0 + # via jaraco-context beautifulsoup4==4.12.3 # via # -r requirements/test.txt # pydata-sphinx-theme -billiard==3.6.4.0 +billiard==4.2.0 # via # -r requirements/test.txt # celery -boto3==1.34.67 +boto3==1.34.144 # via # -r requirements/test.txt # django-ses -botocore==1.34.67 +botocore==1.34.144 # via # -r requirements/test.txt # boto3 # s3transfer -build==1.1.1 +build==1.2.1 # via -r requirements/doc.in -celery==4.4.7 - # via - # -c requirements/constraints.txt - # -r requirements/test.txt -certifi==2024.2.2 +celery==5.4.0 + # via -r requirements/test.txt +certifi==2024.7.4 # via # -r requirements/test.txt # httpcore @@ -81,11 +81,27 @@ charset-normalizer==3.3.2 click==8.1.7 # via # -r requirements/test.txt + # celery + # click-didyoumean + # click-plugins + # click-repl # code-annotations # edx-django-utils -code-annotations==1.7.0 +click-didyoumean==0.3.1 + # via + # -r requirements/test.txt + # celery +click-plugins==1.1.1 + # via + # -r requirements/test.txt + # celery +click-repl==0.3.0 + # via + # -r requirements/test.txt + # celery +code-annotations==1.8.0 # via -r requirements/test.txt -coverage[toml]==7.4.4 +coverage[toml]==7.6.0 # via # -r requirements/test.txt # pytest-cov @@ -117,20 +133,24 @@ django-crum==0.7.9 # edx-django-utils django-filter==23.5 # via -r requirements/test.txt -django-model-utils==4.4.0 +django-model-utils==4.5.1 # via -r requirements/test.txt django-object-actions==4.2.0 # via -r requirements/test.txt -django-ses==3.5.2 +django-ses==4.1.0 # via -r requirements/test.txt -django-solo==2.2.0 +django-solo==2.3.0 # via -r requirements/test.txt django-waffle==4.1.0 # via # -r requirements/test.txt # edx-django-utils -djangorestframework==3.15.0 +djangorestframework==3.15.1 # via -r requirements/test.txt +dnspython==2.6.1 + # via + # -r requirements/test.txt + # pymongo doc8==1.1.1 # via -r requirements/doc.in docutils==0.19 @@ -140,29 +160,34 @@ docutils==0.19 # readme-renderer # restructuredtext-lint # sphinx -edx-django-utils==5.11.0 +edx-ccx-keys==1.3.0 + # via + # -r requirements/test.txt + # openedx-events +edx-django-utils==5.14.2 # via # -r requirements/test.txt # edx-rest-api-client # openedx-events -edx-opaque-keys[django]==2.5.1 +edx-opaque-keys[django]==2.10.0 # via # -r requirements/test.txt + # edx-ccx-keys # openedx-events -edx-rest-api-client==5.6.1 +edx-rest-api-client==5.7.1 # via -r requirements/test.txt -exceptiongroup==1.2.0 +exceptiongroup==1.2.2 # via # -r requirements/test.txt # anyio # pytest factory-boy==3.3.0 # via -r requirements/test.txt -faker==24.3.0 +faker==26.0.0 # via # -r requirements/test.txt # factory-boy -fastavro==1.9.4 +fastavro==1.9.5 # via # -r requirements/test.txt # openedx-events @@ -170,7 +195,7 @@ h11==0.14.0 # via # -r requirements/test.txt # httpcore -httpcore==1.0.4 +httpcore==1.0.5 # via # -r requirements/test.txt # httpx @@ -178,7 +203,7 @@ httpx==0.27.0 # via # -r requirements/test.txt # openai -idna==3.6 +idna==3.7 # via # -r requirements/test.txt # anyio @@ -186,21 +211,23 @@ idna==3.6 # requests imagesize==1.4.1 # via sphinx -importlib-metadata==7.1.0 +importlib-metadata==8.0.0 # via # build # keyring # sphinx # twine -importlib-resources==6.3.2 - # via keyring iniconfig==2.0.0 # via # -r requirements/test.txt # pytest -jaraco-classes==3.3.1 +jaraco-classes==3.4.0 + # via keyring +jaraco-context==5.3.0 # via keyring -jinja2==3.1.3 +jaraco-functools==4.0.1 + # via keyring +jinja2==3.1.4 # via # -r requirements/test.txt # code-annotations @@ -210,9 +237,9 @@ jmespath==1.0.1 # -r requirements/test.txt # boto3 # botocore -keyring==24.3.1 +keyring==25.2.1 # via twine -kombu==4.6.11 +kombu==5.3.7 # via # -r requirements/test.txt # celery @@ -226,19 +253,21 @@ mdurl==0.1.2 # via markdown-it-py mock==5.1.0 # via -r requirements/test.txt -more-itertools==10.2.0 - # via jaraco-classes -newrelic==9.7.1 +more-itertools==10.3.0 + # via + # jaraco-classes + # jaraco-functools +newrelic==9.12.0 # via # -r requirements/test.txt # edx-django-utils -nh3==0.2.15 +nh3==0.2.18 # via readme-renderer -openai==1.14.2 +openai==1.35.14 # via -r requirements/test.txt -openedx-events==9.5.2 +openedx-events==9.11.0 # via -r requirements/test.txt -packaging==24.0 +packaging==24.1 # via # -r requirements/test.txt # build @@ -251,29 +280,35 @@ pbr==6.0.0 # stevedore pkginfo==1.10.0 # via twine -pluggy==1.4.0 +pluggy==1.5.0 # via # -r requirements/test.txt # pytest -psutil==5.9.8 +prompt-toolkit==3.0.47 + # via + # -r requirements/test.txt + # click-repl +psutil==6.0.0 # via # -r requirements/test.txt # edx-django-utils -pycparser==2.21 +pycparser==2.22 # via # -r requirements/test.txt # cffi -pydantic==2.6.4 +pydantic==2.8.2 # via # -r requirements/test.txt # openai -pydantic-core==2.16.3 +pydantic-core==2.20.1 # via # -r requirements/test.txt # pydantic pydata-sphinx-theme==0.14.4 - # via sphinx-book-theme -pygments==2.17.2 + # via + # -c requirements/constraints.txt + # sphinx-book-theme +pygments==2.18.0 # via # accessible-pygments # doc8 @@ -285,7 +320,7 @@ pyjwt==2.8.0 # via # -r requirements/test.txt # edx-rest-api-client -pymongo==3.13.0 +pymongo==4.8.0 # via # -r requirements/test.txt # edx-opaque-keys @@ -293,14 +328,14 @@ pynacl==1.5.0 # via # -r requirements/test.txt # edx-django-utils -pyproject-hooks==1.0.0 +pyproject-hooks==1.1.0 # via build -pytest==8.1.1 +pytest==8.2.2 # via # -r requirements/test.txt # pytest-cov # pytest-django -pytest-cov==4.1.0 +pytest-cov==5.0.0 # via -r requirements/test.txt pytest-django==4.8.0 # via -r requirements/test.txt @@ -308,6 +343,7 @@ python-dateutil==2.9.0.post0 # via # -r requirements/test.txt # botocore + # celery # faker python-slugify==8.0.4 # via @@ -316,8 +352,6 @@ python-slugify==8.0.4 pytz==2024.1 # via # -r requirements/test.txt - # babel - # celery # django # django-ses pyyaml==6.0.1 @@ -327,7 +361,7 @@ pyyaml==6.0.1 # responses readme-renderer==43.0 # via twine -requests==2.31.0 +requests==2.32.3 # via # -r requirements/test.txt # algoliasearch @@ -339,7 +373,7 @@ requests==2.31.0 # twine requests-toolbelt==1.0.0 # via twine -responses==0.25.0 +responses==0.25.3 # via -r requirements/test.txt restructuredtext-lint==1.4.0 # via doc8 @@ -347,13 +381,14 @@ rfc3986==2.0.0 # via twine rich==13.7.1 # via twine -s3transfer==0.10.1 +s3transfer==0.10.2 # via # -r requirements/test.txt # boto3 six==1.16.0 # via # -r requirements/test.txt + # edx-ccx-keys # python-dateutil slumber==0.7.1 # via @@ -373,11 +408,14 @@ soupsieve==2.5 # beautifulsoup4 sphinx==6.2.1 # via + # -c requirements/constraints.txt # -r requirements/doc.in # pydata-sphinx-theme # sphinx-book-theme sphinx-book-theme==1.0.1 - # via -r requirements/doc.in + # via + # -c requirements/constraints.txt + # -r requirements/doc.in sphinxcontrib-applehelp==1.0.4 # via # -c requirements/constraints.txt @@ -400,7 +438,7 @@ sphinxcontrib-serializinghtml==1.1.5 # via # -c requirements/constraints.txt # sphinx -sqlparse==0.4.4 +sqlparse==0.5.1 # via # -r requirements/test.txt # django @@ -411,7 +449,7 @@ stevedore==5.2.0 # doc8 # edx-django-utils # edx-opaque-keys -testfixtures==8.1.0 +testfixtures==8.3.0 # via -r requirements/test.txt text-unidecode==1.3 # via @@ -423,40 +461,45 @@ tomli==2.0.1 # build # coverage # doc8 - # pyproject-hooks # pytest -tqdm==4.66.2 +tqdm==4.66.4 # via # -r requirements/test.txt # openai -twine==5.0.0 +twine==5.1.1 # via -r requirements/doc.in -typing-extensions==4.10.0 +typing-extensions==4.12.2 # via # -r requirements/test.txt - # annotated-types # anyio # asgiref + # django-solo # edx-opaque-keys - # faker + # kombu # openai # pydantic # pydantic-core # pydata-sphinx-theme - # rich -urllib3==1.26.18 +tzdata==2024.1 + # via + # -r requirements/test.txt + # celery +urllib3==1.26.19 # via # -r requirements/test.txt # botocore # requests # responses # twine -vine==1.3.0 +vine==5.1.0 # via # -r requirements/test.txt # amqp # celery -zipp==3.18.1 + # kombu +wcwidth==0.2.13 # via - # importlib-metadata - # importlib-resources + # -r requirements/test.txt + # prompt-toolkit +zipp==3.19.2 + # via importlib-metadata diff --git a/requirements/pip-tools.txt b/requirements/pip-tools.txt index 8931dc2e..64b9b346 100644 --- a/requirements/pip-tools.txt +++ b/requirements/pip-tools.txt @@ -1,20 +1,20 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade # -build==1.1.1 +build==1.2.1 # via pip-tools click==8.1.7 # via pip-tools -importlib-metadata==7.1.0 +importlib-metadata==8.0.0 # via build -packaging==24.0 +packaging==24.1 # via build pip-tools==7.4.1 # via -r requirements/pip-tools.in -pyproject-hooks==1.0.0 +pyproject-hooks==1.1.0 # via # build # pip-tools @@ -22,10 +22,9 @@ tomli==2.0.1 # via # build # pip-tools - # pyproject-hooks wheel==0.43.0 # via pip-tools -zipp==3.18.1 +zipp==3.19.2 # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: diff --git a/requirements/pip.txt b/requirements/pip.txt index cf449024..55e9683c 100644 --- a/requirements/pip.txt +++ b/requirements/pip.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade @@ -8,7 +8,7 @@ wheel==0.43.0 # via -r requirements/pip.in # The following packages are considered to be unsafe in a requirements file: -pip==24.0 +pip==24.1.2 # via -r requirements/pip.in -setuptools==69.2.0 +setuptools==70.3.0 # via -r requirements/pip.in diff --git a/requirements/test.txt b/requirements/test.txt index 63431924..b69b430a 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,5 +1,5 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.9 # by the following command: # # make upgrade @@ -8,35 +8,31 @@ algoliasearch==1.20.0 # via # -c requirements/constraints.txt # -r requirements/base.in -amqp==2.6.1 +amqp==5.2.0 # via kombu -annotated-types==0.6.0 +annotated-types==0.7.0 # via pydantic -anyio==4.3.0 +anyio==4.4.0 # via # httpx # openai -asgiref==3.8.0 +asgiref==3.8.1 # via django attrs==23.2.0 # via openedx-events -backports-zoneinfo==0.2.1 - # via djangorestframework beautifulsoup4==4.12.3 # via -r requirements/base.in -billiard==3.6.4.0 +billiard==4.2.0 # via celery -boto3==1.34.67 +boto3==1.34.144 # via django-ses -botocore==1.34.67 +botocore==1.34.144 # via # boto3 # s3transfer -celery==4.4.7 - # via - # -c requirements/constraints.txt - # -r requirements/base.in -certifi==2024.2.2 +celery==5.4.0 + # via -r requirements/base.in +certifi==2024.7.4 # via # httpcore # httpx @@ -47,11 +43,21 @@ charset-normalizer==3.3.2 # via requests click==8.1.7 # via + # celery + # click-didyoumean + # click-plugins + # click-repl # code-annotations # edx-django-utils -code-annotations==1.7.0 +click-didyoumean==0.3.1 + # via celery +click-plugins==1.1.1 + # via celery +click-repl==0.3.0 + # via celery +code-annotations==1.8.0 # via -r requirements/test.in -coverage[toml]==7.4.4 +coverage[toml]==7.6.0 # via pytest-cov ddt==1.7.2 # via -r requirements/test.in @@ -76,128 +82,137 @@ django-crum==0.7.9 # via edx-django-utils django-filter==23.5 # via -r requirements/base.in -django-model-utils==4.4.0 +django-model-utils==4.5.1 # via -r requirements/base.in django-object-actions==4.2.0 # via -r requirements/base.in -django-ses==3.5.2 +django-ses==4.1.0 # via -r requirements/base.in -django-solo==2.2.0 +django-solo==2.3.0 # via -r requirements/base.in django-waffle==4.1.0 # via edx-django-utils -djangorestframework==3.15.0 +djangorestframework==3.15.1 # via -r requirements/base.in -edx-django-utils==5.11.0 +dnspython==2.6.1 + # via pymongo +edx-ccx-keys==1.3.0 + # via openedx-events +edx-django-utils==5.14.2 # via # -r requirements/base.in # edx-rest-api-client # openedx-events -edx-opaque-keys[django]==2.5.1 +edx-opaque-keys[django]==2.10.0 # via # -r requirements/base.in + # edx-ccx-keys # openedx-events -edx-rest-api-client==5.6.1 +edx-rest-api-client==5.7.1 # via -r requirements/base.in -exceptiongroup==1.2.0 +exceptiongroup==1.2.2 # via # anyio # pytest factory-boy==3.3.0 # via -r requirements/test.in -faker==24.3.0 +faker==26.0.0 # via # -r requirements/test.in # factory-boy -fastavro==1.9.4 +fastavro==1.9.5 # via openedx-events h11==0.14.0 # via httpcore -httpcore==1.0.4 +httpcore==1.0.5 # via httpx httpx==0.27.0 # via openai -idna==3.6 +idna==3.7 # via # anyio # httpx # requests iniconfig==2.0.0 # via pytest -jinja2==3.1.3 +jinja2==3.1.4 # via code-annotations jmespath==1.0.1 # via # boto3 # botocore -kombu==4.6.11 +kombu==5.3.7 # via celery markupsafe==2.1.5 # via jinja2 mock==5.1.0 # via -r requirements/test.in -newrelic==9.7.1 +newrelic==9.12.0 # via edx-django-utils -openai==1.14.2 +openai==1.35.14 # via -r requirements/base.in -openedx-events==9.5.2 +openedx-events==9.11.0 # via -r requirements/base.in -packaging==24.0 +packaging==24.1 # via pytest pbr==6.0.0 # via stevedore -pluggy==1.4.0 +pluggy==1.5.0 # via pytest -psutil==5.9.8 +prompt-toolkit==3.0.47 + # via click-repl +psutil==6.0.0 # via edx-django-utils -pycparser==2.21 +pycparser==2.22 # via cffi -pydantic==2.6.4 +pydantic==2.8.2 # via openai -pydantic-core==2.16.3 +pydantic-core==2.20.1 # via pydantic pyjwt==2.8.0 # via edx-rest-api-client -pymongo==3.13.0 +pymongo==4.8.0 # via edx-opaque-keys pynacl==1.5.0 # via edx-django-utils -pytest==8.1.1 +pytest==8.2.2 # via # pytest-cov # pytest-django -pytest-cov==4.1.0 +pytest-cov==5.0.0 # via -r requirements/test.in pytest-django==4.8.0 # via -r requirements/test.in python-dateutil==2.9.0.post0 # via # botocore + # celery # faker python-slugify==8.0.4 # via code-annotations pytz==2024.1 # via # -r requirements/base.in - # celery # django # django-ses pyyaml==6.0.1 # via # code-annotations # responses -requests==2.31.0 +requests==2.32.3 # via # algoliasearch # edx-rest-api-client # responses # slumber -responses==0.25.0 +responses==0.25.3 # via -r requirements/test.in -s3transfer==0.10.1 +s3transfer==0.10.2 # via boto3 six==1.16.0 - # via python-dateutil + # via + # edx-ccx-keys + # python-dateutil slumber==0.7.1 # via edx-rest-api-client sniffio==1.3.1 @@ -207,14 +222,14 @@ sniffio==1.3.1 # openai soupsieve==2.5 # via beautifulsoup4 -sqlparse==0.4.4 +sqlparse==0.5.1 # via django stevedore==5.2.0 # via # code-annotations # edx-django-utils # edx-opaque-keys -testfixtures==8.1.0 +testfixtures==8.3.0 # via -r requirements/test.in text-unidecode==1.3 # via python-slugify @@ -222,24 +237,29 @@ tomli==2.0.1 # via # coverage # pytest -tqdm==4.66.2 +tqdm==4.66.4 # via openai -typing-extensions==4.10.0 +typing-extensions==4.12.2 # via - # annotated-types # anyio # asgiref + # django-solo # edx-opaque-keys - # faker + # kombu # openai # pydantic # pydantic-core -urllib3==1.26.18 +tzdata==2024.1 + # via celery +urllib3==1.26.19 # via # botocore # requests # responses -vine==1.3.0 +vine==5.1.0 # via # amqp # celery + # kombu +wcwidth==0.2.13 + # via prompt-toolkit diff --git a/taxonomy/__init__.py b/taxonomy/__init__.py index 4d14b545..cca21f13 100644 --- a/taxonomy/__init__.py +++ b/taxonomy/__init__.py @@ -15,6 +15,6 @@ # 2. MINOR version when you add functionality in a backwards compatible manner, and # 3. PATCH version when you make backwards compatible bug fixes. # More details can be found at https://semver.org/ -__version__ = '1.50.0' +__version__ = '1.51.0' default_app_config = 'taxonomy.apps.TaxonomyConfig' # pylint: disable=invalid-name diff --git a/taxonomy/openai/client.py b/taxonomy/openai/client.py index 10521e6b..021d006f 100644 --- a/taxonomy/openai/client.py +++ b/taxonomy/openai/client.py @@ -1,25 +1,31 @@ -"""openai client""" +"""CHAT_COMPLETION_API client""" +import json +import logging -import openai +import requests 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 = settings.CHAT_COMPLETION_API + completion_endpoint_key = settings.CHAT_COMPLETION_API_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) + body = {'message_list': [{'role': 'assistant', 'content': prompt},]} + response = requests.post( + completion_endpoint, + headers=headers, + data=json.dumps(body), + timeout=(connect_timeout, read_timeout) ) - - content = response['choices'][0]['message']['content'] - return content + chat = response.json().get('content') + return chat diff --git a/test_settings.py b/test_settings.py index 2e7b88eb..282c66d2 100644 --- a/test_settings.py +++ b/test_settings.py @@ -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 = 'http://test.chat.ai' +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.' diff --git a/tests/openai/__init__.py b/tests/openai/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/openai/test_client.py b/tests/openai/test_client.py new file mode 100644 index 00000000..941574bd --- /dev/null +++ b/tests/openai/test_client.py @@ -0,0 +1,32 @@ +""" +Tests for chat completion client. +""" +import responses + +from django.conf import settings + +from taxonomy.openai.client import chat_completion +from test_utils.testcase import TaxonomyTestCase + + +class TestChatCompletionClient(TaxonomyTestCase): + """ + Validate chat_completion client. + """ + @responses.activate + def test_client(self): + """ + Test that the chat completion client works as expected. + """ + chat_prompt = 'how many courses are offered by edx in the data science area' + expected_chat_response = { + "role": "assistant", + "content": "edx offers 500 courses in the data science area" + } + responses.add( + method=responses.POST, + url=settings.CHAT_COMPLETION_API, + json=expected_chat_response, + ) + chat_response = chat_completion(chat_prompt) + self.assertEqual(chat_response, expected_chat_response['content']) diff --git a/tests/test_models.py b/tests/test_models.py index 3fb2d335..fb5c6065 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -346,30 +346,26 @@ 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 = { + "role": "assistant", + "content": 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) @@ -377,10 +373,7 @@ def test_chat_completion_is_called( # pylint: disable=invalid-name 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') diff --git a/tests/test_views.py b/tests/test_views.py index 62d28ece..388844b8 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -646,7 +646,7 @@ 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 @@ -654,18 +654,15 @@ def setUp(self) -> None: 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 = { + "role": "assistant", + "content": ai_response } query_params = {