Repository: CIME-Software/perplexipy (language: python)

Issue:
Implement a numbered list of available models for model selection
Let the user choose one, and override it from something like a named tuple or dictionary.


Discussion / hints:

Fix patch:
diff --git a/perplexipy/__init__.py b/perplexipy/__init__.py
index 60869d2..0aa2033 100644
--- a/perplexipy/__init__.py
+++ b/perplexipy/__init__.py
@@ -1,9 +1,11 @@
 # See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
 
 
-__VERSION__ = '0.0.5'
+__VERSION__ = '0.0.6'
 
 
+from collections import namedtuple
+
 from dotenv import load_dotenv
 from openai import OpenAI
 
@@ -59,6 +61,13 @@ def __next__(self):
         return result
 
 
+"""
+Immutable dictionary-like object of a model's capabilities.  Use `_asDict()` if
+dictionary manipulation is required.
+"""
+ModelInfo = namedtuple('ModelInfo', [ 'parameterCount', 'contextLength', 'modelType', 'availability', ])
+
+
 class PerplexityClient:
     """
     PerplexityClient objects encapsulate all the API functionality.  They can be
@@ -102,7 +111,7 @@ def __init__(self, key = PERPLEXITY_API_KEY, endpoint = PERPLEXITY_API_URL):
         self._endpoint = endpoint
         self._key = key
         self._role = PERPLEXITY_DEFAULT_ROLE
-        self.model = PERPLEXITY_DEFAULT_MODEL
+        self._model = PERPLEXITY_DEFAULT_MODEL
         self._client = OpenAI(
             api_key = self._key,
             base_url = self._endpoint,
@@ -230,3 +239,49 @@ def queryStreamable(self, query: str) -> Responses:
 
         return Responses(response)
 
+
+    @property
+    def models(self):
+        """
+        Provide a dictionary of the models supported by Perplexity listed in:
+
+        https://docs.perplexity.ai/docs/model-cards
+
+        Returns
+        -------
+        A dictionary of supported models as the key, with a `perplexypy.ModelInfo`
+        named tuple with the model capabilities description.  The model
+        information attributes are:
+
+        - `parameterCount`
+        - `contextLength`
+        - `modelType`
+        - `availability`
+        """
+        supportedModels = {
+            'codellama-70b-instruct': ModelInfo('70B', 16384, 'chat completion', 'open source',),
+            'mistral-7b-instruct': ModelInfo('7B', 16384, 'chat completion', 'open source',),
+            'mixtral-8x7b-instruct': ModelInfo('8x7B', 16384, 'chat completion', 'open source',),
+            'sonar-medium-chat': ModelInfo('8x7B', 16348, 'chat completion', 'Perplexity',),
+            'sonar-medium-online': ModelInfo('8x7B', 12000, 'chat completion', 'Perplexity',),
+            'sonar-small-chat': ModelInfo('7B', 16384, 'chat completion', 'Perplexity',),
+            'sonar-small-online': ModelInfo('7B', 12000, 'chat completion', 'Perplexity',),
+        }
+
+        return supportedModels
+
+
+    @property
+    def model(self) -> str:
+        return self._model
+
+    @model.setter
+    def model(self, value: str):
+        """
+        """
+        models = self.models.keys()
+        if value not in models:
+            raise PerplexityClientError('value = %s error; supported models: %s' % (value, ', '.join(models)))
+
+        self._model = value
+


Test patch:
diff --git a/tests/perplexipy-test.py b/tests/perplexipy-test.py
index 3035b73..c680a55 100644
--- a/tests/perplexipy-test.py
+++ b/tests/perplexipy-test.py
@@ -50,14 +50,8 @@ def test_PerplexityClient_query(testClient):
 
 
 def test_PerplexityClient_bogusModel(testClient):
-    model = testClient.model
-    testClient.model = TEST_BOGUS_MODEL
     with pytest.raises(Exception):
-        testClient.query(TEST_QUERY)
-
-    testClient.model = model
-    result = testClient.query(TEST_QUERY)
-    assert result
+        testClient.model = TEST_BOGUS_MODEL
 
 
 def test_PerplexityClient_queryBatch(testClient):
@@ -81,6 +75,13 @@ def test_PerplexityClient_queryStreamable(testClient):
         testClient.queryStreamable(None)
 
 
+def test_PerplexityClient_models(testClient):
+    model = testClient.model
+    models = testClient.models
+    assert isinstance(models, dict)
+    assert model in models.keys()
+
+
 # _testClient = PerplexityClient()
-# test_PerplexityClient_queryStreamable(_testClient)
+# test_PerplexityClient_bogusModel(_testClient)