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

Issue:
Create the pdoc documentation and github.io site for it, for completness
Create the pdoc documentation and github.io site for it, for completness.


Discussion / hints:

Fix patch:
diff --git a/LICENSE.txt b/LICENSE.txt
index 9fea731..4c8721d 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,6 +1,6 @@
 BSD 3-Clause License
 
-Copyright (c) 2024, CIME Software
+perplexipy - copyright (c) 2024, CIME Software
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
diff --git a/Makefile b/Makefile
index c755514..4a1bd9c 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@
 
 SHELL=/bin/bash
 
+API_DOC_DIR="./docs"
 BUILD=./build
 DEVPI_HOST=$(shell cat devpi-hostname.txt)
 DEVPI_PASSWORD=$(shell cat ./devpi-password.txt)
@@ -19,6 +20,7 @@ VERSION=$(shell echo "from $(PACKAGE) import __VERSION__; print(__VERSION__)" |
 all: ALWAYS
 	make test
 	make manpage
+	make docs
 	make package
 
 
@@ -30,6 +32,7 @@ clean:
 	rm -Rfv $$(find tests | awk '/__pycache__$$/')
 	rm -Rfv $$(find . | awk '/.ipynb_checkpoints/')
 	rm -Rfv ./.pytest_cache
+	rm -Rf $(API_DOC_DIR)/*
 	mkdir -p ./dist
 	pushd ./dist ; pip uninstall -y $(PACKAGE)==$(VERSION) || true ; popd
 
@@ -42,6 +45,13 @@ devpi:
 	@[[ -e "pip.conf-bak" ]] && rm -f "pip.conf-bak"
 
 
+docs: ALWAYS
+	mkdir -p $(API_DOC_DIR)
+	@[[ -e ".env" ]] && mv ".env" "_env"
+	VERSION="$(VERSION)" pdoc --logo="https://images2.imgbox.com/57/94/AsI1WSfy_o.png" --favicon="https://cime.net/upload_area/favicon.ico" -n -o $(API_DOC_DIR) -t ./resources $(PACKAGE)
+	@[[ -e "_env" ]] && mv "_env" ".env"
+
+
 install:
 	pip install -U $(PACKAGE)==$(VERSION)
 	pip list | awk 'NR < 3 { print; } /$(PACKAGE)/'
@@ -96,6 +106,8 @@ test: ALWAYS
 	@echo "Version = $(VERSION)"
 	@make local
 	pytest -v ./tests/$(PACKAGE)-test.py
+	pytest -v ./tests/errors-test.py
+	pytest -v ./tests/responses-test.py
 	pip uninstall -y $(PACKAGE)==$(VERSION) || true
 	rm -Rfv $$(find $(PACKAGE)/ | awk '/__pycache__$$/')
 	rm -Rfv $$(find tests | awk '/__pycache__$$/')
diff --git a/README.md b/README.md
index b895f2e..1924bd7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-% perplexipy(3) Version 0.0.6 | Perplexity AI high level API documentation
+% perplexipy(3) Version 0.0.7 | Perplexity AI high level API documentation
 
 Name
 ====
@@ -20,14 +20,22 @@ Description
 ===========
 **perplexipy** is a high-level, convenience library for interacting with the
 Perplexity API from any Python 3.9+ application.  The library aims to simplify
-all interactions with Perplexity models by encapsulating all the implementation
+interactions with Perplexity models by encapsulating all the implementation
 details of the lower level OpenAI API.  All interaction between the code and
-this library occurs in the form of string and native Python objects.
+this library occurs in the form of string and native Python objects, not
+OpenAPI / Swagger mapped objects.
 
-**perplexipy** is implemented from a combination of the Perplexity AI and the
-OpenAI documentation.  API semantics follow the "literate programming" workflow,
+**perplexipy** implements a combination of the Perplexity AI and the
+OpenAI outputs.  API semantics follow the "literate programming" workflow,
 and attempt to make the resulting code as simple to follow as possible.
 
+<a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a> is an
+AI-powered search engine that uses natural language
+processing and machine learning to provide accurate and comprehensive answers to
+end-user queries.  It can be argued that it outperforms OpenAI's offerings in
+accuracy and responsiveness.  **perplexypi** enables the creation of Python
+programs and tools that leverage the power of Perplexity AI.
+
 
 Documentation
 =============
@@ -36,8 +44,8 @@ These documents encompass all information about **perplexipy**:
 - This README file, hosted in the **[perplexipy](https://github.com/CIME-Software/perplexipy)**
   project on GitHub and exported to the PyPI project page
 - A `man` page autogenerated from this README file, `perplexipy.3`
-- The complete **perplexipy API reference**
-- The **using-perplexipy.ipynb** tutorial notebook
+- The complete **perplexipy API reference** on GitHub Pages
+- The **using-perplexipy.ipynb** tutorial notebook - see: https://github.com/CIME-Software/perplexipy/issues/18
 
 The `man` page can be generated from the source distribution using this command:
 
@@ -47,7 +55,7 @@ make manpage
 
 The output will reside in:  `./manpages/perplexipy.3`.  The `man` page isn't
 included in the Python package wheel because there's no accepted standard
-installation that's cross-compatible with all supported operating systems and
+installation that's cross-compatible among all supported operating systems and
 distributions.
 
 
@@ -83,7 +91,7 @@ print(client.query('Brief answer:  greet the world in Swedish.'))
 
 Usage
 =====
-See the **using-perplexipy.ipynb** notebook for a richer example of the API's
+See the **using-perplexipy.ipynb** (https://github.com/CIME-Software/perplexipy/issues/18) notebook for a richer example of the API's
 capabilities.
 
 In general:
@@ -123,10 +131,16 @@ Async usage
 Not supported at this time.
 
 
+License
+=======
+The **perplexipy** package, documentation and examples are licensed under the
+[BSD-3 open source license](https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt).
+
+
 See also
 ========
-- **openai** - https://pipy.org/project/openai
-- https://www.perplexity.ai/
+- PyPI:  <a href='https://pipy.org/project/openai' target='_blank'>openai</a>
+- <a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a>
 
 
 Caveats
diff --git a/dev-tools.txt b/dev-tools.txt
index 060dd41..9094d5c 100644
--- a/dev-tools.txt
+++ b/dev-tools.txt
@@ -1,4 +1,6 @@
 devpi-client
+pdoc
 ptpython
 pudb
+pylint
 pytest
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..a472dc8
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta http-equiv="refresh" content="0; url=./perplexipy.html"/>
+</head>
+</html>
diff --git a/docs/perplexipy.html b/docs/perplexipy.html
new file mode 100644
index 0000000..27f057d
--- /dev/null
+++ b/docs/perplexipy.html
@@ -0,0 +1,1567 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="generator" content="pdoc 14.4.0"/>
+    <title>perplexipy API documentation</title>
+            <link rel="icon" href="https://cime.net/upload_area/favicon.ico"/>
+
+    <style>/*! * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}</style>
+    <style>/*! syntax-highlighting.css */pre{line-height:125%;}span.linenos{color:inherit; background-color:transparent; padding-left:5px; padding-right:20px;}.pdoc-code .hll{background-color:#ffffcc}.pdoc-code{background:#f8f8f8;}.pdoc-code .c{color:#3D7B7B; font-style:italic}.pdoc-code .err{border:1px solid #FF0000}.pdoc-code .k{color:#008000; font-weight:bold}.pdoc-code .o{color:#666666}.pdoc-code .ch{color:#3D7B7B; font-style:italic}.pdoc-code .cm{color:#3D7B7B; font-style:italic}.pdoc-code .cp{color:#9C6500}.pdoc-code .cpf{color:#3D7B7B; font-style:italic}.pdoc-code .c1{color:#3D7B7B; font-style:italic}.pdoc-code .cs{color:#3D7B7B; font-style:italic}.pdoc-code .gd{color:#A00000}.pdoc-code .ge{font-style:italic}.pdoc-code .gr{color:#E40000}.pdoc-code .gh{color:#000080; font-weight:bold}.pdoc-code .gi{color:#008400}.pdoc-code .go{color:#717171}.pdoc-code .gp{color:#000080; font-weight:bold}.pdoc-code .gs{font-weight:bold}.pdoc-code .gu{color:#800080; font-weight:bold}.pdoc-code .gt{color:#0044DD}.pdoc-code .kc{color:#008000; font-weight:bold}.pdoc-code .kd{color:#008000; font-weight:bold}.pdoc-code .kn{color:#008000; font-weight:bold}.pdoc-code .kp{color:#008000}.pdoc-code .kr{color:#008000; font-weight:bold}.pdoc-code .kt{color:#B00040}.pdoc-code .m{color:#666666}.pdoc-code .s{color:#BA2121}.pdoc-code .na{color:#687822}.pdoc-code .nb{color:#008000}.pdoc-code .nc{color:#0000FF; font-weight:bold}.pdoc-code .no{color:#880000}.pdoc-code .nd{color:#AA22FF}.pdoc-code .ni{color:#717171; font-weight:bold}.pdoc-code .ne{color:#CB3F38; font-weight:bold}.pdoc-code .nf{color:#0000FF}.pdoc-code .nl{color:#767600}.pdoc-code .nn{color:#0000FF; font-weight:bold}.pdoc-code .nt{color:#008000; font-weight:bold}.pdoc-code .nv{color:#19177C}.pdoc-code .ow{color:#AA22FF; font-weight:bold}.pdoc-code .w{color:#bbbbbb}.pdoc-code .mb{color:#666666}.pdoc-code .mf{color:#666666}.pdoc-code .mh{color:#666666}.pdoc-code .mi{color:#666666}.pdoc-code .mo{color:#666666}.pdoc-code .sa{color:#BA2121}.pdoc-code .sb{color:#BA2121}.pdoc-code .sc{color:#BA2121}.pdoc-code .dl{color:#BA2121}.pdoc-code .sd{color:#BA2121; font-style:italic}.pdoc-code .s2{color:#BA2121}.pdoc-code .se{color:#AA5D1F; font-weight:bold}.pdoc-code .sh{color:#BA2121}.pdoc-code .si{color:#A45A77; font-weight:bold}.pdoc-code .sx{color:#008000}.pdoc-code .sr{color:#A45A77}.pdoc-code .s1{color:#BA2121}.pdoc-code .ss{color:#19177C}.pdoc-code .bp{color:#008000}.pdoc-code .fm{color:#0000FF}.pdoc-code .vc{color:#19177C}.pdoc-code .vg{color:#19177C}.pdoc-code .vi{color:#19177C}.pdoc-code .vm{color:#19177C}.pdoc-code .il{color:#666666}</style>
+    <style>/*! theme.css */:root{--pdoc-background:#fff;}.pdoc{--text:#212529;--muted:#6c757d;--link:#3660a5;--link-hover:#1659c5;--code:#f8f8f8;--active:#fff598;--accent:#eee;--accent2:#c1c1c1;--nav-hover:rgba(255, 255, 255, 0.5);--name:#0066BB;--def:#008800;--annotation:#007020;}</style>
+    <style>/*! layout.css */html, body{width:100%;height:100%;}html, main{scroll-behavior:smooth;}body{background-color:var(--pdoc-background);}@media (max-width:769px){#navtoggle{cursor:pointer;position:absolute;width:50px;height:40px;top:1rem;right:1rem;border-color:var(--text);color:var(--text);display:flex;opacity:0.8;z-index:999;}#navtoggle:hover{opacity:1;}#togglestate + div{display:none;}#togglestate:checked + div{display:inherit;}main, header{padding:2rem 3vw;}header + main{margin-top:-3rem;}.git-button{display:none !important;}nav input[type="search"]{max-width:77%;}nav input[type="search"]:first-child{margin-top:-6px;}nav input[type="search"]:valid ~ *{display:none !important;}}@media (min-width:770px){:root{--sidebar-width:clamp(12.5rem, 28vw, 22rem);}nav{position:fixed;overflow:auto;height:100vh;width:var(--sidebar-width);}main, header{padding:3rem 2rem 3rem calc(var(--sidebar-width) + 3rem);width:calc(54rem + var(--sidebar-width));max-width:100%;}header + main{margin-top:-4rem;}#navtoggle{display:none;}}#togglestate{position:absolute;height:0;opacity:0;}nav.pdoc{--pad:clamp(0.5rem, 2vw, 1.75rem);--indent:1.5rem;background-color:var(--accent);border-right:1px solid var(--accent2);box-shadow:0 0 20px rgba(50, 50, 50, .2) inset;padding:0 0 0 var(--pad);overflow-wrap:anywhere;scrollbar-width:thin; scrollbar-color:var(--accent2) transparent; z-index:1}nav.pdoc::-webkit-scrollbar{width:.4rem; }nav.pdoc::-webkit-scrollbar-thumb{background-color:var(--accent2); }nav.pdoc > div{padding:var(--pad) 0;}nav.pdoc .module-list-button{display:inline-flex;align-items:center;color:var(--text);border-color:var(--muted);margin-bottom:1rem;}nav.pdoc .module-list-button:hover{border-color:var(--text);}nav.pdoc input[type=search]{display:block;outline-offset:0;width:calc(100% - var(--pad));}nav.pdoc .logo{max-width:calc(100% - var(--pad));max-height:35vh;display:block;margin:0 auto 1rem;transform:translate(calc(-.5 * var(--pad)), 0);}nav.pdoc ul{list-style:none;padding-left:0;}nav.pdoc > div > ul{margin-left:calc(0px - var(--pad));}nav.pdoc li a{padding:.2rem 0 .2rem calc(var(--pad) + var(--indent));}nav.pdoc > div > ul > li > a{padding-left:var(--pad);}nav.pdoc li{transition:all 100ms;}nav.pdoc li:hover{background-color:var(--nav-hover);}nav.pdoc a, nav.pdoc a:hover{color:var(--text);}nav.pdoc a{display:block;}nav.pdoc > h2:first-of-type{margin-top:1.5rem;}nav.pdoc .class:before{content:"class ";color:var(--muted);}nav.pdoc .function:after{content:"()";color:var(--muted);}nav.pdoc footer:before{content:"";display:block;width:calc(100% - var(--pad));border-top:solid var(--accent2) 1px;margin-top:1.5rem;padding-top:.5rem;}nav.pdoc footer{font-size:small;}</style>
+    <style>/*! content.css */.pdoc{color:var(--text);box-sizing:border-box;line-height:1.5;background:none;}.pdoc .pdoc-button{cursor:pointer;display:inline-block;border:solid black 1px;border-radius:2px;font-size:.75rem;padding:calc(0.5em - 1px) 1em;transition:100ms all;}.pdoc .pdoc-alert{padding:1rem 1rem 1rem calc(1.5rem + 24px);border:1px solid transparent;border-radius:.25rem;background-repeat:no-repeat;background-position:1rem center;margin-bottom:1rem;}.pdoc .pdoc-alert > *:last-child{margin-bottom:0;}.pdoc .pdoc-alert-note {color:#084298;background-color:#cfe2ff;border-color:#b6d4fe;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23084298%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8%2016A8%208%200%201%200%208%200a8%208%200%200%200%200%2016zm.93-9.412-1%204.705c-.07.34.029.533.304.533.194%200%20.487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703%200-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381%202.29-.287zM8%205.5a1%201%200%201%201%200-2%201%201%200%200%201%200%202z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23664d03%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8.982%201.566a1.13%201.13%200%200%200-1.96%200L.165%2013.233c-.457.778.091%201.767.98%201.767h13.713c.889%200%201.438-.99.98-1.767L8.982%201.566zM8%205c.535%200%20.954.462.9.995l-.35%203.507a.552.552%200%200%201-1.1%200L7.1%205.995A.905.905%200%200%201%208%205zm.002%206a1%201%200%201%201%200%202%201%201%200%200%201%200-2z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23842029%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M5.52.359A.5.5%200%200%201%206%200h4a.5.5%200%200%201%20.474.658L8.694%206H12.5a.5.5%200%200%201%20.395.807l-7%209a.5.5%200%200%201-.873-.454L6.823%209.5H3.5a.5.5%200%200%201-.48-.641l2.5-8.5z%22/%3E%3C/svg%3E");}.pdoc .visually-hidden{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important;}.pdoc h1, .pdoc h2, .pdoc h3{font-weight:300;margin:.3em 0;padding:.2em 0;}.pdoc > section:not(.module-info) h1{font-size:1.5rem;font-weight:500;}.pdoc > section:not(.module-info) h2{font-size:1.4rem;font-weight:500;}.pdoc > section:not(.module-info) h3{font-size:1.3rem;font-weight:500;}.pdoc > section:not(.module-info) h4{font-size:1.2rem;}.pdoc > section:not(.module-info) h5{font-size:1.1rem;}.pdoc a{text-decoration:none;color:var(--link);}.pdoc a:hover{color:var(--link-hover);}.pdoc blockquote{margin-left:2rem;}.pdoc pre{border-top:1px solid var(--accent2);border-bottom:1px solid var(--accent2);margin-top:0;margin-bottom:1em;padding:.5rem 0 .5rem .5rem;overflow-x:auto;background-color:var(--code);}.pdoc code{color:var(--text);padding:.2em .4em;margin:0;font-size:85%;background-color:var(--accent);border-radius:6px;}.pdoc a > code{color:inherit;}.pdoc pre > code{display:inline-block;font-size:inherit;background:none;border:none;padding:0;}.pdoc > section:not(.module-info){margin-bottom:1.5rem;}.pdoc .modulename{margin-top:0;font-weight:bold;}.pdoc .modulename a{color:var(--link);transition:100ms all;}.pdoc .git-button{float:right;border:solid var(--link) 1px;}.pdoc .git-button:hover{background-color:var(--link);color:var(--pdoc-background);}.view-source-toggle-state,.view-source-toggle-state ~ .pdoc-code{display:none;}.view-source-toggle-state:checked ~ .pdoc-code{display:block;}.view-source-button{display:inline-block;float:right;font-size:.75rem;line-height:1.5rem;color:var(--muted);padding:0 .4rem 0 1.3rem;cursor:pointer;text-indent:-2px;}.view-source-button > span{visibility:hidden;}.module-info .view-source-button{float:none;display:flex;justify-content:flex-end;margin:-1.2rem .4rem -.2rem 0;}.view-source-button::before{position:absolute;content:"View Source";display:list-item;list-style-type:disclosure-closed;}.view-source-toggle-state:checked ~ .attr .view-source-button::before,.view-source-toggle-state:checked ~ .view-source-button::before{list-style-type:disclosure-open;}.pdoc .docstring{margin-bottom:1.5rem;}.pdoc section:not(.module-info) .docstring{margin-left:clamp(0rem, 5vw - 2rem, 1rem);}.pdoc .docstring .pdoc-code{margin-left:1em;margin-right:1em;}.pdoc h1:target,.pdoc h2:target,.pdoc h3:target,.pdoc h4:target,.pdoc h5:target,.pdoc h6:target,.pdoc .pdoc-code > pre > span:target{background-color:var(--active);box-shadow:-1rem 0 0 0 var(--active);}.pdoc .pdoc-code > pre > span:target{display:block;}.pdoc div:target > .attr,.pdoc section:target > .attr,.pdoc dd:target > a{background-color:var(--active);}.pdoc *{scroll-margin:2rem;}.pdoc .pdoc-code .linenos{user-select:none;}.pdoc .attr:hover{filter:contrast(0.95);}.pdoc section, .pdoc .classattr{position:relative;}.pdoc .headerlink{--width:clamp(1rem, 3vw, 2rem);position:absolute;top:0;left:calc(0rem - var(--width));transition:all 100ms ease-in-out;opacity:0;}.pdoc .headerlink::before{content:"#";display:block;text-align:center;width:var(--width);height:2.3rem;line-height:2.3rem;font-size:1.5rem;}.pdoc .attr:hover ~ .headerlink,.pdoc *:target > .headerlink,.pdoc .headerlink:hover{opacity:1;}.pdoc .attr{display:block;margin:.5rem 0 .5rem;padding:.4rem .4rem .4rem 1rem;background-color:var(--accent);overflow-x:auto;}.pdoc .classattr{margin-left:2rem;}.pdoc .name{color:var(--name);font-weight:bold;}.pdoc .def{color:var(--def);font-weight:bold;}.pdoc .signature{background-color:transparent;}.pdoc .param, .pdoc .return-annotation{white-space:pre;}.pdoc .signature.multiline .param{display:block;}.pdoc .signature.condensed .param{display:inline-block;}.pdoc .annotation{color:var(--annotation);}.pdoc .view-value-toggle-state,.pdoc .view-value-toggle-state ~ .default_value{display:none;}.pdoc .view-value-toggle-state:checked ~ .default_value{display:inherit;}.pdoc .view-value-button{font-size:.5rem;vertical-align:middle;border-style:dashed;margin-top:-0.1rem;}.pdoc .view-value-button:hover{background:white;}.pdoc .view-value-button::before{content:"show";text-align:center;width:2.2em;display:inline-block;}.pdoc .view-value-toggle-state:checked ~ .view-value-button::before{content:"hide";}.pdoc .inherited{margin-left:2rem;}.pdoc .inherited dt{font-weight:700;}.pdoc .inherited dt, .pdoc .inherited dd{display:inline;margin-left:0;margin-bottom:.5rem;}.pdoc .inherited dd:not(:last-child):after{content:", ";}.pdoc .inherited .class:before{content:"class ";}.pdoc .inherited .function a:after{content:"()";}.pdoc .search-result .docstring{overflow:auto;max-height:25vh;}.pdoc .search-result.focused > .attr{background-color:var(--active);}.pdoc .attribution{margin-top:2rem;display:block;opacity:0.5;transition:all 200ms;filter:grayscale(100%);}.pdoc .attribution:hover{opacity:1;filter:grayscale(0%);}.pdoc .attribution img{margin-left:5px;height:35px;vertical-align:middle;width:70px;transition:all 200ms;}.pdoc table{display:block;width:max-content;max-width:100%;overflow:auto;margin-bottom:1rem;}.pdoc table th{font-weight:600;}.pdoc table th, .pdoc table td{padding:6px 13px;border:1px solid var(--accent2);}</style>
+    <style>/*! custom.css */</style></head>
+<body>
+    <nav class="pdoc">
+        <label id="navtoggle" for="togglestate" class="pdoc-button"><svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke-linecap='round' stroke="currentColor" stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg></label>
+        <input id="togglestate" type="checkbox" aria-hidden="true" tabindex="-1">
+        <div>
+            <img src="https://images2.imgbox.com/57/94/AsI1WSfy_o.png" class="logo" alt="project logo"/>
+
+            <input type="search" placeholder="Search..." role="searchbox" aria-label="search"
+                   pattern=".+" required>
+
+            <h2>Contents</h2>
+            <ul>
+  <li><a href="#name">Name</a></li>
+  <li><a href="#synopsis">Synopsis</a></li>
+  <li><a href="#description">Description</a></li>
+  <li><a href="#documentation">Documentation</a></li>
+  <li><a href="#installation">Installation</a></li>
+  <li><a href="#api-key">API key</a></li>
+  <li><a href="#usage">Usage</a></li>
+  <li><a href="#async-usage">Async usage</a></li>
+  <li><a href="#license">License</a></li>
+  <li><a href="#see-also">See also</a></li>
+  <li><a href="#caveats">Caveats</a></li>
+  <li><a href="#bugs">Bugs</a></li>
+  <li><a href="#perplexipy-api-documentation">perplexipy API Documentation</a></li>
+</ul>
+
+
+            <h2>Submodules</h2>
+            <ul>
+                    <li><a href="perplexipy/errors.html">errors</a></li>
+                    <li><a href="perplexipy/responses.html">responses</a></li>
+            </ul>
+
+            <h2>API Documentation</h2>
+                <ul class="memberlist">
+            <li>
+                    <a class="variable" href="#PERPLEXITY_API_KEY">PERPLEXITY_API_KEY</a>
+            </li>
+            <li>
+                    <a class="variable" href="#PERPLEXITY_API_URL">PERPLEXITY_API_URL</a>
+            </li>
+            <li>
+                    <a class="variable" href="#PERPLEXITY_DEFAULT_MODEL">PERPLEXITY_DEFAULT_MODEL</a>
+            </li>
+            <li>
+                    <a class="variable" href="#PERPLEXITY_DEFAULT_ROLE">PERPLEXITY_DEFAULT_ROLE</a>
+            </li>
+            <li>
+                    <a class="variable" href="#PERPLEXITY_TIMEOUT">PERPLEXITY_TIMEOUT</a>
+            </li>
+            <li>
+                    <a class="class" href="#ModelInfo">ModelInfo</a>
+                            <ul class="memberlist">
+                        <li>
+                                <a class="function" href="#ModelInfo.__init__">ModelInfo</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#ModelInfo.parameterCount">parameterCount</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#ModelInfo.contextLength">contextLength</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#ModelInfo.modelType">modelType</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#ModelInfo.availability">availability</a>
+                        </li>
+                </ul>
+
+            </li>
+            <li>
+                    <a class="class" href="#PerplexityClient">PerplexityClient</a>
+                            <ul class="memberlist">
+                        <li>
+                                <a class="function" href="#PerplexityClient.__init__">PerplexityClient</a>
+                        </li>
+                        <li>
+                                <a class="function" href="#PerplexityClient.query">query</a>
+                        </li>
+                        <li>
+                                <a class="function" href="#PerplexityClient.queryBatch">queryBatch</a>
+                        </li>
+                        <li>
+                                <a class="function" href="#PerplexityClient.queryStreamable">queryStreamable</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#PerplexityClient.models">models</a>
+                        </li>
+                        <li>
+                                <a class="variable" href="#PerplexityClient.model">model</a>
+                        </li>
+                </ul>
+
+            </li>
+    </ul>
+
+
+
+        <a class="attribution" title="pdoc: Python API documentation generator" href="https://pdoc.dev" target="_blank">
+            built with <span class="visually-hidden">pdoc</span><img
+                alt="pdoc logo"
+                src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20role%3D%22img%22%20aria-label%3D%22pdoc%20logo%22%20width%3D%22300%22%20height%3D%22150%22%20viewBox%3D%22-1%200%2060%2030%22%3E%3Ctitle%3Epdoc%3C/title%3E%3Cpath%20d%3D%22M29.621%2021.293c-.011-.273-.214-.475-.511-.481a.5.5%200%200%200-.489.503l-.044%201.393c-.097.551-.695%201.215-1.566%201.704-.577.428-1.306.486-2.193.182-1.426-.617-2.467-1.654-3.304-2.487l-.173-.172a3.43%203.43%200%200%200-.365-.306.49.49%200%200%200-.286-.196c-1.718-1.06-4.931-1.47-7.353.191l-.219.15c-1.707%201.187-3.413%202.131-4.328%201.03-.02-.027-.49-.685-.141-1.763.233-.721.546-2.408.772-4.076.042-.09.067-.187.046-.288.166-1.347.277-2.625.241-3.351%201.378-1.008%202.271-2.586%202.271-4.362%200-.976-.272-1.935-.788-2.774-.057-.094-.122-.18-.184-.268.033-.167.052-.339.052-.516%200-1.477-1.202-2.679-2.679-2.679-.791%200-1.496.352-1.987.9a6.3%206.3%200%200%200-1.001.029c-.492-.564-1.207-.929-2.012-.929-1.477%200-2.679%201.202-2.679%202.679A2.65%202.65%200%200%200%20.97%206.554c-.383.747-.595%201.572-.595%202.41%200%202.311%201.507%204.29%203.635%205.107-.037.699-.147%202.27-.423%203.294l-.137.461c-.622%202.042-2.515%208.257%201.727%2010.643%201.614.908%203.06%201.248%204.317%201.248%202.665%200%204.492-1.524%205.322-2.401%201.476-1.559%202.886-1.854%206.491.82%201.877%201.393%203.514%201.753%204.861%201.068%202.223-1.713%202.811-3.867%203.399-6.374.077-.846.056-1.469.054-1.537zm-4.835%204.313c-.054.305-.156.586-.242.629-.034-.007-.131-.022-.307-.157-.145-.111-.314-.478-.456-.908.221.121.432.25.675.355.115.039.219.051.33.081zm-2.251-1.238c-.05.33-.158.648-.252.694-.022.001-.125-.018-.307-.157-.217-.166-.488-.906-.639-1.573.358.344.754.693%201.198%201.036zm-3.887-2.337c-.006-.116-.018-.231-.041-.342.635.145%201.189.368%201.599.625.097.231.166.481.174.642-.03.049-.055.101-.067.158-.046.013-.128.026-.298.004-.278-.037-.901-.57-1.367-1.087zm-1.127-.497c.116.306.176.625.12.71-.019.014-.117.045-.345.016-.206-.027-.604-.332-.986-.695.41-.051.816-.056%201.211-.031zm-4.535%201.535c.209.22.379.47.358.598-.006.041-.088.138-.351.234-.144.055-.539-.063-.979-.259a11.66%2011.66%200%200%200%20.972-.573zm.983-.664c.359-.237.738-.418%201.126-.554.25.237.479.548.457.694-.006.042-.087.138-.351.235-.174.064-.694-.105-1.232-.375zm-3.381%201.794c-.022.145-.061.29-.149.401-.133.166-.358.248-.69.251h-.002c-.133%200-.306-.26-.45-.621.417.091.854.07%201.291-.031zm-2.066-8.077a4.78%204.78%200%200%201-.775-.584c.172-.115.505-.254.88-.378l-.105.962zm-.331%202.302a10.32%2010.32%200%200%201-.828-.502c.202-.143.576-.328.984-.49l-.156.992zm-.45%202.157l-.701-.403c.214-.115.536-.249.891-.376a11.57%2011.57%200%200%201-.19.779zm-.181%201.716c.064.398.194.702.298.893-.194-.051-.435-.162-.736-.398.061-.119.224-.3.438-.495zM8.87%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zm-.735-.389a1.15%201.15%200%200%200-.314.783%201.16%201.16%200%200%200%201.162%201.162c.457%200%20.842-.27%201.032-.653.026.117.042.238.042.362a1.68%201.68%200%200%201-1.679%201.679%201.68%201.68%200%200%201-1.679-1.679c0-.843.626-1.535%201.436-1.654zM5.059%205.406A1.68%201.68%200%200%201%203.38%207.085a1.68%201.68%200%200%201-1.679-1.679c0-.037.009-.072.011-.109.21.3.541.508.935.508a1.16%201.16%200%200%200%201.162-1.162%201.14%201.14%200%200%200-.474-.912c.015%200%20.03-.005.045-.005.926.001%201.679.754%201.679%201.68zM3.198%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zM1.375%208.964c0-.52.103-1.035.288-1.52.466.394%201.06.64%201.717.64%201.144%200%202.116-.725%202.499-1.738.383%201.012%201.355%201.738%202.499%201.738.867%200%201.631-.421%202.121-1.062.307.605.478%201.267.478%201.942%200%202.486-2.153%204.51-4.801%204.51s-4.801-2.023-4.801-4.51zm24.342%2019.349c-.985.498-2.267.168-3.813-.979-3.073-2.281-5.453-3.199-7.813-.705-1.315%201.391-4.163%203.365-8.423.97-3.174-1.786-2.239-6.266-1.261-9.479l.146-.492c.276-1.02.395-2.457.444-3.268a6.11%206.11%200%200%200%201.18.115%206.01%206.01%200%200%200%202.536-.562l-.006.175c-.802.215-1.848.612-2.021%201.25-.079.295.021.601.274.837.219.203.415.364.598.501-.667.304-1.243.698-1.311%201.179-.02.144-.022.507.393.787.213.144.395.26.564.365-1.285.521-1.361.96-1.381%201.126-.018.142-.011.496.427.746l.854.489c-.473.389-.971.914-.999%201.429-.018.278.095.532.316.713.675.556%201.231.721%201.653.721.059%200%20.104-.014.158-.02.207.707.641%201.64%201.513%201.64h.013c.8-.008%201.236-.345%201.462-.626.173-.216.268-.457.325-.692.424.195.93.374%201.372.374.151%200%20.294-.021.423-.068.732-.27.944-.704.993-1.021.009-.061.003-.119.002-.179.266.086.538.147.789.147.15%200%20.294-.021.423-.069.542-.2.797-.489.914-.754.237.147.478.258.704.288.106.014.205.021.296.021.356%200%20.595-.101.767-.229.438.435%201.094.992%201.656%201.067.106.014.205.021.296.021a1.56%201.56%200%200%200%20.323-.035c.17.575.453%201.289.866%201.605.358.273.665.362.914.362a.99.99%200%200%200%20.421-.093%201.03%201.03%200%200%200%20.245-.164c.168.428.39.846.68%201.068.358.273.665.362.913.362a.99.99%200%200%200%20.421-.093c.317-.148.512-.448.639-.762.251.157.495.257.726.257.127%200%20.25-.024.37-.071.427-.17.706-.617.841-1.314.022-.015.047-.022.068-.038.067-.051.133-.104.196-.159-.443%201.486-1.107%202.761-2.086%203.257zM8.66%209.925a.5.5%200%201%200-1%200c0%20.653-.818%201.205-1.787%201.205s-1.787-.552-1.787-1.205a.5.5%200%201%200-1%200c0%201.216%201.25%202.205%202.787%202.205s2.787-.989%202.787-2.205zm4.4%2015.965l-.208.097c-2.661%201.258-4.708%201.436-6.086.527-1.542-1.017-1.88-3.19-1.844-4.198a.4.4%200%200%200-.385-.414c-.242-.029-.406.164-.414.385-.046%201.249.367%203.686%202.202%204.896.708.467%201.547.7%202.51.7%201.248%200%202.706-.392%204.362-1.174l.185-.086a.4.4%200%200%200%20.205-.527c-.089-.204-.326-.291-.527-.206zM9.547%202.292c.093.077.205.114.317.114a.5.5%200%200%200%20.318-.886L8.817.397a.5.5%200%200%200-.703.068.5.5%200%200%200%20.069.703l1.364%201.124zm-7.661-.065c.086%200%20.173-.022.253-.068l1.523-.893a.5.5%200%200%200-.506-.863l-1.523.892a.5.5%200%200%200-.179.685c.094.158.261.247.432.247z%22%20transform%3D%22matrix%28-1%200%200%201%2058%200%29%22%20fill%3D%22%233bb300%22/%3E%3Cpath%20d%3D%22M.3%2021.86V10.18q0-.46.02-.68.04-.22.18-.5.28-.54%201.34-.54%201.06%200%201.42.28.38.26.44.78.76-1.04%202.38-1.04%201.64%200%203.1%201.54%201.46%201.54%201.46%203.58%200%202.04-1.46%203.58-1.44%201.54-3.08%201.54-1.64%200-2.38-.92v4.04q0%20.46-.04.68-.02.22-.18.5-.14.3-.5.42-.36.12-.98.12-.62%200-1-.12-.36-.12-.52-.4-.14-.28-.18-.5-.02-.22-.02-.68zm3.96-9.42q-.46.54-.46%201.18%200%20.64.46%201.18.48.52%201.2.52.74%200%201.24-.52.52-.52.52-1.18%200-.66-.48-1.18-.48-.54-1.26-.54-.76%200-1.22.54zm14.741-8.36q.16-.3.54-.42.38-.12%201-.12.64%200%201.02.12.38.12.52.42.16.3.18.54.04.22.04.68v11.94q0%20.46-.04.7-.02.22-.18.5-.3.54-1.7.54-1.38%200-1.54-.98-.84.96-2.34.96-1.8%200-3.28-1.56-1.48-1.58-1.48-3.66%200-2.1%201.48-3.68%201.5-1.58%203.28-1.58%201.48%200%202.3%201v-4.2q0-.46.02-.68.04-.24.18-.52zm-3.24%2010.86q.52.54%201.26.54.74%200%201.22-.54.5-.54.5-1.18%200-.66-.48-1.22-.46-.56-1.26-.56-.8%200-1.28.56-.48.54-.48%201.2%200%20.66.52%201.2zm7.833-1.2q0-2.4%201.68-3.96%201.68-1.56%203.84-1.56%202.16%200%203.82%201.56%201.66%201.54%201.66%203.94%200%201.66-.86%202.96-.86%201.28-2.1%201.9-1.22.6-2.54.6-1.32%200-2.56-.64-1.24-.66-2.1-1.92-.84-1.28-.84-2.88zm4.18%201.44q.64.48%201.3.48.66%200%201.32-.5.66-.5.66-1.48%200-.98-.62-1.46-.62-.48-1.34-.48-.72%200-1.34.5-.62.5-.62%201.48%200%20.96.64%201.46zm11.412-1.44q0%20.84.56%201.32.56.46%201.18.46.64%200%201.18-.36.56-.38.9-.38.6%200%201.46%201.06.46.58.46%201.04%200%20.76-1.1%201.42-1.14.8-2.8.8-1.86%200-3.58-1.34-.82-.64-1.34-1.7-.52-1.08-.52-2.36%200-1.3.52-2.34.52-1.06%201.34-1.7%201.66-1.32%203.54-1.32.76%200%201.48.22.72.2%201.06.4l.32.2q.36.24.56.38.52.4.52.92%200%20.5-.42%201.14-.72%201.1-1.38%201.1-.38%200-1.08-.44-.36-.34-1.04-.34-.66%200-1.24.48-.58.48-.58%201.34z%22%20fill%3D%22green%22/%3E%3C/svg%3E"/>
+        </a>
+</div>
+    </nav>
+    <main class="pdoc">
+            <section class="module-info">
+                    <h1 class="modulename">
+perplexipy    </h1>
+
+                        <div class="docstring"><p>% perplexipy(3) Version 0.0.7 | Perplexity AI high level API documentation</p>
+
+<h1 id="name">Name</h1>
+
+<p><strong>perplexipy</strong> - Perplexity AI high level library</p>
+
+<h1 id="synopsis">Synopsis</h1>
+
+<div class="pdoc-code codehilite">
+<pre><span></span><code><span class="n">client</span> <span class="o">=</span> <span class="n">PerplexityClient</span><span class="p">()</span> \
+<span class="nb">print</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;What is the meaning of 42?&#39;</span><span class="p">)</span> \
+<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">client</span><span class="o">.</span><span class="n">queryStreamable</span><span class="p">(</span><span class="s1">&#39;List of all US presidents&#39;</span><span class="p">):</span> \
+    <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
+</code></pre>
+</div>
+
+<h1 id="description">Description</h1>
+
+<p><strong>perplexipy</strong> is a high-level, convenience library for interacting with the
+Perplexity API from any Python 3.9+ application.  The library aims to simplify
+interactions with Perplexity models by encapsulating all the implementation
+details of the lower level OpenAI API.  All interaction between the code and
+this library occurs in the form of string and native Python objects, not
+OpenAPI / Swagger mapped objects.</p>
+
+<p><strong>perplexipy</strong> implements a combination of the Perplexity AI and the
+OpenAI outputs.  API semantics follow the "literate programming" workflow,
+and attempt to make the resulting code as simple to follow as possible.</p>
+
+<p><a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a> is an
+AI-powered search engine that uses natural language
+processing and machine learning to provide accurate and comprehensive answers to
+end-user queries.  It can be argued that it outperforms OpenAI's offerings in
+accuracy and responsiveness.  <strong>perplexypi</strong> enables the creation of Python
+programs and tools that leverage the power of Perplexity AI.</p>
+
+<h1 id="documentation">Documentation</h1>
+
+<p>These documents encompass all information about <strong>perplexipy</strong>:</p>
+
+<ul>
+<li>This README file, hosted in the <strong><a href="https://github.com/CIME-Software/perplexipy">perplexipy</a></strong>
+project on GitHub and exported to the PyPI project page</li>
+<li>A <code>man</code> page autogenerated from this README file, <code>perplexipy.3</code></li>
+<li>The complete <strong>perplexipy API reference</strong></li>
+<li>The <strong>using-perplexipy.ipynb</strong> tutorial notebook - see: <a href="https://github.com/CIME-Software/perplexipy/issues/18">https://github.com/CIME-Software/perplexipy/issues/18</a></li>
+</ul>
+
+<p>The <code>man</code> page can be generated from the source distribution using this command:</p>
+
+<div class="pdoc-code codehilite">
+<pre><span></span><code>make<span class="w"> </span>manpage
+</code></pre>
+</div>
+
+<p>The output will reside in:  <code>./manpages/perplexipy.3</code>.  The <code>man</code> page isn't
+included in the Python package wheel because there's no accepted standard
+installation that's cross-compatible among all supported operating systems and
+distributions.</p>
+
+<h1 id="installation">Installation</h1>
+
+<div class="pdoc-code codehilite">
+<pre><span></span><code>pip<span class="w"> </span>install<span class="w"> </span>perplexipy
+</code></pre>
+</div>
+
+<p>Package information:  <a href="https://pypi.org/project/perplexipy">https://pypi.org/project/perplexipy</a></p>
+
+<h1 id="api-key">API key</h1>
+
+<p>Access to the Perplexity API requires a paid subscription and an API key.</p>
+
+<p>Use of <code>.env</code> is recommended for storing the private key.  There is an automatic
+constant <code><a href="#PERPLEXITY_API_KEY">PERPLEXITY_API_KEY</a></code> that gets initialized to the value of a <code>.env</code> key
+of the same name via the <code>dotenv</code> API.  Otherwise, <code><a href="#PERPLEXITY_API_KEY">PERPLEXITY_API_KEY</a></code> may
+be handled like any other secret by the implementing team.  This module provides
+no other tools or services for handling the API key.</p>
+
+<p>This key is used only during <code><a href="#PerplexityClient">PerplexityClient</a></code> instantiation:</p>
+
+<div class="pdoc-code codehilite">
+<pre><span></span><code><span class="kn">import</span> <span class="nn">os</span>
+
+<span class="n">key</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="p">[</span><span class="s1">&#39;PERPLEXITY_API_KEY&#39;</span><span class="p">]</span>
+<span class="n">client</span> <span class="o">=</span> <span class="n">PerplexityClient</span><span class="p">(</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span><span class="p">)</span>
+<span class="nb">print</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;Brief answer:  greet the world in Swedish.&#39;</span><span class="p">))</span>
+</code></pre>
+</div>
+
+<h1 id="usage">Usage</h1>
+
+<p>See the <strong>using-perplexipy.ipynb</strong> (<a href="https://github.com/CIME-Software/perplexipy/issues/18">https://github.com/CIME-Software/perplexipy/issues/18</a>) notebook for a richer example of the API's
+capabilities.</p>
+
+<p>In general:</p>
+
+<div class="pdoc-code codehilite">
+<pre><span></span><code><span class="n">client</span> <span class="o">=</span> <span class="n">PerplexityClient</span><span class="p">()</span>
+<span class="n">result</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="s1">&#39;Show me how to declare a list in Python&#39;</span><span class="p">)</span>
+<span class="c1"># result is a string</span>
+
+<span class="n">results</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">queryBatch</span><span class="p">(</span><span class="s1">&#39;Show me different ways of declaring a Python list&#39;</span><span class="p">)</span>
+<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
+    <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
+    <span class="c1"># results is a tuple of one or more results</span>
+
+<span class="n">results</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">queryStreamable</span><span class="p">(</span><span class="s1">&#39;Tell me why lists are important in programming&#39;</span><span class="p">)</span>
+<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
+    <span class="nb">print</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
+    <span class="c1"># results is a long stream of data, served over time.</span>
+
+<span class="n">models</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">models</span> <span class="c1"># lists all models supported by Perplexity AI</span>
+
+<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;Model names:&#39;</span><span class="p">)</span>
+<span class="k">for</span> <span class="n">model</span> <span class="ow">in</span> <span class="n">models</span><span class="o">.</span><span class="n">keys</span><span class="p">():</span>
+    <span class="nb">print</span><span class="p">(</span><span class="s1">&#39; - </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="n">model</span><span class="p">)</span>
+
+<span class="k">try</span><span class="p">:</span>
+    <span class="n">client</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="s1">&#39;bogus-LLM-7b&#39;</span>
+<span class="k">except</span> <span class="n">PerplexityClientError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
+    <span class="nb">print</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
+
+<span class="n">client</span><span class="o">.</span><span class="n">model</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">keys</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># OK</span>
+</code></pre>
+</div>
+
+<h1 id="async-usage">Async usage</h1>
+
+<p>Not supported at this time.</p>
+
+<h1 id="license">License</h1>
+
+<p>The <strong>perplexipy</strong> package, documentation and examples are licensed under the
+<a href="https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt">BSD-3 open source license</a>.</p>
+
+<h1 id="see-also">See also</h1>
+
+<ul>
+<li>PyPI:  <a href='https://pipy.org/project/openai' target='_blank'>openai</a></li>
+<li><a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a></li>
+</ul>
+
+<h1 id="caveats">Caveats</h1>
+
+<p>The code should work with Python 3.7 or later, but it was only tested with
+Python 3.9.16 and later.  Download the package and install it from source if
+support for an earlier Python version is required.</p>
+
+<h1 id="bugs">Bugs</h1>
+
+<p>Feature requests and bug reports:</p>
+
+<p><a href="https://github.com/CIME-Software/perplexipy/issues">https://github.com/CIME-Software/perplexipy/issues</a></p>
+
+<hr />
+
+<h1 id="perplexipy-api-documentation">perplexipy API Documentation</h1>
+</div>
+
+                        <input id="mod-perplexipy-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+
+                        <label class="view-source-button" for="mod-perplexipy-view-source"><span>View Source</span></label>
+
+                        <div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">  1</span></a><span class="c1"># See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt</span>
+</span><span id="L-2"><a href="#L-2"><span class="linenos">  2</span></a>
+</span><span id="L-3"><a href="#L-3"><span class="linenos">  3</span></a>
+</span><span id="L-4"><a href="#L-4"><span class="linenos">  4</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-5"><a href="#L-5"><span class="linenos">  5</span></a><span class="sd">.. include:: ../README.md</span>
+</span><span id="L-6"><a href="#L-6"><span class="linenos">  6</span></a>
+</span><span id="L-7"><a href="#L-7"><span class="linenos">  7</span></a><span class="sd">---</span>
+</span><span id="L-8"><a href="#L-8"><span class="linenos">  8</span></a>
+</span><span id="L-9"><a href="#L-9"><span class="linenos">  9</span></a><span class="sd"># perplexipy API Documentation</span>
+</span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a>
+</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a>
+</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="n">__VERSION__</span> <span class="o">=</span> <span class="s1">&#39;0.0.7&#39;</span>
+</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a>
+</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a>
+</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">namedtuple</span>
+</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a>
+</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a><span class="kn">from</span> <span class="nn">dotenv</span> <span class="kn">import</span> <span class="n">load_dotenv</span>
+</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a><span class="kn">from</span> <span class="nn">openai</span> <span class="kn">import</span> <span class="n">OpenAI</span>
+</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a>
+</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="kn">from</span> <span class="nn">perplexipy.errors</span> <span class="kn">import</span> <span class="n">PerplexityClientError</span>
+</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="kn">from</span> <span class="nn">perplexipy.responses</span> <span class="kn">import</span> <span class="n">Responses</span>
+</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a>
+</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a><span class="n">load_dotenv</span><span class="p">()</span>
+</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a>
+</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a><span class="kn">import</span> <span class="nn">os</span>
+</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a>
+</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a>
+</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a>
+</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a><span class="sd">`PERPLEXITY_API_KEY` is set to the environment variable of the same name if</span>
+</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a><span class="sd">present, otherwise it&#39;s set to the empty string `&#39;&#39;`.</span>
+</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a><span class="n">PERPLEXITY_API_KEY</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;PERPLEXITY_API_KEY&#39;</span><span class="p">,</span> <span class="n">default</span> <span class="o">=</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
+</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a><span class="n">PERPLEXITY_API_URL</span> <span class="o">=</span> <span class="s1">&#39;https://api.perplexity.ai&#39;</span>
+</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a><span class="sd">The default model is **mistral-7b-instruct** because of it&#39;s efficiency and</span>
+</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a><span class="sd">performance qualities.  Ref:  https://arxiv.org/abs/2310.06825</span>
+</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a><span class="n">PERPLEXITY_DEFAULT_MODEL</span> <span class="o">=</span> <span class="s1">&#39;mistral-7b-instruct&#39;</span>
+</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a><span class="n">PERPLEXITY_DEFAULT_ROLE</span> <span class="o">=</span> <span class="s1">&#39;user&#39;</span>
+</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a><span class="n">PERPLEXITY_TIMEOUT</span> <span class="o">=</span> <span class="mf">30.0</span> <span class="c1"># seconds</span>
+</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a>
+</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a>
+</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a><span class="sd">Immutable dictionary-like object of a model&#39;s capabilities.  Use `_asDict()` if</span>
+</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a><span class="sd">dictionary manipulation is required.</span>
+</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a><span class="n">ModelInfo</span> <span class="o">=</span> <span class="n">namedtuple</span><span class="p">(</span><span class="s1">&#39;ModelInfo&#39;</span><span class="p">,</span> <span class="p">[</span> <span class="s1">&#39;parameterCount&#39;</span><span class="p">,</span> <span class="s1">&#39;contextLength&#39;</span><span class="p">,</span> <span class="s1">&#39;modelType&#39;</span><span class="p">,</span> <span class="s1">&#39;availability&#39;</span><span class="p">,</span> <span class="p">])</span>
+</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a>
+</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a>
+</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a><span class="k">class</span> <span class="nc">PerplexityClient</span><span class="p">:</span>
+</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a><span class="sd">    PerplexityClient objects encapsulate all the API functionality.  They can be</span>
+</span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a><span class="sd">    instantiated across multiple contexts, each keeping its own state.</span>
+</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_KEY</span><span class="p">,</span> <span class="n">endpoint</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_URL</span><span class="p">):</span>
+</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a><span class="sd">        Create a new instance of `perplexipy.PerplexityClient` using the API</span>
+</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a><span class="sd">        `key` to connect to the corresponding `endpoint`.</span>
+</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a>
+</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a><span class="sd">        Arguments</span>
+</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a><span class="sd">        ---------</span>
+</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a><span class="sd">            key</span>
+</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a><span class="sd">        A valid API key string.  If not present, it defaults to `perplexipy.PERPLEXITY_API_KEY`.</span>
+</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a>
+</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a><span class="sd">            endpoint</span>
+</span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a><span class="sd">        An string representing a URL to the Perplexity API.</span>
+</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a>
+</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a><span class="sd">        Returns</span>
+</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a><span class="sd">        -------</span>
+</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a><span class="sd">        An instance of `perplexipy.PerplexityClient` if successful.</span>
+</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a>
+</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a><span class="sd">        Attributes:</span>
+</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a>
+</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a><span class="sd">        `model` - the current model to use in queries, user configurable.</span>
+</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a>
+</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a><span class="sd">        The role is fixed to `&quot;user&quot;` for Perplexity calls, per the API</span>
+</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a><span class="sd">        recommendations.</span>
+</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a>
+</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a><span class="sd">        Raises</span>
+</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a><span class="sd">        ------</span>
+</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a><span class="sd">        If the API key is empty, or doesn&#39;t match one of the valid API prefixes</span>
+</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a><span class="sd">        per the documentation.</span>
+</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;Provide a valid key argument during instantiation&#39;</span><span class="p">)</span>
+</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="s1">&#39;pplx-&#39;</span> <span class="ow">in</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;The key </span><span class="si">%s</span><span class="s1"> i missing the pplx- prefix - invalid API key&#39;</span><span class="p">)</span>
+</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a>
+</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>
+</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_key</span> <span class="o">=</span> <span class="n">key</span>
+</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_role</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_ROLE</span>
+</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_MODEL</span>
+</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_client</span> <span class="o">=</span> <span class="n">OpenAI</span><span class="p">(</span>
+</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a>            <span class="n">api_key</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_key</span><span class="p">,</span>
+</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a>            <span class="n">base_url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span><span class="p">,</span>
+</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a>            <span class="n">timeout</span> <span class="o">=</span> <span class="n">PERPLEXITY_TIMEOUT</span><span class="p">,</span>
+</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a>        <span class="p">)</span>
+</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a>
+</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a>
+</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a>    <span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a>
+</span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a><span class="sd">        Arguments</span>
+</span><span id="L-108"><a href="#L-108"><span class="linenos">108</span></a><span class="sd">        ---------</span>
+</span><span id="L-109"><a href="#L-109"><span class="linenos">109</span></a><span class="sd">            query</span>
+</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a>
+</span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a><span class="sd">        Returns</span>
+</span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a><span class="sd">        -------</span>
+</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a><span class="sd">        A string with a response from the Perplexity service.</span>
+</span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a>
+</span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a><span class="sd">        Raises</span>
+</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a><span class="sd">        ------</span>
+</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a><span class="sd">            Exception</span>
+</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="L-122"><a href="#L-122"><span class="linenos">122</span></a>
+</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a>
+</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="L-126"><a href="#L-126"><span class="linenos">126</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="L-127"><a href="#L-127"><span class="linenos">127</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-128"><a href="#L-128"><span class="linenos">128</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="L-129"><a href="#L-129"><span class="linenos">129</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="L-130"><a href="#L-130"><span class="linenos">130</span></a>
+</span><span id="L-131"><a href="#L-131"><span class="linenos">131</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="L-132"><a href="#L-132"><span class="linenos">132</span></a>
+</span><span id="L-133"><a href="#L-133"><span class="linenos">133</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="L-134"><a href="#L-134"><span class="linenos">134</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="L-135"><a href="#L-135"><span class="linenos">135</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="L-136"><a href="#L-136"><span class="linenos">136</span></a>        <span class="p">)</span>
+</span><span id="L-137"><a href="#L-137"><span class="linenos">137</span></a>
+</span><span id="L-138"><a href="#L-138"><span class="linenos">138</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span>
+</span><span id="L-139"><a href="#L-139"><span class="linenos">139</span></a>
+</span><span id="L-140"><a href="#L-140"><span class="linenos">140</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span><span id="L-141"><a href="#L-141"><span class="linenos">141</span></a>
+</span><span id="L-142"><a href="#L-142"><span class="linenos">142</span></a>
+</span><span id="L-143"><a href="#L-143"><span class="linenos">143</span></a>    <span class="k">def</span> <span class="nf">queryBatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">:</span>
+</span><span id="L-144"><a href="#L-144"><span class="linenos">144</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-145"><a href="#L-145"><span class="linenos">145</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="L-146"><a href="#L-146"><span class="linenos">146</span></a>
+</span><span id="L-147"><a href="#L-147"><span class="linenos">147</span></a><span class="sd">        Arguments</span>
+</span><span id="L-148"><a href="#L-148"><span class="linenos">148</span></a><span class="sd">        ---------</span>
+</span><span id="L-149"><a href="#L-149"><span class="linenos">149</span></a><span class="sd">            query</span>
+</span><span id="L-150"><a href="#L-150"><span class="linenos">150</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="L-151"><a href="#L-151"><span class="linenos">151</span></a>
+</span><span id="L-152"><a href="#L-152"><span class="linenos">152</span></a><span class="sd">        Returns</span>
+</span><span id="L-153"><a href="#L-153"><span class="linenos">153</span></a><span class="sd">        -------</span>
+</span><span id="L-154"><a href="#L-154"><span class="linenos">154</span></a><span class="sd">        A tuple with a batch of 1 or more response strings.</span>
+</span><span id="L-155"><a href="#L-155"><span class="linenos">155</span></a>
+</span><span id="L-156"><a href="#L-156"><span class="linenos">156</span></a><span class="sd">        Raises</span>
+</span><span id="L-157"><a href="#L-157"><span class="linenos">157</span></a><span class="sd">        ------</span>
+</span><span id="L-158"><a href="#L-158"><span class="linenos">158</span></a><span class="sd">            Exception</span>
+</span><span id="L-159"><a href="#L-159"><span class="linenos">159</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="L-160"><a href="#L-160"><span class="linenos">160</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="L-161"><a href="#L-161"><span class="linenos">161</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="L-162"><a href="#L-162"><span class="linenos">162</span></a>
+</span><span id="L-163"><a href="#L-163"><span class="linenos">163</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="L-164"><a href="#L-164"><span class="linenos">164</span></a>
+</span><span id="L-165"><a href="#L-165"><span class="linenos">165</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="L-166"><a href="#L-166"><span class="linenos">166</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="L-167"><a href="#L-167"><span class="linenos">167</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-168"><a href="#L-168"><span class="linenos">168</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="L-169"><a href="#L-169"><span class="linenos">169</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="L-170"><a href="#L-170"><span class="linenos">170</span></a>
+</span><span id="L-171"><a href="#L-171"><span class="linenos">171</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="L-172"><a href="#L-172"><span class="linenos">172</span></a>
+</span><span id="L-173"><a href="#L-173"><span class="linenos">173</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="L-174"><a href="#L-174"><span class="linenos">174</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="L-175"><a href="#L-175"><span class="linenos">175</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="L-176"><a href="#L-176"><span class="linenos">176</span></a>        <span class="p">)</span>
+</span><span id="L-177"><a href="#L-177"><span class="linenos">177</span></a>
+</span><span id="L-178"><a href="#L-178"><span class="linenos">178</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span> <span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">)</span>
+</span><span id="L-179"><a href="#L-179"><span class="linenos">179</span></a>
+</span><span id="L-180"><a href="#L-180"><span class="linenos">180</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span><span id="L-181"><a href="#L-181"><span class="linenos">181</span></a>
+</span><span id="L-182"><a href="#L-182"><span class="linenos">182</span></a>
+</span><span id="L-183"><a href="#L-183"><span class="linenos">183</span></a>    <span class="k">def</span> <span class="nf">queryStreamable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Responses</span><span class="p">:</span>
+</span><span id="L-184"><a href="#L-184"><span class="linenos">184</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-185"><a href="#L-185"><span class="linenos">185</span></a><span class="sd">        Send a query and return a long, streamable response.</span>
+</span><span id="L-186"><a href="#L-186"><span class="linenos">186</span></a>
+</span><span id="L-187"><a href="#L-187"><span class="linenos">187</span></a><span class="sd">        Arguments</span>
+</span><span id="L-188"><a href="#L-188"><span class="linenos">188</span></a><span class="sd">        ---------</span>
+</span><span id="L-189"><a href="#L-189"><span class="linenos">189</span></a><span class="sd">            query</span>
+</span><span id="L-190"><a href="#L-190"><span class="linenos">190</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="L-191"><a href="#L-191"><span class="linenos">191</span></a>
+</span><span id="L-192"><a href="#L-192"><span class="linenos">192</span></a><span class="sd">        Returns</span>
+</span><span id="L-193"><a href="#L-193"><span class="linenos">193</span></a><span class="sd">        -------</span>
+</span><span id="L-194"><a href="#L-194"><span class="linenos">194</span></a><span class="sd">        Returns a `perplexipy.Responses` object for streaming the textual</span>
+</span><span id="L-195"><a href="#L-195"><span class="linenos">195</span></a><span class="sd">        responses from the client.  The response strips all metadata and returns</span>
+</span><span id="L-196"><a href="#L-196"><span class="linenos">196</span></a><span class="sd">        only content strings, for simpler and easier integration.</span>
+</span><span id="L-197"><a href="#L-197"><span class="linenos">197</span></a>
+</span><span id="L-198"><a href="#L-198"><span class="linenos">198</span></a><span class="sd">        Raises</span>
+</span><span id="L-199"><a href="#L-199"><span class="linenos">199</span></a><span class="sd">        ------</span>
+</span><span id="L-200"><a href="#L-200"><span class="linenos">200</span></a><span class="sd">            Exception</span>
+</span><span id="L-201"><a href="#L-201"><span class="linenos">201</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="L-202"><a href="#L-202"><span class="linenos">202</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="L-203"><a href="#L-203"><span class="linenos">203</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="L-204"><a href="#L-204"><span class="linenos">204</span></a>
+</span><span id="L-205"><a href="#L-205"><span class="linenos">205</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="L-206"><a href="#L-206"><span class="linenos">206</span></a>
+</span><span id="L-207"><a href="#L-207"><span class="linenos">207</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="L-208"><a href="#L-208"><span class="linenos">208</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="L-209"><a href="#L-209"><span class="linenos">209</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-210"><a href="#L-210"><span class="linenos">210</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="L-211"><a href="#L-211"><span class="linenos">211</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="L-212"><a href="#L-212"><span class="linenos">212</span></a>
+</span><span id="L-213"><a href="#L-213"><span class="linenos">213</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="L-214"><a href="#L-214"><span class="linenos">214</span></a>
+</span><span id="L-215"><a href="#L-215"><span class="linenos">215</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="L-216"><a href="#L-216"><span class="linenos">216</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="L-217"><a href="#L-217"><span class="linenos">217</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="L-218"><a href="#L-218"><span class="linenos">218</span></a>            <span class="n">stream</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
+</span><span id="L-219"><a href="#L-219"><span class="linenos">219</span></a>        <span class="p">)</span>
+</span><span id="L-220"><a href="#L-220"><span class="linenos">220</span></a>
+</span><span id="L-221"><a href="#L-221"><span class="linenos">221</span></a>        <span class="k">return</span> <span class="n">Responses</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
+</span><span id="L-222"><a href="#L-222"><span class="linenos">222</span></a>
+</span><span id="L-223"><a href="#L-223"><span class="linenos">223</span></a>
+</span><span id="L-224"><a href="#L-224"><span class="linenos">224</span></a>    <span class="nd">@property</span>
+</span><span id="L-225"><a href="#L-225"><span class="linenos">225</span></a>    <span class="k">def</span> <span class="nf">models</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="L-226"><a href="#L-226"><span class="linenos">226</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-227"><a href="#L-227"><span class="linenos">227</span></a><span class="sd">        Provide a dictionary of the models supported by Perplexity listed in:</span>
+</span><span id="L-228"><a href="#L-228"><span class="linenos">228</span></a>
+</span><span id="L-229"><a href="#L-229"><span class="linenos">229</span></a><span class="sd">        https://docs.perplexity.ai/docs/model-cards</span>
+</span><span id="L-230"><a href="#L-230"><span class="linenos">230</span></a>
+</span><span id="L-231"><a href="#L-231"><span class="linenos">231</span></a><span class="sd">        Returns</span>
+</span><span id="L-232"><a href="#L-232"><span class="linenos">232</span></a><span class="sd">        -------</span>
+</span><span id="L-233"><a href="#L-233"><span class="linenos">233</span></a><span class="sd">        A dictionary of supported models as the key, with a `perplexypy.ModelInfo`</span>
+</span><span id="L-234"><a href="#L-234"><span class="linenos">234</span></a><span class="sd">        named tuple with the model capabilities description.  The model</span>
+</span><span id="L-235"><a href="#L-235"><span class="linenos">235</span></a><span class="sd">        information attributes are:</span>
+</span><span id="L-236"><a href="#L-236"><span class="linenos">236</span></a>
+</span><span id="L-237"><a href="#L-237"><span class="linenos">237</span></a><span class="sd">        - `parameterCount`</span>
+</span><span id="L-238"><a href="#L-238"><span class="linenos">238</span></a><span class="sd">        - `contextLength`</span>
+</span><span id="L-239"><a href="#L-239"><span class="linenos">239</span></a><span class="sd">        - `modelType`</span>
+</span><span id="L-240"><a href="#L-240"><span class="linenos">240</span></a><span class="sd">        - `availability`</span>
+</span><span id="L-241"><a href="#L-241"><span class="linenos">241</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-242"><a href="#L-242"><span class="linenos">242</span></a>        <span class="n">supportedModels</span> <span class="o">=</span> <span class="p">{</span>
+</span><span id="L-243"><a href="#L-243"><span class="linenos">243</span></a>            <span class="s1">&#39;codellama-70b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;70B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="L-244"><a href="#L-244"><span class="linenos">244</span></a>            <span class="s1">&#39;mistral-7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="L-245"><a href="#L-245"><span class="linenos">245</span></a>            <span class="s1">&#39;mixtral-8x7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="L-246"><a href="#L-246"><span class="linenos">246</span></a>            <span class="s1">&#39;sonar-medium-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16348</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="L-247"><a href="#L-247"><span class="linenos">247</span></a>            <span class="s1">&#39;sonar-medium-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="L-248"><a href="#L-248"><span class="linenos">248</span></a>            <span class="s1">&#39;sonar-small-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="L-249"><a href="#L-249"><span class="linenos">249</span></a>            <span class="s1">&#39;sonar-small-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="L-250"><a href="#L-250"><span class="linenos">250</span></a>        <span class="p">}</span>
+</span><span id="L-251"><a href="#L-251"><span class="linenos">251</span></a>
+</span><span id="L-252"><a href="#L-252"><span class="linenos">252</span></a>        <span class="k">return</span> <span class="n">supportedModels</span>
+</span><span id="L-253"><a href="#L-253"><span class="linenos">253</span></a>
+</span><span id="L-254"><a href="#L-254"><span class="linenos">254</span></a>
+</span><span id="L-255"><a href="#L-255"><span class="linenos">255</span></a>    <span class="nd">@property</span>
+</span><span id="L-256"><a href="#L-256"><span class="linenos">256</span></a>    <span class="k">def</span> <span class="nf">model</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="L-257"><a href="#L-257"><span class="linenos">257</span></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_model</span>
+</span><span id="L-258"><a href="#L-258"><span class="linenos">258</span></a>
+</span><span id="L-259"><a href="#L-259"><span class="linenos">259</span></a>    <span class="nd">@model</span><span class="o">.</span><span class="n">setter</span>
+</span><span id="L-260"><a href="#L-260"><span class="linenos">260</span></a>    <span class="k">def</span> <span class="nf">model</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
+</span><span id="L-261"><a href="#L-261"><span class="linenos">261</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-262"><a href="#L-262"><span class="linenos">262</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="L-263"><a href="#L-263"><span class="linenos">263</span></a>        <span class="n">models</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">models</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
+</span><span id="L-264"><a href="#L-264"><span class="linenos">264</span></a>        <span class="k">if</span> <span class="n">value</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">models</span><span class="p">:</span>
+</span><span id="L-265"><a href="#L-265"><span class="linenos">265</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;value = </span><span class="si">%s</span><span class="s1"> error; supported models: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">models</span><span class="p">)))</span>
+</span><span id="L-266"><a href="#L-266"><span class="linenos">266</span></a>
+</span><span id="L-267"><a href="#L-267"><span class="linenos">267</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">value</span>
+</span></pre></div>
+
+
+            </section>
+                <section id="PERPLEXITY_API_KEY">
+                    <div class="attr variable">
+            <span class="name">PERPLEXITY_API_KEY</span>        =
+<span class="default_value">&#39;&#39;</span>
+
+        
+    </div>
+    <a class="headerlink" href="#PERPLEXITY_API_KEY"></a>
+    
+    
+
+                </section>
+                <section id="PERPLEXITY_API_URL">
+                    <div class="attr variable">
+            <span class="name">PERPLEXITY_API_URL</span>        =
+<span class="default_value">&#39;https://api.perplexity.ai&#39;</span>
+
+        
+    </div>
+    <a class="headerlink" href="#PERPLEXITY_API_URL"></a>
+    
+            <div class="docstring"><p>The default model is <strong>mistral-7b-instruct</strong> because of it's efficiency and
+performance qualities.  Ref:  <a href="https://arxiv.org/abs/2310.06825">https://arxiv.org/abs/2310.06825</a></p>
+</div>
+
+
+                </section>
+                <section id="PERPLEXITY_DEFAULT_MODEL">
+                    <div class="attr variable">
+            <span class="name">PERPLEXITY_DEFAULT_MODEL</span>        =
+<span class="default_value">&#39;mistral-7b-instruct&#39;</span>
+
+        
+    </div>
+    <a class="headerlink" href="#PERPLEXITY_DEFAULT_MODEL"></a>
+    
+    
+
+                </section>
+                <section id="PERPLEXITY_DEFAULT_ROLE">
+                    <div class="attr variable">
+            <span class="name">PERPLEXITY_DEFAULT_ROLE</span>        =
+<span class="default_value">&#39;user&#39;</span>
+
+        
+    </div>
+    <a class="headerlink" href="#PERPLEXITY_DEFAULT_ROLE"></a>
+    
+    
+
+                </section>
+                <section id="PERPLEXITY_TIMEOUT">
+                    <div class="attr variable">
+            <span class="name">PERPLEXITY_TIMEOUT</span>        =
+<span class="default_value">30.0</span>
+
+        
+    </div>
+    <a class="headerlink" href="#PERPLEXITY_TIMEOUT"></a>
+    
+            <div class="docstring"><p>Immutable dictionary-like object of a model's capabilities.  Use <code>_asDict()</code> if
+dictionary manipulation is required.</p>
+</div>
+
+
+                </section>
+                <section id="ModelInfo">
+                    <div class="attr class">
+            
+    <span class="def">class</span>
+    <span class="name">ModelInfo</span><wbr>(<span class="base">builtins.tuple</span>):
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo"></a>
+    
+            <div class="docstring"><p>ModelInfo(parameterCount, contextLength, modelType, availability)</p>
+</div>
+
+
+                            <div id="ModelInfo.__init__" class="classattr">
+                                <div class="attr function">
+            
+        <span class="name">ModelInfo</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">parameterCount</span>, </span><span class="param"><span class="n">contextLength</span>, </span><span class="param"><span class="n">modelType</span>, </span><span class="param"><span class="n">availability</span></span>)</span>
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo.__init__"></a>
+    
+            <div class="docstring"><p>Create new instance of ModelInfo(parameterCount, contextLength, modelType, availability)</p>
+</div>
+
+
+                            </div>
+                            <div id="ModelInfo.parameterCount" class="classattr">
+                                <div class="attr variable">
+            <span class="name">parameterCount</span>
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo.parameterCount"></a>
+    
+            <div class="docstring"><p>Alias for field number 0</p>
+</div>
+
+
+                            </div>
+                            <div id="ModelInfo.contextLength" class="classattr">
+                                <div class="attr variable">
+            <span class="name">contextLength</span>
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo.contextLength"></a>
+    
+            <div class="docstring"><p>Alias for field number 1</p>
+</div>
+
+
+                            </div>
+                            <div id="ModelInfo.modelType" class="classattr">
+                                <div class="attr variable">
+            <span class="name">modelType</span>
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo.modelType"></a>
+    
+            <div class="docstring"><p>Alias for field number 2</p>
+</div>
+
+
+                            </div>
+                            <div id="ModelInfo.availability" class="classattr">
+                                <div class="attr variable">
+            <span class="name">availability</span>
+
+        
+    </div>
+    <a class="headerlink" href="#ModelInfo.availability"></a>
+    
+            <div class="docstring"><p>Alias for field number 3</p>
+</div>
+
+
+                            </div>
+                            <div class="inherited">
+                                <h5>Inherited Members</h5>
+                                <dl>
+                                    <div><dt>builtins.tuple</dt>
+                                <dd id="ModelInfo.index" class="function">index</dd>
+                <dd id="ModelInfo.count" class="function">count</dd>
+
+            </div>
+                                </dl>
+                            </div>
+                </section>
+                <section id="PerplexityClient">
+                            <input id="PerplexityClient-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr class">
+            
+    <span class="def">class</span>
+    <span class="name">PerplexityClient</span>:
+
+                <label class="view-source-button" for="PerplexityClient-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient-53"><a href="#PerplexityClient-53"><span class="linenos"> 53</span></a><span class="k">class</span> <span class="nc">PerplexityClient</span><span class="p">:</span>
+</span><span id="PerplexityClient-54"><a href="#PerplexityClient-54"><span class="linenos"> 54</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-55"><a href="#PerplexityClient-55"><span class="linenos"> 55</span></a><span class="sd">    PerplexityClient objects encapsulate all the API functionality.  They can be</span>
+</span><span id="PerplexityClient-56"><a href="#PerplexityClient-56"><span class="linenos"> 56</span></a><span class="sd">    instantiated across multiple contexts, each keeping its own state.</span>
+</span><span id="PerplexityClient-57"><a href="#PerplexityClient-57"><span class="linenos"> 57</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-58"><a href="#PerplexityClient-58"><span class="linenos"> 58</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_KEY</span><span class="p">,</span> <span class="n">endpoint</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_URL</span><span class="p">):</span>
+</span><span id="PerplexityClient-59"><a href="#PerplexityClient-59"><span class="linenos"> 59</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-60"><a href="#PerplexityClient-60"><span class="linenos"> 60</span></a><span class="sd">        Create a new instance of `perplexipy.PerplexityClient` using the API</span>
+</span><span id="PerplexityClient-61"><a href="#PerplexityClient-61"><span class="linenos"> 61</span></a><span class="sd">        `key` to connect to the corresponding `endpoint`.</span>
+</span><span id="PerplexityClient-62"><a href="#PerplexityClient-62"><span class="linenos"> 62</span></a>
+</span><span id="PerplexityClient-63"><a href="#PerplexityClient-63"><span class="linenos"> 63</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient-64"><a href="#PerplexityClient-64"><span class="linenos"> 64</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient-65"><a href="#PerplexityClient-65"><span class="linenos"> 65</span></a><span class="sd">            key</span>
+</span><span id="PerplexityClient-66"><a href="#PerplexityClient-66"><span class="linenos"> 66</span></a><span class="sd">        A valid API key string.  If not present, it defaults to `perplexipy.PERPLEXITY_API_KEY`.</span>
+</span><span id="PerplexityClient-67"><a href="#PerplexityClient-67"><span class="linenos"> 67</span></a>
+</span><span id="PerplexityClient-68"><a href="#PerplexityClient-68"><span class="linenos"> 68</span></a><span class="sd">            endpoint</span>
+</span><span id="PerplexityClient-69"><a href="#PerplexityClient-69"><span class="linenos"> 69</span></a><span class="sd">        An string representing a URL to the Perplexity API.</span>
+</span><span id="PerplexityClient-70"><a href="#PerplexityClient-70"><span class="linenos"> 70</span></a>
+</span><span id="PerplexityClient-71"><a href="#PerplexityClient-71"><span class="linenos"> 71</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient-72"><a href="#PerplexityClient-72"><span class="linenos"> 72</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient-73"><a href="#PerplexityClient-73"><span class="linenos"> 73</span></a><span class="sd">        An instance of `perplexipy.PerplexityClient` if successful.</span>
+</span><span id="PerplexityClient-74"><a href="#PerplexityClient-74"><span class="linenos"> 74</span></a>
+</span><span id="PerplexityClient-75"><a href="#PerplexityClient-75"><span class="linenos"> 75</span></a><span class="sd">        Attributes:</span>
+</span><span id="PerplexityClient-76"><a href="#PerplexityClient-76"><span class="linenos"> 76</span></a>
+</span><span id="PerplexityClient-77"><a href="#PerplexityClient-77"><span class="linenos"> 77</span></a><span class="sd">        `model` - the current model to use in queries, user configurable.</span>
+</span><span id="PerplexityClient-78"><a href="#PerplexityClient-78"><span class="linenos"> 78</span></a>
+</span><span id="PerplexityClient-79"><a href="#PerplexityClient-79"><span class="linenos"> 79</span></a><span class="sd">        The role is fixed to `&quot;user&quot;` for Perplexity calls, per the API</span>
+</span><span id="PerplexityClient-80"><a href="#PerplexityClient-80"><span class="linenos"> 80</span></a><span class="sd">        recommendations.</span>
+</span><span id="PerplexityClient-81"><a href="#PerplexityClient-81"><span class="linenos"> 81</span></a>
+</span><span id="PerplexityClient-82"><a href="#PerplexityClient-82"><span class="linenos"> 82</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient-83"><a href="#PerplexityClient-83"><span class="linenos"> 83</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient-84"><a href="#PerplexityClient-84"><span class="linenos"> 84</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient-85"><a href="#PerplexityClient-85"><span class="linenos"> 85</span></a><span class="sd">        If the API key is empty, or doesn&#39;t match one of the valid API prefixes</span>
+</span><span id="PerplexityClient-86"><a href="#PerplexityClient-86"><span class="linenos"> 86</span></a><span class="sd">        per the documentation.</span>
+</span><span id="PerplexityClient-87"><a href="#PerplexityClient-87"><span class="linenos"> 87</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-88"><a href="#PerplexityClient-88"><span class="linenos"> 88</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="PerplexityClient-89"><a href="#PerplexityClient-89"><span class="linenos"> 89</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;Provide a valid key argument during instantiation&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient-90"><a href="#PerplexityClient-90"><span class="linenos"> 90</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="s1">&#39;pplx-&#39;</span> <span class="ow">in</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="PerplexityClient-91"><a href="#PerplexityClient-91"><span class="linenos"> 91</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;The key </span><span class="si">%s</span><span class="s1"> i missing the pplx- prefix - invalid API key&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient-92"><a href="#PerplexityClient-92"><span class="linenos"> 92</span></a>
+</span><span id="PerplexityClient-93"><a href="#PerplexityClient-93"><span class="linenos"> 93</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>
+</span><span id="PerplexityClient-94"><a href="#PerplexityClient-94"><span class="linenos"> 94</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_key</span> <span class="o">=</span> <span class="n">key</span>
+</span><span id="PerplexityClient-95"><a href="#PerplexityClient-95"><span class="linenos"> 95</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_role</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_ROLE</span>
+</span><span id="PerplexityClient-96"><a href="#PerplexityClient-96"><span class="linenos"> 96</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_MODEL</span>
+</span><span id="PerplexityClient-97"><a href="#PerplexityClient-97"><span class="linenos"> 97</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_client</span> <span class="o">=</span> <span class="n">OpenAI</span><span class="p">(</span>
+</span><span id="PerplexityClient-98"><a href="#PerplexityClient-98"><span class="linenos"> 98</span></a>            <span class="n">api_key</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_key</span><span class="p">,</span>
+</span><span id="PerplexityClient-99"><a href="#PerplexityClient-99"><span class="linenos"> 99</span></a>            <span class="n">base_url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span><span class="p">,</span>
+</span><span id="PerplexityClient-100"><a href="#PerplexityClient-100"><span class="linenos">100</span></a>            <span class="n">timeout</span> <span class="o">=</span> <span class="n">PERPLEXITY_TIMEOUT</span><span class="p">,</span>
+</span><span id="PerplexityClient-101"><a href="#PerplexityClient-101"><span class="linenos">101</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient-102"><a href="#PerplexityClient-102"><span class="linenos">102</span></a>
+</span><span id="PerplexityClient-103"><a href="#PerplexityClient-103"><span class="linenos">103</span></a>
+</span><span id="PerplexityClient-104"><a href="#PerplexityClient-104"><span class="linenos">104</span></a>    <span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="PerplexityClient-105"><a href="#PerplexityClient-105"><span class="linenos">105</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-106"><a href="#PerplexityClient-106"><span class="linenos">106</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="PerplexityClient-107"><a href="#PerplexityClient-107"><span class="linenos">107</span></a>
+</span><span id="PerplexityClient-108"><a href="#PerplexityClient-108"><span class="linenos">108</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient-109"><a href="#PerplexityClient-109"><span class="linenos">109</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient-110"><a href="#PerplexityClient-110"><span class="linenos">110</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient-111"><a href="#PerplexityClient-111"><span class="linenos">111</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient-112"><a href="#PerplexityClient-112"><span class="linenos">112</span></a>
+</span><span id="PerplexityClient-113"><a href="#PerplexityClient-113"><span class="linenos">113</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient-114"><a href="#PerplexityClient-114"><span class="linenos">114</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient-115"><a href="#PerplexityClient-115"><span class="linenos">115</span></a><span class="sd">        A string with a response from the Perplexity service.</span>
+</span><span id="PerplexityClient-116"><a href="#PerplexityClient-116"><span class="linenos">116</span></a>
+</span><span id="PerplexityClient-117"><a href="#PerplexityClient-117"><span class="linenos">117</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient-118"><a href="#PerplexityClient-118"><span class="linenos">118</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient-119"><a href="#PerplexityClient-119"><span class="linenos">119</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient-120"><a href="#PerplexityClient-120"><span class="linenos">120</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient-121"><a href="#PerplexityClient-121"><span class="linenos">121</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient-122"><a href="#PerplexityClient-122"><span class="linenos">122</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient-123"><a href="#PerplexityClient-123"><span class="linenos">123</span></a>
+</span><span id="PerplexityClient-124"><a href="#PerplexityClient-124"><span class="linenos">124</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient-125"><a href="#PerplexityClient-125"><span class="linenos">125</span></a>
+</span><span id="PerplexityClient-126"><a href="#PerplexityClient-126"><span class="linenos">126</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient-127"><a href="#PerplexityClient-127"><span class="linenos">127</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient-128"><a href="#PerplexityClient-128"><span class="linenos">128</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-129"><a href="#PerplexityClient-129"><span class="linenos">129</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient-130"><a href="#PerplexityClient-130"><span class="linenos">130</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient-131"><a href="#PerplexityClient-131"><span class="linenos">131</span></a>
+</span><span id="PerplexityClient-132"><a href="#PerplexityClient-132"><span class="linenos">132</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient-133"><a href="#PerplexityClient-133"><span class="linenos">133</span></a>
+</span><span id="PerplexityClient-134"><a href="#PerplexityClient-134"><span class="linenos">134</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient-135"><a href="#PerplexityClient-135"><span class="linenos">135</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient-136"><a href="#PerplexityClient-136"><span class="linenos">136</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient-137"><a href="#PerplexityClient-137"><span class="linenos">137</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient-138"><a href="#PerplexityClient-138"><span class="linenos">138</span></a>
+</span><span id="PerplexityClient-139"><a href="#PerplexityClient-139"><span class="linenos">139</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span>
+</span><span id="PerplexityClient-140"><a href="#PerplexityClient-140"><span class="linenos">140</span></a>
+</span><span id="PerplexityClient-141"><a href="#PerplexityClient-141"><span class="linenos">141</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span><span id="PerplexityClient-142"><a href="#PerplexityClient-142"><span class="linenos">142</span></a>
+</span><span id="PerplexityClient-143"><a href="#PerplexityClient-143"><span class="linenos">143</span></a>
+</span><span id="PerplexityClient-144"><a href="#PerplexityClient-144"><span class="linenos">144</span></a>    <span class="k">def</span> <span class="nf">queryBatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">:</span>
+</span><span id="PerplexityClient-145"><a href="#PerplexityClient-145"><span class="linenos">145</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-146"><a href="#PerplexityClient-146"><span class="linenos">146</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="PerplexityClient-147"><a href="#PerplexityClient-147"><span class="linenos">147</span></a>
+</span><span id="PerplexityClient-148"><a href="#PerplexityClient-148"><span class="linenos">148</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient-149"><a href="#PerplexityClient-149"><span class="linenos">149</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient-150"><a href="#PerplexityClient-150"><span class="linenos">150</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient-151"><a href="#PerplexityClient-151"><span class="linenos">151</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient-152"><a href="#PerplexityClient-152"><span class="linenos">152</span></a>
+</span><span id="PerplexityClient-153"><a href="#PerplexityClient-153"><span class="linenos">153</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient-154"><a href="#PerplexityClient-154"><span class="linenos">154</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient-155"><a href="#PerplexityClient-155"><span class="linenos">155</span></a><span class="sd">        A tuple with a batch of 1 or more response strings.</span>
+</span><span id="PerplexityClient-156"><a href="#PerplexityClient-156"><span class="linenos">156</span></a>
+</span><span id="PerplexityClient-157"><a href="#PerplexityClient-157"><span class="linenos">157</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient-158"><a href="#PerplexityClient-158"><span class="linenos">158</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient-159"><a href="#PerplexityClient-159"><span class="linenos">159</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient-160"><a href="#PerplexityClient-160"><span class="linenos">160</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient-161"><a href="#PerplexityClient-161"><span class="linenos">161</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient-162"><a href="#PerplexityClient-162"><span class="linenos">162</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient-163"><a href="#PerplexityClient-163"><span class="linenos">163</span></a>
+</span><span id="PerplexityClient-164"><a href="#PerplexityClient-164"><span class="linenos">164</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient-165"><a href="#PerplexityClient-165"><span class="linenos">165</span></a>
+</span><span id="PerplexityClient-166"><a href="#PerplexityClient-166"><span class="linenos">166</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient-167"><a href="#PerplexityClient-167"><span class="linenos">167</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient-168"><a href="#PerplexityClient-168"><span class="linenos">168</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-169"><a href="#PerplexityClient-169"><span class="linenos">169</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient-170"><a href="#PerplexityClient-170"><span class="linenos">170</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient-171"><a href="#PerplexityClient-171"><span class="linenos">171</span></a>
+</span><span id="PerplexityClient-172"><a href="#PerplexityClient-172"><span class="linenos">172</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient-173"><a href="#PerplexityClient-173"><span class="linenos">173</span></a>
+</span><span id="PerplexityClient-174"><a href="#PerplexityClient-174"><span class="linenos">174</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient-175"><a href="#PerplexityClient-175"><span class="linenos">175</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient-176"><a href="#PerplexityClient-176"><span class="linenos">176</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient-177"><a href="#PerplexityClient-177"><span class="linenos">177</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient-178"><a href="#PerplexityClient-178"><span class="linenos">178</span></a>
+</span><span id="PerplexityClient-179"><a href="#PerplexityClient-179"><span class="linenos">179</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span> <span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">)</span>
+</span><span id="PerplexityClient-180"><a href="#PerplexityClient-180"><span class="linenos">180</span></a>
+</span><span id="PerplexityClient-181"><a href="#PerplexityClient-181"><span class="linenos">181</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span><span id="PerplexityClient-182"><a href="#PerplexityClient-182"><span class="linenos">182</span></a>
+</span><span id="PerplexityClient-183"><a href="#PerplexityClient-183"><span class="linenos">183</span></a>
+</span><span id="PerplexityClient-184"><a href="#PerplexityClient-184"><span class="linenos">184</span></a>    <span class="k">def</span> <span class="nf">queryStreamable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Responses</span><span class="p">:</span>
+</span><span id="PerplexityClient-185"><a href="#PerplexityClient-185"><span class="linenos">185</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-186"><a href="#PerplexityClient-186"><span class="linenos">186</span></a><span class="sd">        Send a query and return a long, streamable response.</span>
+</span><span id="PerplexityClient-187"><a href="#PerplexityClient-187"><span class="linenos">187</span></a>
+</span><span id="PerplexityClient-188"><a href="#PerplexityClient-188"><span class="linenos">188</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient-189"><a href="#PerplexityClient-189"><span class="linenos">189</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient-190"><a href="#PerplexityClient-190"><span class="linenos">190</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient-191"><a href="#PerplexityClient-191"><span class="linenos">191</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient-192"><a href="#PerplexityClient-192"><span class="linenos">192</span></a>
+</span><span id="PerplexityClient-193"><a href="#PerplexityClient-193"><span class="linenos">193</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient-194"><a href="#PerplexityClient-194"><span class="linenos">194</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient-195"><a href="#PerplexityClient-195"><span class="linenos">195</span></a><span class="sd">        Returns a `perplexipy.Responses` object for streaming the textual</span>
+</span><span id="PerplexityClient-196"><a href="#PerplexityClient-196"><span class="linenos">196</span></a><span class="sd">        responses from the client.  The response strips all metadata and returns</span>
+</span><span id="PerplexityClient-197"><a href="#PerplexityClient-197"><span class="linenos">197</span></a><span class="sd">        only content strings, for simpler and easier integration.</span>
+</span><span id="PerplexityClient-198"><a href="#PerplexityClient-198"><span class="linenos">198</span></a>
+</span><span id="PerplexityClient-199"><a href="#PerplexityClient-199"><span class="linenos">199</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient-200"><a href="#PerplexityClient-200"><span class="linenos">200</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient-201"><a href="#PerplexityClient-201"><span class="linenos">201</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient-202"><a href="#PerplexityClient-202"><span class="linenos">202</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient-203"><a href="#PerplexityClient-203"><span class="linenos">203</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient-204"><a href="#PerplexityClient-204"><span class="linenos">204</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient-205"><a href="#PerplexityClient-205"><span class="linenos">205</span></a>
+</span><span id="PerplexityClient-206"><a href="#PerplexityClient-206"><span class="linenos">206</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient-207"><a href="#PerplexityClient-207"><span class="linenos">207</span></a>
+</span><span id="PerplexityClient-208"><a href="#PerplexityClient-208"><span class="linenos">208</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient-209"><a href="#PerplexityClient-209"><span class="linenos">209</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient-210"><a href="#PerplexityClient-210"><span class="linenos">210</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-211"><a href="#PerplexityClient-211"><span class="linenos">211</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient-212"><a href="#PerplexityClient-212"><span class="linenos">212</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient-213"><a href="#PerplexityClient-213"><span class="linenos">213</span></a>
+</span><span id="PerplexityClient-214"><a href="#PerplexityClient-214"><span class="linenos">214</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient-215"><a href="#PerplexityClient-215"><span class="linenos">215</span></a>
+</span><span id="PerplexityClient-216"><a href="#PerplexityClient-216"><span class="linenos">216</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient-217"><a href="#PerplexityClient-217"><span class="linenos">217</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient-218"><a href="#PerplexityClient-218"><span class="linenos">218</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient-219"><a href="#PerplexityClient-219"><span class="linenos">219</span></a>            <span class="n">stream</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
+</span><span id="PerplexityClient-220"><a href="#PerplexityClient-220"><span class="linenos">220</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient-221"><a href="#PerplexityClient-221"><span class="linenos">221</span></a>
+</span><span id="PerplexityClient-222"><a href="#PerplexityClient-222"><span class="linenos">222</span></a>        <span class="k">return</span> <span class="n">Responses</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
+</span><span id="PerplexityClient-223"><a href="#PerplexityClient-223"><span class="linenos">223</span></a>
+</span><span id="PerplexityClient-224"><a href="#PerplexityClient-224"><span class="linenos">224</span></a>
+</span><span id="PerplexityClient-225"><a href="#PerplexityClient-225"><span class="linenos">225</span></a>    <span class="nd">@property</span>
+</span><span id="PerplexityClient-226"><a href="#PerplexityClient-226"><span class="linenos">226</span></a>    <span class="k">def</span> <span class="nf">models</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="PerplexityClient-227"><a href="#PerplexityClient-227"><span class="linenos">227</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-228"><a href="#PerplexityClient-228"><span class="linenos">228</span></a><span class="sd">        Provide a dictionary of the models supported by Perplexity listed in:</span>
+</span><span id="PerplexityClient-229"><a href="#PerplexityClient-229"><span class="linenos">229</span></a>
+</span><span id="PerplexityClient-230"><a href="#PerplexityClient-230"><span class="linenos">230</span></a><span class="sd">        https://docs.perplexity.ai/docs/model-cards</span>
+</span><span id="PerplexityClient-231"><a href="#PerplexityClient-231"><span class="linenos">231</span></a>
+</span><span id="PerplexityClient-232"><a href="#PerplexityClient-232"><span class="linenos">232</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient-233"><a href="#PerplexityClient-233"><span class="linenos">233</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient-234"><a href="#PerplexityClient-234"><span class="linenos">234</span></a><span class="sd">        A dictionary of supported models as the key, with a `perplexypy.ModelInfo`</span>
+</span><span id="PerplexityClient-235"><a href="#PerplexityClient-235"><span class="linenos">235</span></a><span class="sd">        named tuple with the model capabilities description.  The model</span>
+</span><span id="PerplexityClient-236"><a href="#PerplexityClient-236"><span class="linenos">236</span></a><span class="sd">        information attributes are:</span>
+</span><span id="PerplexityClient-237"><a href="#PerplexityClient-237"><span class="linenos">237</span></a>
+</span><span id="PerplexityClient-238"><a href="#PerplexityClient-238"><span class="linenos">238</span></a><span class="sd">        - `parameterCount`</span>
+</span><span id="PerplexityClient-239"><a href="#PerplexityClient-239"><span class="linenos">239</span></a><span class="sd">        - `contextLength`</span>
+</span><span id="PerplexityClient-240"><a href="#PerplexityClient-240"><span class="linenos">240</span></a><span class="sd">        - `modelType`</span>
+</span><span id="PerplexityClient-241"><a href="#PerplexityClient-241"><span class="linenos">241</span></a><span class="sd">        - `availability`</span>
+</span><span id="PerplexityClient-242"><a href="#PerplexityClient-242"><span class="linenos">242</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-243"><a href="#PerplexityClient-243"><span class="linenos">243</span></a>        <span class="n">supportedModels</span> <span class="o">=</span> <span class="p">{</span>
+</span><span id="PerplexityClient-244"><a href="#PerplexityClient-244"><span class="linenos">244</span></a>            <span class="s1">&#39;codellama-70b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;70B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-245"><a href="#PerplexityClient-245"><span class="linenos">245</span></a>            <span class="s1">&#39;mistral-7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-246"><a href="#PerplexityClient-246"><span class="linenos">246</span></a>            <span class="s1">&#39;mixtral-8x7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-247"><a href="#PerplexityClient-247"><span class="linenos">247</span></a>            <span class="s1">&#39;sonar-medium-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16348</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-248"><a href="#PerplexityClient-248"><span class="linenos">248</span></a>            <span class="s1">&#39;sonar-medium-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-249"><a href="#PerplexityClient-249"><span class="linenos">249</span></a>            <span class="s1">&#39;sonar-small-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-250"><a href="#PerplexityClient-250"><span class="linenos">250</span></a>            <span class="s1">&#39;sonar-small-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient-251"><a href="#PerplexityClient-251"><span class="linenos">251</span></a>        <span class="p">}</span>
+</span><span id="PerplexityClient-252"><a href="#PerplexityClient-252"><span class="linenos">252</span></a>
+</span><span id="PerplexityClient-253"><a href="#PerplexityClient-253"><span class="linenos">253</span></a>        <span class="k">return</span> <span class="n">supportedModels</span>
+</span><span id="PerplexityClient-254"><a href="#PerplexityClient-254"><span class="linenos">254</span></a>
+</span><span id="PerplexityClient-255"><a href="#PerplexityClient-255"><span class="linenos">255</span></a>
+</span><span id="PerplexityClient-256"><a href="#PerplexityClient-256"><span class="linenos">256</span></a>    <span class="nd">@property</span>
+</span><span id="PerplexityClient-257"><a href="#PerplexityClient-257"><span class="linenos">257</span></a>    <span class="k">def</span> <span class="nf">model</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="PerplexityClient-258"><a href="#PerplexityClient-258"><span class="linenos">258</span></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_model</span>
+</span><span id="PerplexityClient-259"><a href="#PerplexityClient-259"><span class="linenos">259</span></a>
+</span><span id="PerplexityClient-260"><a href="#PerplexityClient-260"><span class="linenos">260</span></a>    <span class="nd">@model</span><span class="o">.</span><span class="n">setter</span>
+</span><span id="PerplexityClient-261"><a href="#PerplexityClient-261"><span class="linenos">261</span></a>    <span class="k">def</span> <span class="nf">model</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
+</span><span id="PerplexityClient-262"><a href="#PerplexityClient-262"><span class="linenos">262</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-263"><a href="#PerplexityClient-263"><span class="linenos">263</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient-264"><a href="#PerplexityClient-264"><span class="linenos">264</span></a>        <span class="n">models</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">models</span><span class="o">.</span><span class="n">keys</span><span class="p">()</span>
+</span><span id="PerplexityClient-265"><a href="#PerplexityClient-265"><span class="linenos">265</span></a>        <span class="k">if</span> <span class="n">value</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">models</span><span class="p">:</span>
+</span><span id="PerplexityClient-266"><a href="#PerplexityClient-266"><span class="linenos">266</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;value = </span><span class="si">%s</span><span class="s1"> error; supported models: </span><span class="si">%s</span><span class="s1">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="s1">&#39;, &#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">models</span><span class="p">)))</span>
+</span><span id="PerplexityClient-267"><a href="#PerplexityClient-267"><span class="linenos">267</span></a>
+</span><span id="PerplexityClient-268"><a href="#PerplexityClient-268"><span class="linenos">268</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">value</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>PerplexityClient objects encapsulate all the API functionality.  They can be
+instantiated across multiple contexts, each keeping its own state.</p>
+</div>
+
+
+                            <div id="PerplexityClient.__init__" class="classattr">
+                                        <input id="PerplexityClient.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="name">PerplexityClient</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">key</span><span class="o">=</span><span class="s1">&#39;&#39;</span>, </span><span class="param"><span class="n">endpoint</span><span class="o">=</span><span class="s1">&#39;https://api.perplexity.ai&#39;</span></span>)</span>
+
+                <label class="view-source-button" for="PerplexityClient.__init__-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.__init__"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.__init__-58"><a href="#PerplexityClient.__init__-58"><span class="linenos"> 58</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_KEY</span><span class="p">,</span> <span class="n">endpoint</span> <span class="o">=</span> <span class="n">PERPLEXITY_API_URL</span><span class="p">):</span>
+</span><span id="PerplexityClient.__init__-59"><a href="#PerplexityClient.__init__-59"><span class="linenos"> 59</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.__init__-60"><a href="#PerplexityClient.__init__-60"><span class="linenos"> 60</span></a><span class="sd">        Create a new instance of `perplexipy.PerplexityClient` using the API</span>
+</span><span id="PerplexityClient.__init__-61"><a href="#PerplexityClient.__init__-61"><span class="linenos"> 61</span></a><span class="sd">        `key` to connect to the corresponding `endpoint`.</span>
+</span><span id="PerplexityClient.__init__-62"><a href="#PerplexityClient.__init__-62"><span class="linenos"> 62</span></a>
+</span><span id="PerplexityClient.__init__-63"><a href="#PerplexityClient.__init__-63"><span class="linenos"> 63</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient.__init__-64"><a href="#PerplexityClient.__init__-64"><span class="linenos"> 64</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient.__init__-65"><a href="#PerplexityClient.__init__-65"><span class="linenos"> 65</span></a><span class="sd">            key</span>
+</span><span id="PerplexityClient.__init__-66"><a href="#PerplexityClient.__init__-66"><span class="linenos"> 66</span></a><span class="sd">        A valid API key string.  If not present, it defaults to `perplexipy.PERPLEXITY_API_KEY`.</span>
+</span><span id="PerplexityClient.__init__-67"><a href="#PerplexityClient.__init__-67"><span class="linenos"> 67</span></a>
+</span><span id="PerplexityClient.__init__-68"><a href="#PerplexityClient.__init__-68"><span class="linenos"> 68</span></a><span class="sd">            endpoint</span>
+</span><span id="PerplexityClient.__init__-69"><a href="#PerplexityClient.__init__-69"><span class="linenos"> 69</span></a><span class="sd">        An string representing a URL to the Perplexity API.</span>
+</span><span id="PerplexityClient.__init__-70"><a href="#PerplexityClient.__init__-70"><span class="linenos"> 70</span></a>
+</span><span id="PerplexityClient.__init__-71"><a href="#PerplexityClient.__init__-71"><span class="linenos"> 71</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient.__init__-72"><a href="#PerplexityClient.__init__-72"><span class="linenos"> 72</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient.__init__-73"><a href="#PerplexityClient.__init__-73"><span class="linenos"> 73</span></a><span class="sd">        An instance of `perplexipy.PerplexityClient` if successful.</span>
+</span><span id="PerplexityClient.__init__-74"><a href="#PerplexityClient.__init__-74"><span class="linenos"> 74</span></a>
+</span><span id="PerplexityClient.__init__-75"><a href="#PerplexityClient.__init__-75"><span class="linenos"> 75</span></a><span class="sd">        Attributes:</span>
+</span><span id="PerplexityClient.__init__-76"><a href="#PerplexityClient.__init__-76"><span class="linenos"> 76</span></a>
+</span><span id="PerplexityClient.__init__-77"><a href="#PerplexityClient.__init__-77"><span class="linenos"> 77</span></a><span class="sd">        `model` - the current model to use in queries, user configurable.</span>
+</span><span id="PerplexityClient.__init__-78"><a href="#PerplexityClient.__init__-78"><span class="linenos"> 78</span></a>
+</span><span id="PerplexityClient.__init__-79"><a href="#PerplexityClient.__init__-79"><span class="linenos"> 79</span></a><span class="sd">        The role is fixed to `&quot;user&quot;` for Perplexity calls, per the API</span>
+</span><span id="PerplexityClient.__init__-80"><a href="#PerplexityClient.__init__-80"><span class="linenos"> 80</span></a><span class="sd">        recommendations.</span>
+</span><span id="PerplexityClient.__init__-81"><a href="#PerplexityClient.__init__-81"><span class="linenos"> 81</span></a>
+</span><span id="PerplexityClient.__init__-82"><a href="#PerplexityClient.__init__-82"><span class="linenos"> 82</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient.__init__-83"><a href="#PerplexityClient.__init__-83"><span class="linenos"> 83</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient.__init__-84"><a href="#PerplexityClient.__init__-84"><span class="linenos"> 84</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient.__init__-85"><a href="#PerplexityClient.__init__-85"><span class="linenos"> 85</span></a><span class="sd">        If the API key is empty, or doesn&#39;t match one of the valid API prefixes</span>
+</span><span id="PerplexityClient.__init__-86"><a href="#PerplexityClient.__init__-86"><span class="linenos"> 86</span></a><span class="sd">        per the documentation.</span>
+</span><span id="PerplexityClient.__init__-87"><a href="#PerplexityClient.__init__-87"><span class="linenos"> 87</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.__init__-88"><a href="#PerplexityClient.__init__-88"><span class="linenos"> 88</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="PerplexityClient.__init__-89"><a href="#PerplexityClient.__init__-89"><span class="linenos"> 89</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;Provide a valid key argument during instantiation&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient.__init__-90"><a href="#PerplexityClient.__init__-90"><span class="linenos"> 90</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="s1">&#39;pplx-&#39;</span> <span class="ow">in</span> <span class="n">key</span><span class="p">:</span>
+</span><span id="PerplexityClient.__init__-91"><a href="#PerplexityClient.__init__-91"><span class="linenos"> 91</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;The key </span><span class="si">%s</span><span class="s1"> i missing the pplx- prefix - invalid API key&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient.__init__-92"><a href="#PerplexityClient.__init__-92"><span class="linenos"> 92</span></a>
+</span><span id="PerplexityClient.__init__-93"><a href="#PerplexityClient.__init__-93"><span class="linenos"> 93</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span> <span class="o">=</span> <span class="n">endpoint</span>
+</span><span id="PerplexityClient.__init__-94"><a href="#PerplexityClient.__init__-94"><span class="linenos"> 94</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_key</span> <span class="o">=</span> <span class="n">key</span>
+</span><span id="PerplexityClient.__init__-95"><a href="#PerplexityClient.__init__-95"><span class="linenos"> 95</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_role</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_ROLE</span>
+</span><span id="PerplexityClient.__init__-96"><a href="#PerplexityClient.__init__-96"><span class="linenos"> 96</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_model</span> <span class="o">=</span> <span class="n">PERPLEXITY_DEFAULT_MODEL</span>
+</span><span id="PerplexityClient.__init__-97"><a href="#PerplexityClient.__init__-97"><span class="linenos"> 97</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_client</span> <span class="o">=</span> <span class="n">OpenAI</span><span class="p">(</span>
+</span><span id="PerplexityClient.__init__-98"><a href="#PerplexityClient.__init__-98"><span class="linenos"> 98</span></a>            <span class="n">api_key</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_key</span><span class="p">,</span>
+</span><span id="PerplexityClient.__init__-99"><a href="#PerplexityClient.__init__-99"><span class="linenos"> 99</span></a>            <span class="n">base_url</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_endpoint</span><span class="p">,</span>
+</span><span id="PerplexityClient.__init__-100"><a href="#PerplexityClient.__init__-100"><span class="linenos">100</span></a>            <span class="n">timeout</span> <span class="o">=</span> <span class="n">PERPLEXITY_TIMEOUT</span><span class="p">,</span>
+</span><span id="PerplexityClient.__init__-101"><a href="#PerplexityClient.__init__-101"><span class="linenos">101</span></a>        <span class="p">)</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Create a new instance of <code><a href="#PerplexityClient">PerplexityClient</a></code> using the API
+<code>key</code> to connect to the corresponding <code>endpoint</code>.</p>
+
+<h2 id="arguments">Arguments</h2>
+
+<pre><code>key
+</code></pre>
+
+<p>A valid API key string.  If not present, it defaults to <code><a href="#PERPLEXITY_API_KEY">PERPLEXITY_API_KEY</a></code>.</p>
+
+<pre><code>endpoint
+</code></pre>
+
+<p>An string representing a URL to the Perplexity API.</p>
+
+<h2 id="returns">Returns</h2>
+
+<p>An instance of <code><a href="#PerplexityClient">PerplexityClient</a></code> if successful.</p>
+
+<p>Attributes:</p>
+
+<p><code><a href="#PerplexityClient.model">model</a></code> - the current model to use in queries, user configurable.</p>
+
+<p>The role is fixed to <code>"user"</code> for Perplexity calls, per the API
+recommendations.</p>
+
+<h2 id="raises">Raises</h2>
+
+<pre><code>PerplexityClientError
+</code></pre>
+
+<p>If the API key is empty, or doesn't match one of the valid API prefixes
+per the documentation.</p>
+</div>
+
+
+                            </div>
+                            <div id="PerplexityClient.query" class="classattr">
+                                        <input id="PerplexityClient.query-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="def">def</span>
+        <span class="name">query</span><span class="signature pdoc-code condensed">(<span class="param"><span class="bp">self</span>, </span><span class="param"><span class="n">query</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="nb">str</span>:</span></span>
+
+                <label class="view-source-button" for="PerplexityClient.query-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.query"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.query-104"><a href="#PerplexityClient.query-104"><span class="linenos">104</span></a>    <span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="PerplexityClient.query-105"><a href="#PerplexityClient.query-105"><span class="linenos">105</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.query-106"><a href="#PerplexityClient.query-106"><span class="linenos">106</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="PerplexityClient.query-107"><a href="#PerplexityClient.query-107"><span class="linenos">107</span></a>
+</span><span id="PerplexityClient.query-108"><a href="#PerplexityClient.query-108"><span class="linenos">108</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient.query-109"><a href="#PerplexityClient.query-109"><span class="linenos">109</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient.query-110"><a href="#PerplexityClient.query-110"><span class="linenos">110</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient.query-111"><a href="#PerplexityClient.query-111"><span class="linenos">111</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient.query-112"><a href="#PerplexityClient.query-112"><span class="linenos">112</span></a>
+</span><span id="PerplexityClient.query-113"><a href="#PerplexityClient.query-113"><span class="linenos">113</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient.query-114"><a href="#PerplexityClient.query-114"><span class="linenos">114</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient.query-115"><a href="#PerplexityClient.query-115"><span class="linenos">115</span></a><span class="sd">        A string with a response from the Perplexity service.</span>
+</span><span id="PerplexityClient.query-116"><a href="#PerplexityClient.query-116"><span class="linenos">116</span></a>
+</span><span id="PerplexityClient.query-117"><a href="#PerplexityClient.query-117"><span class="linenos">117</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient.query-118"><a href="#PerplexityClient.query-118"><span class="linenos">118</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient.query-119"><a href="#PerplexityClient.query-119"><span class="linenos">119</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient.query-120"><a href="#PerplexityClient.query-120"><span class="linenos">120</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient.query-121"><a href="#PerplexityClient.query-121"><span class="linenos">121</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient.query-122"><a href="#PerplexityClient.query-122"><span class="linenos">122</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient.query-123"><a href="#PerplexityClient.query-123"><span class="linenos">123</span></a>
+</span><span id="PerplexityClient.query-124"><a href="#PerplexityClient.query-124"><span class="linenos">124</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient.query-125"><a href="#PerplexityClient.query-125"><span class="linenos">125</span></a>
+</span><span id="PerplexityClient.query-126"><a href="#PerplexityClient.query-126"><span class="linenos">126</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient.query-127"><a href="#PerplexityClient.query-127"><span class="linenos">127</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient.query-128"><a href="#PerplexityClient.query-128"><span class="linenos">128</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.query-129"><a href="#PerplexityClient.query-129"><span class="linenos">129</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient.query-130"><a href="#PerplexityClient.query-130"><span class="linenos">130</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient.query-131"><a href="#PerplexityClient.query-131"><span class="linenos">131</span></a>
+</span><span id="PerplexityClient.query-132"><a href="#PerplexityClient.query-132"><span class="linenos">132</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient.query-133"><a href="#PerplexityClient.query-133"><span class="linenos">133</span></a>
+</span><span id="PerplexityClient.query-134"><a href="#PerplexityClient.query-134"><span class="linenos">134</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient.query-135"><a href="#PerplexityClient.query-135"><span class="linenos">135</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient.query-136"><a href="#PerplexityClient.query-136"><span class="linenos">136</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient.query-137"><a href="#PerplexityClient.query-137"><span class="linenos">137</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient.query-138"><a href="#PerplexityClient.query-138"><span class="linenos">138</span></a>
+</span><span id="PerplexityClient.query-139"><a href="#PerplexityClient.query-139"><span class="linenos">139</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span>
+</span><span id="PerplexityClient.query-140"><a href="#PerplexityClient.query-140"><span class="linenos">140</span></a>
+</span><span id="PerplexityClient.query-141"><a href="#PerplexityClient.query-141"><span class="linenos">141</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Send a single message query to the service, receive a single response.</p>
+
+<h2 id="arguments">Arguments</h2>
+
+<pre><code>query
+</code></pre>
+
+<p>A string with the query in one of the model's supported languages.</p>
+
+<h2 id="returns">Returns</h2>
+
+<p>A string with a response from the Perplexity service.</p>
+
+<h2 id="raises">Raises</h2>
+
+<pre><code>Exception
+</code></pre>
+
+<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has
+something other than text data.  The error raised passes through
+whatever the API raised.</p>
+
+<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>
+
+<pre><code>PerplexityClientError
+</code></pre>
+
+<p>If the query is <code>None</code> or empty.</p>
+</div>
+
+
+                            </div>
+                            <div id="PerplexityClient.queryBatch" class="classattr">
+                                        <input id="PerplexityClient.queryBatch-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="def">def</span>
+        <span class="name">queryBatch</span><span class="signature pdoc-code condensed">(<span class="param"><span class="bp">self</span>, </span><span class="param"><span class="n">query</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="nb">tuple</span>:</span></span>
+
+                <label class="view-source-button" for="PerplexityClient.queryBatch-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.queryBatch"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.queryBatch-144"><a href="#PerplexityClient.queryBatch-144"><span class="linenos">144</span></a>    <span class="k">def</span> <span class="nf">queryBatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">:</span>
+</span><span id="PerplexityClient.queryBatch-145"><a href="#PerplexityClient.queryBatch-145"><span class="linenos">145</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.queryBatch-146"><a href="#PerplexityClient.queryBatch-146"><span class="linenos">146</span></a><span class="sd">        Send a single message query to the service, receive a single response.</span>
+</span><span id="PerplexityClient.queryBatch-147"><a href="#PerplexityClient.queryBatch-147"><span class="linenos">147</span></a>
+</span><span id="PerplexityClient.queryBatch-148"><a href="#PerplexityClient.queryBatch-148"><span class="linenos">148</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient.queryBatch-149"><a href="#PerplexityClient.queryBatch-149"><span class="linenos">149</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient.queryBatch-150"><a href="#PerplexityClient.queryBatch-150"><span class="linenos">150</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient.queryBatch-151"><a href="#PerplexityClient.queryBatch-151"><span class="linenos">151</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient.queryBatch-152"><a href="#PerplexityClient.queryBatch-152"><span class="linenos">152</span></a>
+</span><span id="PerplexityClient.queryBatch-153"><a href="#PerplexityClient.queryBatch-153"><span class="linenos">153</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient.queryBatch-154"><a href="#PerplexityClient.queryBatch-154"><span class="linenos">154</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient.queryBatch-155"><a href="#PerplexityClient.queryBatch-155"><span class="linenos">155</span></a><span class="sd">        A tuple with a batch of 1 or more response strings.</span>
+</span><span id="PerplexityClient.queryBatch-156"><a href="#PerplexityClient.queryBatch-156"><span class="linenos">156</span></a>
+</span><span id="PerplexityClient.queryBatch-157"><a href="#PerplexityClient.queryBatch-157"><span class="linenos">157</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient.queryBatch-158"><a href="#PerplexityClient.queryBatch-158"><span class="linenos">158</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient.queryBatch-159"><a href="#PerplexityClient.queryBatch-159"><span class="linenos">159</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient.queryBatch-160"><a href="#PerplexityClient.queryBatch-160"><span class="linenos">160</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient.queryBatch-161"><a href="#PerplexityClient.queryBatch-161"><span class="linenos">161</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient.queryBatch-162"><a href="#PerplexityClient.queryBatch-162"><span class="linenos">162</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient.queryBatch-163"><a href="#PerplexityClient.queryBatch-163"><span class="linenos">163</span></a>
+</span><span id="PerplexityClient.queryBatch-164"><a href="#PerplexityClient.queryBatch-164"><span class="linenos">164</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient.queryBatch-165"><a href="#PerplexityClient.queryBatch-165"><span class="linenos">165</span></a>
+</span><span id="PerplexityClient.queryBatch-166"><a href="#PerplexityClient.queryBatch-166"><span class="linenos">166</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient.queryBatch-167"><a href="#PerplexityClient.queryBatch-167"><span class="linenos">167</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient.queryBatch-168"><a href="#PerplexityClient.queryBatch-168"><span class="linenos">168</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.queryBatch-169"><a href="#PerplexityClient.queryBatch-169"><span class="linenos">169</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient.queryBatch-170"><a href="#PerplexityClient.queryBatch-170"><span class="linenos">170</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient.queryBatch-171"><a href="#PerplexityClient.queryBatch-171"><span class="linenos">171</span></a>
+</span><span id="PerplexityClient.queryBatch-172"><a href="#PerplexityClient.queryBatch-172"><span class="linenos">172</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient.queryBatch-173"><a href="#PerplexityClient.queryBatch-173"><span class="linenos">173</span></a>
+</span><span id="PerplexityClient.queryBatch-174"><a href="#PerplexityClient.queryBatch-174"><span class="linenos">174</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient.queryBatch-175"><a href="#PerplexityClient.queryBatch-175"><span class="linenos">175</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient.queryBatch-176"><a href="#PerplexityClient.queryBatch-176"><span class="linenos">176</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient.queryBatch-177"><a href="#PerplexityClient.queryBatch-177"><span class="linenos">177</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient.queryBatch-178"><a href="#PerplexityClient.queryBatch-178"><span class="linenos">178</span></a>
+</span><span id="PerplexityClient.queryBatch-179"><a href="#PerplexityClient.queryBatch-179"><span class="linenos">179</span></a>        <span class="n">result</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span> <span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="n">response</span><span class="o">.</span><span class="n">choices</span><span class="p">)</span>
+</span><span id="PerplexityClient.queryBatch-180"><a href="#PerplexityClient.queryBatch-180"><span class="linenos">180</span></a>
+</span><span id="PerplexityClient.queryBatch-181"><a href="#PerplexityClient.queryBatch-181"><span class="linenos">181</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Send a single message query to the service, receive a single response.</p>
+
+<h2 id="arguments">Arguments</h2>
+
+<pre><code>query
+</code></pre>
+
+<p>A string with the query in one of the model's supported languages.</p>
+
+<h2 id="returns">Returns</h2>
+
+<p>A tuple with a batch of 1 or more response strings.</p>
+
+<h2 id="raises">Raises</h2>
+
+<pre><code>Exception
+</code></pre>
+
+<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has
+something other than text data.  The error raised passes through
+whatever the API raised.</p>
+
+<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>
+
+<pre><code>PerplexityClientError
+</code></pre>
+
+<p>If the query is <code>None</code> or empty.</p>
+</div>
+
+
+                            </div>
+                            <div id="PerplexityClient.queryStreamable" class="classattr">
+                                        <input id="PerplexityClient.queryStreamable-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="def">def</span>
+        <span class="name">queryStreamable</span><span class="signature pdoc-code condensed">(<span class="param"><span class="bp">self</span>, </span><span class="param"><span class="n">query</span><span class="p">:</span> <span class="nb">str</span></span><span class="return-annotation">) -> <span class="n"><a href="perplexipy/responses.html#Responses">perplexipy.responses.Responses</a></span>:</span></span>
+
+                <label class="view-source-button" for="PerplexityClient.queryStreamable-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.queryStreamable"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.queryStreamable-184"><a href="#PerplexityClient.queryStreamable-184"><span class="linenos">184</span></a>    <span class="k">def</span> <span class="nf">queryStreamable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Responses</span><span class="p">:</span>
+</span><span id="PerplexityClient.queryStreamable-185"><a href="#PerplexityClient.queryStreamable-185"><span class="linenos">185</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.queryStreamable-186"><a href="#PerplexityClient.queryStreamable-186"><span class="linenos">186</span></a><span class="sd">        Send a query and return a long, streamable response.</span>
+</span><span id="PerplexityClient.queryStreamable-187"><a href="#PerplexityClient.queryStreamable-187"><span class="linenos">187</span></a>
+</span><span id="PerplexityClient.queryStreamable-188"><a href="#PerplexityClient.queryStreamable-188"><span class="linenos">188</span></a><span class="sd">        Arguments</span>
+</span><span id="PerplexityClient.queryStreamable-189"><a href="#PerplexityClient.queryStreamable-189"><span class="linenos">189</span></a><span class="sd">        ---------</span>
+</span><span id="PerplexityClient.queryStreamable-190"><a href="#PerplexityClient.queryStreamable-190"><span class="linenos">190</span></a><span class="sd">            query</span>
+</span><span id="PerplexityClient.queryStreamable-191"><a href="#PerplexityClient.queryStreamable-191"><span class="linenos">191</span></a><span class="sd">        A string with the query in one of the model&#39;s supported languages.</span>
+</span><span id="PerplexityClient.queryStreamable-192"><a href="#PerplexityClient.queryStreamable-192"><span class="linenos">192</span></a>
+</span><span id="PerplexityClient.queryStreamable-193"><a href="#PerplexityClient.queryStreamable-193"><span class="linenos">193</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient.queryStreamable-194"><a href="#PerplexityClient.queryStreamable-194"><span class="linenos">194</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient.queryStreamable-195"><a href="#PerplexityClient.queryStreamable-195"><span class="linenos">195</span></a><span class="sd">        Returns a `perplexipy.Responses` object for streaming the textual</span>
+</span><span id="PerplexityClient.queryStreamable-196"><a href="#PerplexityClient.queryStreamable-196"><span class="linenos">196</span></a><span class="sd">        responses from the client.  The response strips all metadata and returns</span>
+</span><span id="PerplexityClient.queryStreamable-197"><a href="#PerplexityClient.queryStreamable-197"><span class="linenos">197</span></a><span class="sd">        only content strings, for simpler and easier integration.</span>
+</span><span id="PerplexityClient.queryStreamable-198"><a href="#PerplexityClient.queryStreamable-198"><span class="linenos">198</span></a>
+</span><span id="PerplexityClient.queryStreamable-199"><a href="#PerplexityClient.queryStreamable-199"><span class="linenos">199</span></a><span class="sd">        Raises</span>
+</span><span id="PerplexityClient.queryStreamable-200"><a href="#PerplexityClient.queryStreamable-200"><span class="linenos">200</span></a><span class="sd">        ------</span>
+</span><span id="PerplexityClient.queryStreamable-201"><a href="#PerplexityClient.queryStreamable-201"><span class="linenos">201</span></a><span class="sd">            Exception</span>
+</span><span id="PerplexityClient.queryStreamable-202"><a href="#PerplexityClient.queryStreamable-202"><span class="linenos">202</span></a><span class="sd">        An `openai.BadRequestError` or similar if the query is malformed or has</span>
+</span><span id="PerplexityClient.queryStreamable-203"><a href="#PerplexityClient.queryStreamable-203"><span class="linenos">203</span></a><span class="sd">        something other than text data.  The error raised passes through</span>
+</span><span id="PerplexityClient.queryStreamable-204"><a href="#PerplexityClient.queryStreamable-204"><span class="linenos">204</span></a><span class="sd">        whatever the API raised.</span>
+</span><span id="PerplexityClient.queryStreamable-205"><a href="#PerplexityClient.queryStreamable-205"><span class="linenos">205</span></a>
+</span><span id="PerplexityClient.queryStreamable-206"><a href="#PerplexityClient.queryStreamable-206"><span class="linenos">206</span></a><span class="sd">        In most cases, the API returns `openai.BadRequestError`.</span>
+</span><span id="PerplexityClient.queryStreamable-207"><a href="#PerplexityClient.queryStreamable-207"><span class="linenos">207</span></a>
+</span><span id="PerplexityClient.queryStreamable-208"><a href="#PerplexityClient.queryStreamable-208"><span class="linenos">208</span></a><span class="sd">            PerplexityClientError</span>
+</span><span id="PerplexityClient.queryStreamable-209"><a href="#PerplexityClient.queryStreamable-209"><span class="linenos">209</span></a><span class="sd">        If the query is `None` or empty.</span>
+</span><span id="PerplexityClient.queryStreamable-210"><a href="#PerplexityClient.queryStreamable-210"><span class="linenos">210</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.queryStreamable-211"><a href="#PerplexityClient.queryStreamable-211"><span class="linenos">211</span></a>        <span class="k">if</span> <span class="ow">not</span> <span class="n">query</span><span class="p">:</span>
+</span><span id="PerplexityClient.queryStreamable-212"><a href="#PerplexityClient.queryStreamable-212"><span class="linenos">212</span></a>            <span class="k">raise</span> <span class="n">PerplexityClientError</span><span class="p">(</span><span class="s1">&#39;query cannot be None or empty&#39;</span><span class="p">)</span>
+</span><span id="PerplexityClient.queryStreamable-213"><a href="#PerplexityClient.queryStreamable-213"><span class="linenos">213</span></a>
+</span><span id="PerplexityClient.queryStreamable-214"><a href="#PerplexityClient.queryStreamable-214"><span class="linenos">214</span></a>        <span class="n">messages</span> <span class="o">=</span> <span class="p">[</span> <span class="p">{</span> <span class="s1">&#39;role&#39;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">_role</span><span class="p">,</span> <span class="s1">&#39;content&#39;</span><span class="p">:</span> <span class="n">query</span><span class="p">,</span> <span class="p">},</span> <span class="p">]</span>
+</span><span id="PerplexityClient.queryStreamable-215"><a href="#PerplexityClient.queryStreamable-215"><span class="linenos">215</span></a>
+</span><span id="PerplexityClient.queryStreamable-216"><a href="#PerplexityClient.queryStreamable-216"><span class="linenos">216</span></a>        <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_client</span><span class="o">.</span><span class="n">chat</span><span class="o">.</span><span class="n">completions</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
+</span><span id="PerplexityClient.queryStreamable-217"><a href="#PerplexityClient.queryStreamable-217"><span class="linenos">217</span></a>            <span class="n">model</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">model</span><span class="p">,</span>
+</span><span id="PerplexityClient.queryStreamable-218"><a href="#PerplexityClient.queryStreamable-218"><span class="linenos">218</span></a>            <span class="n">messages</span> <span class="o">=</span> <span class="n">messages</span><span class="p">,</span>
+</span><span id="PerplexityClient.queryStreamable-219"><a href="#PerplexityClient.queryStreamable-219"><span class="linenos">219</span></a>            <span class="n">stream</span> <span class="o">=</span> <span class="kc">True</span><span class="p">,</span>
+</span><span id="PerplexityClient.queryStreamable-220"><a href="#PerplexityClient.queryStreamable-220"><span class="linenos">220</span></a>        <span class="p">)</span>
+</span><span id="PerplexityClient.queryStreamable-221"><a href="#PerplexityClient.queryStreamable-221"><span class="linenos">221</span></a>
+</span><span id="PerplexityClient.queryStreamable-222"><a href="#PerplexityClient.queryStreamable-222"><span class="linenos">222</span></a>        <span class="k">return</span> <span class="n">Responses</span><span class="p">(</span><span class="n">response</span><span class="p">)</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Send a query and return a long, streamable response.</p>
+
+<h2 id="arguments">Arguments</h2>
+
+<pre><code>query
+</code></pre>
+
+<p>A string with the query in one of the model's supported languages.</p>
+
+<h2 id="returns">Returns</h2>
+
+<p>Returns a <code>perplexipy.Responses</code> object for streaming the textual
+responses from the client.  The response strips all metadata and returns
+only content strings, for simpler and easier integration.</p>
+
+<h2 id="raises">Raises</h2>
+
+<pre><code>Exception
+</code></pre>
+
+<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has
+something other than text data.  The error raised passes through
+whatever the API raised.</p>
+
+<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>
+
+<pre><code>PerplexityClientError
+</code></pre>
+
+<p>If the query is <code>None</code> or empty.</p>
+</div>
+
+
+                            </div>
+                            <div id="PerplexityClient.models" class="classattr">
+                                        <input id="PerplexityClient.models-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr variable">
+            <span class="name">models</span>
+
+                <label class="view-source-button" for="PerplexityClient.models-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.models"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.models-225"><a href="#PerplexityClient.models-225"><span class="linenos">225</span></a>    <span class="nd">@property</span>
+</span><span id="PerplexityClient.models-226"><a href="#PerplexityClient.models-226"><span class="linenos">226</span></a>    <span class="k">def</span> <span class="nf">models</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="PerplexityClient.models-227"><a href="#PerplexityClient.models-227"><span class="linenos">227</span></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.models-228"><a href="#PerplexityClient.models-228"><span class="linenos">228</span></a><span class="sd">        Provide a dictionary of the models supported by Perplexity listed in:</span>
+</span><span id="PerplexityClient.models-229"><a href="#PerplexityClient.models-229"><span class="linenos">229</span></a>
+</span><span id="PerplexityClient.models-230"><a href="#PerplexityClient.models-230"><span class="linenos">230</span></a><span class="sd">        https://docs.perplexity.ai/docs/model-cards</span>
+</span><span id="PerplexityClient.models-231"><a href="#PerplexityClient.models-231"><span class="linenos">231</span></a>
+</span><span id="PerplexityClient.models-232"><a href="#PerplexityClient.models-232"><span class="linenos">232</span></a><span class="sd">        Returns</span>
+</span><span id="PerplexityClient.models-233"><a href="#PerplexityClient.models-233"><span class="linenos">233</span></a><span class="sd">        -------</span>
+</span><span id="PerplexityClient.models-234"><a href="#PerplexityClient.models-234"><span class="linenos">234</span></a><span class="sd">        A dictionary of supported models as the key, with a `perplexypy.ModelInfo`</span>
+</span><span id="PerplexityClient.models-235"><a href="#PerplexityClient.models-235"><span class="linenos">235</span></a><span class="sd">        named tuple with the model capabilities description.  The model</span>
+</span><span id="PerplexityClient.models-236"><a href="#PerplexityClient.models-236"><span class="linenos">236</span></a><span class="sd">        information attributes are:</span>
+</span><span id="PerplexityClient.models-237"><a href="#PerplexityClient.models-237"><span class="linenos">237</span></a>
+</span><span id="PerplexityClient.models-238"><a href="#PerplexityClient.models-238"><span class="linenos">238</span></a><span class="sd">        - `parameterCount`</span>
+</span><span id="PerplexityClient.models-239"><a href="#PerplexityClient.models-239"><span class="linenos">239</span></a><span class="sd">        - `contextLength`</span>
+</span><span id="PerplexityClient.models-240"><a href="#PerplexityClient.models-240"><span class="linenos">240</span></a><span class="sd">        - `modelType`</span>
+</span><span id="PerplexityClient.models-241"><a href="#PerplexityClient.models-241"><span class="linenos">241</span></a><span class="sd">        - `availability`</span>
+</span><span id="PerplexityClient.models-242"><a href="#PerplexityClient.models-242"><span class="linenos">242</span></a><span class="sd">        &quot;&quot;&quot;</span>
+</span><span id="PerplexityClient.models-243"><a href="#PerplexityClient.models-243"><span class="linenos">243</span></a>        <span class="n">supportedModels</span> <span class="o">=</span> <span class="p">{</span>
+</span><span id="PerplexityClient.models-244"><a href="#PerplexityClient.models-244"><span class="linenos">244</span></a>            <span class="s1">&#39;codellama-70b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;70B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-245"><a href="#PerplexityClient.models-245"><span class="linenos">245</span></a>            <span class="s1">&#39;mistral-7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-246"><a href="#PerplexityClient.models-246"><span class="linenos">246</span></a>            <span class="s1">&#39;mixtral-8x7b-instruct&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;open source&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-247"><a href="#PerplexityClient.models-247"><span class="linenos">247</span></a>            <span class="s1">&#39;sonar-medium-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">16348</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-248"><a href="#PerplexityClient.models-248"><span class="linenos">248</span></a>            <span class="s1">&#39;sonar-medium-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;8x7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-249"><a href="#PerplexityClient.models-249"><span class="linenos">249</span></a>            <span class="s1">&#39;sonar-small-chat&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">16384</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-250"><a href="#PerplexityClient.models-250"><span class="linenos">250</span></a>            <span class="s1">&#39;sonar-small-online&#39;</span><span class="p">:</span> <span class="n">ModelInfo</span><span class="p">(</span><span class="s1">&#39;7B&#39;</span><span class="p">,</span> <span class="mi">12000</span><span class="p">,</span> <span class="s1">&#39;chat completion&#39;</span><span class="p">,</span> <span class="s1">&#39;Perplexity&#39;</span><span class="p">,),</span>
+</span><span id="PerplexityClient.models-251"><a href="#PerplexityClient.models-251"><span class="linenos">251</span></a>        <span class="p">}</span>
+</span><span id="PerplexityClient.models-252"><a href="#PerplexityClient.models-252"><span class="linenos">252</span></a>
+</span><span id="PerplexityClient.models-253"><a href="#PerplexityClient.models-253"><span class="linenos">253</span></a>        <span class="k">return</span> <span class="n">supportedModels</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Provide a dictionary of the models supported by Perplexity listed in:</p>
+
+<p><a href="https://docs.perplexity.ai/docs/model-cards">https://docs.perplexity.ai/docs/model-cards</a></p>
+
+<h2 id="returns">Returns</h2>
+
+<p>A dictionary of supported models as the key, with a <code>perplexypy.ModelInfo</code>
+named tuple with the model capabilities description.  The model
+information attributes are:</p>
+
+<ul>
+<li><code>parameterCount</code></li>
+<li><code>contextLength</code></li>
+<li><code>modelType</code></li>
+<li><code>availability</code></li>
+</ul>
+</div>
+
+
+                            </div>
+                            <div id="PerplexityClient.model" class="classattr">
+                                        <input id="PerplexityClient.model-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr variable">
+            <span class="name">model</span><span class="annotation">: str</span>
+
+                <label class="view-source-button" for="PerplexityClient.model-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClient.model"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClient.model-256"><a href="#PerplexityClient.model-256"><span class="linenos">256</span></a>    <span class="nd">@property</span>
+</span><span id="PerplexityClient.model-257"><a href="#PerplexityClient.model-257"><span class="linenos">257</span></a>    <span class="k">def</span> <span class="nf">model</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
+</span><span id="PerplexityClient.model-258"><a href="#PerplexityClient.model-258"><span class="linenos">258</span></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_model</span>
+</span></pre></div>
+
+
+    
+
+                            </div>
+                </section>
+    </main>
+<script>
+    function escapeHTML(html) {
+        return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
+    }
+
+    const originalContent = document.querySelector("main.pdoc");
+    let currentContent = originalContent;
+
+    function setContent(innerHTML) {
+        let elem;
+        if (innerHTML) {
+            elem = document.createElement("main");
+            elem.classList.add("pdoc");
+            elem.innerHTML = innerHTML;
+        } else {
+            elem = originalContent;
+        }
+        if (currentContent !== elem) {
+            currentContent.replaceWith(elem);
+            currentContent = elem;
+        }
+    }
+
+    function getSearchTerm() {
+        return (new URL(window.location)).searchParams.get("search");
+    }
+
+    const searchBox = document.querySelector(".pdoc input[type=search]");
+    searchBox.addEventListener("input", function () {
+        let url = new URL(window.location);
+        if (searchBox.value.trim()) {
+            url.hash = "";
+            url.searchParams.set("search", searchBox.value);
+        } else {
+            url.searchParams.delete("search");
+        }
+        history.replaceState("", "", url.toString());
+        onInput();
+    });
+    window.addEventListener("popstate", onInput);
+
+
+    let search, searchErr;
+
+    async function initialize() {
+        try {
+            search = await new Promise((resolve, reject) => {
+                const script = document.createElement("script");
+                script.type = "text/javascript";
+                script.async = true;
+                script.onload = () => resolve(window.pdocSearch);
+                script.onerror = (e) => reject(e);
+                script.src = "search.js";
+                document.getElementsByTagName("head")[0].appendChild(script);
+            });
+        } catch (e) {
+            console.error("Cannot fetch pdoc search index");
+            searchErr = "Cannot fetch search index.";
+        }
+        onInput();
+
+        document.querySelector("nav.pdoc").addEventListener("click", e => {
+            if (e.target.hash) {
+                searchBox.value = "";
+                searchBox.dispatchEvent(new Event("input"));
+            }
+        });
+    }
+
+    function onInput() {
+        setContent((() => {
+            const term = getSearchTerm();
+            if (!term) {
+                return null
+            }
+            if (searchErr) {
+                return `<h3>Error: ${searchErr}</h3>`
+            }
+            if (!search) {
+                return "<h3>Searching...</h3>"
+            }
+
+            window.scrollTo({top: 0, left: 0, behavior: 'auto'});
+
+            const results = search(term);
+
+            let html;
+            if (results.length === 0) {
+                html = `No search results for '${escapeHTML(term)}'.`
+            } else {
+                html = `<h4>${results.length} search result${results.length > 1 ? "s" : ""} for '${escapeHTML(term)}'.</h4>`;
+            }
+            for (let result of results.slice(0, 10)) {
+                let doc = result.doc;
+                let url = `${doc.modulename.replaceAll(".", "/")}.html`;
+                if (doc.qualname) {
+                    url += `#${doc.qualname}`;
+                }
+
+                let heading;
+                switch (result.doc.kind) {
+                    case "function":
+                        if (doc.fullname.endsWith(".__init__")) {
+                            heading = `<span class="name">${doc.fullname.replace(/\.__init__$/, "")}</span>${doc.signature}`;
+                        } else {
+                            heading = `<span class="def">${doc.funcdef}</span> <span class="name">${doc.fullname}</span>${doc.signature}`;
+                        }
+                        break;
+                    case "class":
+                        heading = `<span class="def">class</span> <span class="name">${doc.fullname}</span>`;
+                        if (doc.bases)
+                            heading += `<wbr>(<span class="base">${doc.bases}</span>)`;
+                        heading += `:`;
+                        break;
+                    case "variable":
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        if (doc.annotation)
+                            heading += `<span class="annotation">${doc.annotation}</span>`;
+                        if (doc.default_value)
+                            heading += `<span class="default_value"> = ${doc.default_value}</span>`;
+                        break;
+                    default:
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        break;
+                }
+                html += `
+                        <section class="search-result">
+                        <a href="${url}" class="attr ${doc.kind}">${heading}</a>
+                        <div class="docstring">${doc.doc}</div>
+                        </section>
+                    `;
+
+            }
+            return html;
+        })());
+    }
+
+    if (getSearchTerm()) {
+        initialize();
+        searchBox.value = getSearchTerm();
+        onInput();
+    } else {
+        searchBox.addEventListener("focus", initialize, {once: true});
+    }
+
+    searchBox.addEventListener("keydown", e => {
+        if (["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) {
+            let focused = currentContent.querySelector(".search-result.focused");
+            if (!focused) {
+                currentContent.querySelector(".search-result").classList.add("focused");
+            } else if (
+                e.key === "ArrowDown"
+                && focused.nextElementSibling
+                && focused.nextElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.nextElementSibling.classList.add("focused");
+                focused.nextElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "ArrowUp"
+                && focused.previousElementSibling
+                && focused.previousElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.previousElementSibling.classList.add("focused");
+                focused.previousElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "Enter"
+            ) {
+                focused.querySelector("a").click();
+            }
+        }
+    });
+</script></body>
+</html>
\ No newline at end of file
diff --git a/docs/perplexipy/errors.html b/docs/perplexipy/errors.html
new file mode 100644
index 0000000..75ebb52
--- /dev/null
+++ b/docs/perplexipy/errors.html
@@ -0,0 +1,314 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="generator" content="pdoc 14.4.0"/>
+    <title>perplexipy.errors API documentation</title>
+            <link rel="icon" href="https://cime.net/upload_area/favicon.ico"/>
+
+    <style>/*! * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}</style>
+    <style>/*! syntax-highlighting.css */pre{line-height:125%;}span.linenos{color:inherit; background-color:transparent; padding-left:5px; padding-right:20px;}.pdoc-code .hll{background-color:#ffffcc}.pdoc-code{background:#f8f8f8;}.pdoc-code .c{color:#3D7B7B; font-style:italic}.pdoc-code .err{border:1px solid #FF0000}.pdoc-code .k{color:#008000; font-weight:bold}.pdoc-code .o{color:#666666}.pdoc-code .ch{color:#3D7B7B; font-style:italic}.pdoc-code .cm{color:#3D7B7B; font-style:italic}.pdoc-code .cp{color:#9C6500}.pdoc-code .cpf{color:#3D7B7B; font-style:italic}.pdoc-code .c1{color:#3D7B7B; font-style:italic}.pdoc-code .cs{color:#3D7B7B; font-style:italic}.pdoc-code .gd{color:#A00000}.pdoc-code .ge{font-style:italic}.pdoc-code .gr{color:#E40000}.pdoc-code .gh{color:#000080; font-weight:bold}.pdoc-code .gi{color:#008400}.pdoc-code .go{color:#717171}.pdoc-code .gp{color:#000080; font-weight:bold}.pdoc-code .gs{font-weight:bold}.pdoc-code .gu{color:#800080; font-weight:bold}.pdoc-code .gt{color:#0044DD}.pdoc-code .kc{color:#008000; font-weight:bold}.pdoc-code .kd{color:#008000; font-weight:bold}.pdoc-code .kn{color:#008000; font-weight:bold}.pdoc-code .kp{color:#008000}.pdoc-code .kr{color:#008000; font-weight:bold}.pdoc-code .kt{color:#B00040}.pdoc-code .m{color:#666666}.pdoc-code .s{color:#BA2121}.pdoc-code .na{color:#687822}.pdoc-code .nb{color:#008000}.pdoc-code .nc{color:#0000FF; font-weight:bold}.pdoc-code .no{color:#880000}.pdoc-code .nd{color:#AA22FF}.pdoc-code .ni{color:#717171; font-weight:bold}.pdoc-code .ne{color:#CB3F38; font-weight:bold}.pdoc-code .nf{color:#0000FF}.pdoc-code .nl{color:#767600}.pdoc-code .nn{color:#0000FF; font-weight:bold}.pdoc-code .nt{color:#008000; font-weight:bold}.pdoc-code .nv{color:#19177C}.pdoc-code .ow{color:#AA22FF; font-weight:bold}.pdoc-code .w{color:#bbbbbb}.pdoc-code .mb{color:#666666}.pdoc-code .mf{color:#666666}.pdoc-code .mh{color:#666666}.pdoc-code .mi{color:#666666}.pdoc-code .mo{color:#666666}.pdoc-code .sa{color:#BA2121}.pdoc-code .sb{color:#BA2121}.pdoc-code .sc{color:#BA2121}.pdoc-code .dl{color:#BA2121}.pdoc-code .sd{color:#BA2121; font-style:italic}.pdoc-code .s2{color:#BA2121}.pdoc-code .se{color:#AA5D1F; font-weight:bold}.pdoc-code .sh{color:#BA2121}.pdoc-code .si{color:#A45A77; font-weight:bold}.pdoc-code .sx{color:#008000}.pdoc-code .sr{color:#A45A77}.pdoc-code .s1{color:#BA2121}.pdoc-code .ss{color:#19177C}.pdoc-code .bp{color:#008000}.pdoc-code .fm{color:#0000FF}.pdoc-code .vc{color:#19177C}.pdoc-code .vg{color:#19177C}.pdoc-code .vi{color:#19177C}.pdoc-code .vm{color:#19177C}.pdoc-code .il{color:#666666}</style>
+    <style>/*! theme.css */:root{--pdoc-background:#fff;}.pdoc{--text:#212529;--muted:#6c757d;--link:#3660a5;--link-hover:#1659c5;--code:#f8f8f8;--active:#fff598;--accent:#eee;--accent2:#c1c1c1;--nav-hover:rgba(255, 255, 255, 0.5);--name:#0066BB;--def:#008800;--annotation:#007020;}</style>
+    <style>/*! layout.css */html, body{width:100%;height:100%;}html, main{scroll-behavior:smooth;}body{background-color:var(--pdoc-background);}@media (max-width:769px){#navtoggle{cursor:pointer;position:absolute;width:50px;height:40px;top:1rem;right:1rem;border-color:var(--text);color:var(--text);display:flex;opacity:0.8;z-index:999;}#navtoggle:hover{opacity:1;}#togglestate + div{display:none;}#togglestate:checked + div{display:inherit;}main, header{padding:2rem 3vw;}header + main{margin-top:-3rem;}.git-button{display:none !important;}nav input[type="search"]{max-width:77%;}nav input[type="search"]:first-child{margin-top:-6px;}nav input[type="search"]:valid ~ *{display:none !important;}}@media (min-width:770px){:root{--sidebar-width:clamp(12.5rem, 28vw, 22rem);}nav{position:fixed;overflow:auto;height:100vh;width:var(--sidebar-width);}main, header{padding:3rem 2rem 3rem calc(var(--sidebar-width) + 3rem);width:calc(54rem + var(--sidebar-width));max-width:100%;}header + main{margin-top:-4rem;}#navtoggle{display:none;}}#togglestate{position:absolute;height:0;opacity:0;}nav.pdoc{--pad:clamp(0.5rem, 2vw, 1.75rem);--indent:1.5rem;background-color:var(--accent);border-right:1px solid var(--accent2);box-shadow:0 0 20px rgba(50, 50, 50, .2) inset;padding:0 0 0 var(--pad);overflow-wrap:anywhere;scrollbar-width:thin; scrollbar-color:var(--accent2) transparent; z-index:1}nav.pdoc::-webkit-scrollbar{width:.4rem; }nav.pdoc::-webkit-scrollbar-thumb{background-color:var(--accent2); }nav.pdoc > div{padding:var(--pad) 0;}nav.pdoc .module-list-button{display:inline-flex;align-items:center;color:var(--text);border-color:var(--muted);margin-bottom:1rem;}nav.pdoc .module-list-button:hover{border-color:var(--text);}nav.pdoc input[type=search]{display:block;outline-offset:0;width:calc(100% - var(--pad));}nav.pdoc .logo{max-width:calc(100% - var(--pad));max-height:35vh;display:block;margin:0 auto 1rem;transform:translate(calc(-.5 * var(--pad)), 0);}nav.pdoc ul{list-style:none;padding-left:0;}nav.pdoc > div > ul{margin-left:calc(0px - var(--pad));}nav.pdoc li a{padding:.2rem 0 .2rem calc(var(--pad) + var(--indent));}nav.pdoc > div > ul > li > a{padding-left:var(--pad);}nav.pdoc li{transition:all 100ms;}nav.pdoc li:hover{background-color:var(--nav-hover);}nav.pdoc a, nav.pdoc a:hover{color:var(--text);}nav.pdoc a{display:block;}nav.pdoc > h2:first-of-type{margin-top:1.5rem;}nav.pdoc .class:before{content:"class ";color:var(--muted);}nav.pdoc .function:after{content:"()";color:var(--muted);}nav.pdoc footer:before{content:"";display:block;width:calc(100% - var(--pad));border-top:solid var(--accent2) 1px;margin-top:1.5rem;padding-top:.5rem;}nav.pdoc footer{font-size:small;}</style>
+    <style>/*! content.css */.pdoc{color:var(--text);box-sizing:border-box;line-height:1.5;background:none;}.pdoc .pdoc-button{cursor:pointer;display:inline-block;border:solid black 1px;border-radius:2px;font-size:.75rem;padding:calc(0.5em - 1px) 1em;transition:100ms all;}.pdoc .pdoc-alert{padding:1rem 1rem 1rem calc(1.5rem + 24px);border:1px solid transparent;border-radius:.25rem;background-repeat:no-repeat;background-position:1rem center;margin-bottom:1rem;}.pdoc .pdoc-alert > *:last-child{margin-bottom:0;}.pdoc .pdoc-alert-note {color:#084298;background-color:#cfe2ff;border-color:#b6d4fe;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23084298%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8%2016A8%208%200%201%200%208%200a8%208%200%200%200%200%2016zm.93-9.412-1%204.705c-.07.34.029.533.304.533.194%200%20.487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703%200-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381%202.29-.287zM8%205.5a1%201%200%201%201%200-2%201%201%200%200%201%200%202z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23664d03%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8.982%201.566a1.13%201.13%200%200%200-1.96%200L.165%2013.233c-.457.778.091%201.767.98%201.767h13.713c.889%200%201.438-.99.98-1.767L8.982%201.566zM8%205c.535%200%20.954.462.9.995l-.35%203.507a.552.552%200%200%201-1.1%200L7.1%205.995A.905.905%200%200%201%208%205zm.002%206a1%201%200%201%201%200%202%201%201%200%200%201%200-2z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23842029%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M5.52.359A.5.5%200%200%201%206%200h4a.5.5%200%200%201%20.474.658L8.694%206H12.5a.5.5%200%200%201%20.395.807l-7%209a.5.5%200%200%201-.873-.454L6.823%209.5H3.5a.5.5%200%200%201-.48-.641l2.5-8.5z%22/%3E%3C/svg%3E");}.pdoc .visually-hidden{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important;}.pdoc h1, .pdoc h2, .pdoc h3{font-weight:300;margin:.3em 0;padding:.2em 0;}.pdoc > section:not(.module-info) h1{font-size:1.5rem;font-weight:500;}.pdoc > section:not(.module-info) h2{font-size:1.4rem;font-weight:500;}.pdoc > section:not(.module-info) h3{font-size:1.3rem;font-weight:500;}.pdoc > section:not(.module-info) h4{font-size:1.2rem;}.pdoc > section:not(.module-info) h5{font-size:1.1rem;}.pdoc a{text-decoration:none;color:var(--link);}.pdoc a:hover{color:var(--link-hover);}.pdoc blockquote{margin-left:2rem;}.pdoc pre{border-top:1px solid var(--accent2);border-bottom:1px solid var(--accent2);margin-top:0;margin-bottom:1em;padding:.5rem 0 .5rem .5rem;overflow-x:auto;background-color:var(--code);}.pdoc code{color:var(--text);padding:.2em .4em;margin:0;font-size:85%;background-color:var(--accent);border-radius:6px;}.pdoc a > code{color:inherit;}.pdoc pre > code{display:inline-block;font-size:inherit;background:none;border:none;padding:0;}.pdoc > section:not(.module-info){margin-bottom:1.5rem;}.pdoc .modulename{margin-top:0;font-weight:bold;}.pdoc .modulename a{color:var(--link);transition:100ms all;}.pdoc .git-button{float:right;border:solid var(--link) 1px;}.pdoc .git-button:hover{background-color:var(--link);color:var(--pdoc-background);}.view-source-toggle-state,.view-source-toggle-state ~ .pdoc-code{display:none;}.view-source-toggle-state:checked ~ .pdoc-code{display:block;}.view-source-button{display:inline-block;float:right;font-size:.75rem;line-height:1.5rem;color:var(--muted);padding:0 .4rem 0 1.3rem;cursor:pointer;text-indent:-2px;}.view-source-button > span{visibility:hidden;}.module-info .view-source-button{float:none;display:flex;justify-content:flex-end;margin:-1.2rem .4rem -.2rem 0;}.view-source-button::before{position:absolute;content:"View Source";display:list-item;list-style-type:disclosure-closed;}.view-source-toggle-state:checked ~ .attr .view-source-button::before,.view-source-toggle-state:checked ~ .view-source-button::before{list-style-type:disclosure-open;}.pdoc .docstring{margin-bottom:1.5rem;}.pdoc section:not(.module-info) .docstring{margin-left:clamp(0rem, 5vw - 2rem, 1rem);}.pdoc .docstring .pdoc-code{margin-left:1em;margin-right:1em;}.pdoc h1:target,.pdoc h2:target,.pdoc h3:target,.pdoc h4:target,.pdoc h5:target,.pdoc h6:target,.pdoc .pdoc-code > pre > span:target{background-color:var(--active);box-shadow:-1rem 0 0 0 var(--active);}.pdoc .pdoc-code > pre > span:target{display:block;}.pdoc div:target > .attr,.pdoc section:target > .attr,.pdoc dd:target > a{background-color:var(--active);}.pdoc *{scroll-margin:2rem;}.pdoc .pdoc-code .linenos{user-select:none;}.pdoc .attr:hover{filter:contrast(0.95);}.pdoc section, .pdoc .classattr{position:relative;}.pdoc .headerlink{--width:clamp(1rem, 3vw, 2rem);position:absolute;top:0;left:calc(0rem - var(--width));transition:all 100ms ease-in-out;opacity:0;}.pdoc .headerlink::before{content:"#";display:block;text-align:center;width:var(--width);height:2.3rem;line-height:2.3rem;font-size:1.5rem;}.pdoc .attr:hover ~ .headerlink,.pdoc *:target > .headerlink,.pdoc .headerlink:hover{opacity:1;}.pdoc .attr{display:block;margin:.5rem 0 .5rem;padding:.4rem .4rem .4rem 1rem;background-color:var(--accent);overflow-x:auto;}.pdoc .classattr{margin-left:2rem;}.pdoc .name{color:var(--name);font-weight:bold;}.pdoc .def{color:var(--def);font-weight:bold;}.pdoc .signature{background-color:transparent;}.pdoc .param, .pdoc .return-annotation{white-space:pre;}.pdoc .signature.multiline .param{display:block;}.pdoc .signature.condensed .param{display:inline-block;}.pdoc .annotation{color:var(--annotation);}.pdoc .view-value-toggle-state,.pdoc .view-value-toggle-state ~ .default_value{display:none;}.pdoc .view-value-toggle-state:checked ~ .default_value{display:inherit;}.pdoc .view-value-button{font-size:.5rem;vertical-align:middle;border-style:dashed;margin-top:-0.1rem;}.pdoc .view-value-button:hover{background:white;}.pdoc .view-value-button::before{content:"show";text-align:center;width:2.2em;display:inline-block;}.pdoc .view-value-toggle-state:checked ~ .view-value-button::before{content:"hide";}.pdoc .inherited{margin-left:2rem;}.pdoc .inherited dt{font-weight:700;}.pdoc .inherited dt, .pdoc .inherited dd{display:inline;margin-left:0;margin-bottom:.5rem;}.pdoc .inherited dd:not(:last-child):after{content:", ";}.pdoc .inherited .class:before{content:"class ";}.pdoc .inherited .function a:after{content:"()";}.pdoc .search-result .docstring{overflow:auto;max-height:25vh;}.pdoc .search-result.focused > .attr{background-color:var(--active);}.pdoc .attribution{margin-top:2rem;display:block;opacity:0.5;transition:all 200ms;filter:grayscale(100%);}.pdoc .attribution:hover{opacity:1;filter:grayscale(0%);}.pdoc .attribution img{margin-left:5px;height:35px;vertical-align:middle;width:70px;transition:all 200ms;}.pdoc table{display:block;width:max-content;max-width:100%;overflow:auto;margin-bottom:1rem;}.pdoc table th{font-weight:600;}.pdoc table th, .pdoc table td{padding:6px 13px;border:1px solid var(--accent2);}</style>
+    <style>/*! custom.css */</style></head>
+<body>
+    <nav class="pdoc">
+        <label id="navtoggle" for="togglestate" class="pdoc-button"><svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke-linecap='round' stroke="currentColor" stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg></label>
+        <input id="togglestate" type="checkbox" aria-hidden="true" tabindex="-1">
+        <div>            <a class="pdoc-button module-list-button" href="../perplexipy.html">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-left" viewBox="0 0 16 16">
+  <path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0v-2z"/>
+  <path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
+</svg>                &nbsp;perplexipy</a>
+
+            <img src="https://images2.imgbox.com/57/94/AsI1WSfy_o.png" class="logo" alt="project logo"/>
+
+            <input type="search" placeholder="Search..." role="searchbox" aria-label="search"
+                   pattern=".+" required>
+
+
+
+            <h2>API Documentation</h2>
+                <ul class="memberlist">
+            <li>
+                    <a class="class" href="#PerplexityClientError">PerplexityClientError</a>
+                            <ul class="memberlist">
+                        <li>
+                                <a class="function" href="#PerplexityClientError.__init__">PerplexityClientError</a>
+                        </li>
+                </ul>
+
+            </li>
+    </ul>
+
+
+
+        <a class="attribution" title="pdoc: Python API documentation generator" href="https://pdoc.dev" target="_blank">
+            built with <span class="visually-hidden">pdoc</span><img
+                alt="pdoc logo"
+                src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20role%3D%22img%22%20aria-label%3D%22pdoc%20logo%22%20width%3D%22300%22%20height%3D%22150%22%20viewBox%3D%22-1%200%2060%2030%22%3E%3Ctitle%3Epdoc%3C/title%3E%3Cpath%20d%3D%22M29.621%2021.293c-.011-.273-.214-.475-.511-.481a.5.5%200%200%200-.489.503l-.044%201.393c-.097.551-.695%201.215-1.566%201.704-.577.428-1.306.486-2.193.182-1.426-.617-2.467-1.654-3.304-2.487l-.173-.172a3.43%203.43%200%200%200-.365-.306.49.49%200%200%200-.286-.196c-1.718-1.06-4.931-1.47-7.353.191l-.219.15c-1.707%201.187-3.413%202.131-4.328%201.03-.02-.027-.49-.685-.141-1.763.233-.721.546-2.408.772-4.076.042-.09.067-.187.046-.288.166-1.347.277-2.625.241-3.351%201.378-1.008%202.271-2.586%202.271-4.362%200-.976-.272-1.935-.788-2.774-.057-.094-.122-.18-.184-.268.033-.167.052-.339.052-.516%200-1.477-1.202-2.679-2.679-2.679-.791%200-1.496.352-1.987.9a6.3%206.3%200%200%200-1.001.029c-.492-.564-1.207-.929-2.012-.929-1.477%200-2.679%201.202-2.679%202.679A2.65%202.65%200%200%200%20.97%206.554c-.383.747-.595%201.572-.595%202.41%200%202.311%201.507%204.29%203.635%205.107-.037.699-.147%202.27-.423%203.294l-.137.461c-.622%202.042-2.515%208.257%201.727%2010.643%201.614.908%203.06%201.248%204.317%201.248%202.665%200%204.492-1.524%205.322-2.401%201.476-1.559%202.886-1.854%206.491.82%201.877%201.393%203.514%201.753%204.861%201.068%202.223-1.713%202.811-3.867%203.399-6.374.077-.846.056-1.469.054-1.537zm-4.835%204.313c-.054.305-.156.586-.242.629-.034-.007-.131-.022-.307-.157-.145-.111-.314-.478-.456-.908.221.121.432.25.675.355.115.039.219.051.33.081zm-2.251-1.238c-.05.33-.158.648-.252.694-.022.001-.125-.018-.307-.157-.217-.166-.488-.906-.639-1.573.358.344.754.693%201.198%201.036zm-3.887-2.337c-.006-.116-.018-.231-.041-.342.635.145%201.189.368%201.599.625.097.231.166.481.174.642-.03.049-.055.101-.067.158-.046.013-.128.026-.298.004-.278-.037-.901-.57-1.367-1.087zm-1.127-.497c.116.306.176.625.12.71-.019.014-.117.045-.345.016-.206-.027-.604-.332-.986-.695.41-.051.816-.056%201.211-.031zm-4.535%201.535c.209.22.379.47.358.598-.006.041-.088.138-.351.234-.144.055-.539-.063-.979-.259a11.66%2011.66%200%200%200%20.972-.573zm.983-.664c.359-.237.738-.418%201.126-.554.25.237.479.548.457.694-.006.042-.087.138-.351.235-.174.064-.694-.105-1.232-.375zm-3.381%201.794c-.022.145-.061.29-.149.401-.133.166-.358.248-.69.251h-.002c-.133%200-.306-.26-.45-.621.417.091.854.07%201.291-.031zm-2.066-8.077a4.78%204.78%200%200%201-.775-.584c.172-.115.505-.254.88-.378l-.105.962zm-.331%202.302a10.32%2010.32%200%200%201-.828-.502c.202-.143.576-.328.984-.49l-.156.992zm-.45%202.157l-.701-.403c.214-.115.536-.249.891-.376a11.57%2011.57%200%200%201-.19.779zm-.181%201.716c.064.398.194.702.298.893-.194-.051-.435-.162-.736-.398.061-.119.224-.3.438-.495zM8.87%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zm-.735-.389a1.15%201.15%200%200%200-.314.783%201.16%201.16%200%200%200%201.162%201.162c.457%200%20.842-.27%201.032-.653.026.117.042.238.042.362a1.68%201.68%200%200%201-1.679%201.679%201.68%201.68%200%200%201-1.679-1.679c0-.843.626-1.535%201.436-1.654zM5.059%205.406A1.68%201.68%200%200%201%203.38%207.085a1.68%201.68%200%200%201-1.679-1.679c0-.037.009-.072.011-.109.21.3.541.508.935.508a1.16%201.16%200%200%200%201.162-1.162%201.14%201.14%200%200%200-.474-.912c.015%200%20.03-.005.045-.005.926.001%201.679.754%201.679%201.68zM3.198%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zM1.375%208.964c0-.52.103-1.035.288-1.52.466.394%201.06.64%201.717.64%201.144%200%202.116-.725%202.499-1.738.383%201.012%201.355%201.738%202.499%201.738.867%200%201.631-.421%202.121-1.062.307.605.478%201.267.478%201.942%200%202.486-2.153%204.51-4.801%204.51s-4.801-2.023-4.801-4.51zm24.342%2019.349c-.985.498-2.267.168-3.813-.979-3.073-2.281-5.453-3.199-7.813-.705-1.315%201.391-4.163%203.365-8.423.97-3.174-1.786-2.239-6.266-1.261-9.479l.146-.492c.276-1.02.395-2.457.444-3.268a6.11%206.11%200%200%200%201.18.115%206.01%206.01%200%200%200%202.536-.562l-.006.175c-.802.215-1.848.612-2.021%201.25-.079.295.021.601.274.837.219.203.415.364.598.501-.667.304-1.243.698-1.311%201.179-.02.144-.022.507.393.787.213.144.395.26.564.365-1.285.521-1.361.96-1.381%201.126-.018.142-.011.496.427.746l.854.489c-.473.389-.971.914-.999%201.429-.018.278.095.532.316.713.675.556%201.231.721%201.653.721.059%200%20.104-.014.158-.02.207.707.641%201.64%201.513%201.64h.013c.8-.008%201.236-.345%201.462-.626.173-.216.268-.457.325-.692.424.195.93.374%201.372.374.151%200%20.294-.021.423-.068.732-.27.944-.704.993-1.021.009-.061.003-.119.002-.179.266.086.538.147.789.147.15%200%20.294-.021.423-.069.542-.2.797-.489.914-.754.237.147.478.258.704.288.106.014.205.021.296.021.356%200%20.595-.101.767-.229.438.435%201.094.992%201.656%201.067.106.014.205.021.296.021a1.56%201.56%200%200%200%20.323-.035c.17.575.453%201.289.866%201.605.358.273.665.362.914.362a.99.99%200%200%200%20.421-.093%201.03%201.03%200%200%200%20.245-.164c.168.428.39.846.68%201.068.358.273.665.362.913.362a.99.99%200%200%200%20.421-.093c.317-.148.512-.448.639-.762.251.157.495.257.726.257.127%200%20.25-.024.37-.071.427-.17.706-.617.841-1.314.022-.015.047-.022.068-.038.067-.051.133-.104.196-.159-.443%201.486-1.107%202.761-2.086%203.257zM8.66%209.925a.5.5%200%201%200-1%200c0%20.653-.818%201.205-1.787%201.205s-1.787-.552-1.787-1.205a.5.5%200%201%200-1%200c0%201.216%201.25%202.205%202.787%202.205s2.787-.989%202.787-2.205zm4.4%2015.965l-.208.097c-2.661%201.258-4.708%201.436-6.086.527-1.542-1.017-1.88-3.19-1.844-4.198a.4.4%200%200%200-.385-.414c-.242-.029-.406.164-.414.385-.046%201.249.367%203.686%202.202%204.896.708.467%201.547.7%202.51.7%201.248%200%202.706-.392%204.362-1.174l.185-.086a.4.4%200%200%200%20.205-.527c-.089-.204-.326-.291-.527-.206zM9.547%202.292c.093.077.205.114.317.114a.5.5%200%200%200%20.318-.886L8.817.397a.5.5%200%200%200-.703.068.5.5%200%200%200%20.069.703l1.364%201.124zm-7.661-.065c.086%200%20.173-.022.253-.068l1.523-.893a.5.5%200%200%200-.506-.863l-1.523.892a.5.5%200%200%200-.179.685c.094.158.261.247.432.247z%22%20transform%3D%22matrix%28-1%200%200%201%2058%200%29%22%20fill%3D%22%233bb300%22/%3E%3Cpath%20d%3D%22M.3%2021.86V10.18q0-.46.02-.68.04-.22.18-.5.28-.54%201.34-.54%201.06%200%201.42.28.38.26.44.78.76-1.04%202.38-1.04%201.64%200%203.1%201.54%201.46%201.54%201.46%203.58%200%202.04-1.46%203.58-1.44%201.54-3.08%201.54-1.64%200-2.38-.92v4.04q0%20.46-.04.68-.02.22-.18.5-.14.3-.5.42-.36.12-.98.12-.62%200-1-.12-.36-.12-.52-.4-.14-.28-.18-.5-.02-.22-.02-.68zm3.96-9.42q-.46.54-.46%201.18%200%20.64.46%201.18.48.52%201.2.52.74%200%201.24-.52.52-.52.52-1.18%200-.66-.48-1.18-.48-.54-1.26-.54-.76%200-1.22.54zm14.741-8.36q.16-.3.54-.42.38-.12%201-.12.64%200%201.02.12.38.12.52.42.16.3.18.54.04.22.04.68v11.94q0%20.46-.04.7-.02.22-.18.5-.3.54-1.7.54-1.38%200-1.54-.98-.84.96-2.34.96-1.8%200-3.28-1.56-1.48-1.58-1.48-3.66%200-2.1%201.48-3.68%201.5-1.58%203.28-1.58%201.48%200%202.3%201v-4.2q0-.46.02-.68.04-.24.18-.52zm-3.24%2010.86q.52.54%201.26.54.74%200%201.22-.54.5-.54.5-1.18%200-.66-.48-1.22-.46-.56-1.26-.56-.8%200-1.28.56-.48.54-.48%201.2%200%20.66.52%201.2zm7.833-1.2q0-2.4%201.68-3.96%201.68-1.56%203.84-1.56%202.16%200%203.82%201.56%201.66%201.54%201.66%203.94%200%201.66-.86%202.96-.86%201.28-2.1%201.9-1.22.6-2.54.6-1.32%200-2.56-.64-1.24-.66-2.1-1.92-.84-1.28-.84-2.88zm4.18%201.44q.64.48%201.3.48.66%200%201.32-.5.66-.5.66-1.48%200-.98-.62-1.46-.62-.48-1.34-.48-.72%200-1.34.5-.62.5-.62%201.48%200%20.96.64%201.46zm11.412-1.44q0%20.84.56%201.32.56.46%201.18.46.64%200%201.18-.36.56-.38.9-.38.6%200%201.46%201.06.46.58.46%201.04%200%20.76-1.1%201.42-1.14.8-2.8.8-1.86%200-3.58-1.34-.82-.64-1.34-1.7-.52-1.08-.52-2.36%200-1.3.52-2.34.52-1.06%201.34-1.7%201.66-1.32%203.54-1.32.76%200%201.48.22.72.2%201.06.4l.32.2q.36.24.56.38.52.4.52.92%200%20.5-.42%201.14-.72%201.1-1.38%201.1-.38%200-1.08-.44-.36-.34-1.04-.34-.66%200-1.24.48-.58.48-.58%201.34z%22%20fill%3D%22green%22/%3E%3C/svg%3E"/>
+        </a>
+</div>
+    </nav>
+    <main class="pdoc">
+            <section class="module-info">
+                    <h1 class="modulename">
+<a href="./../perplexipy.html">perplexipy</a><wbr>.errors    </h1>
+
+                
+                        <input id="mod-errors-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+
+                        <label class="view-source-button" for="mod-errors-view-source"><span>View Source</span></label>
+
+                        <div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt</span>
+</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a>
+</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a>
+</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="k">class</span> <span class="nc">PerplexityClientError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
+</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-6"><a href="#L-6"><span class="linenos">6</span></a><span class="sd">    Perplexity client generic errors, for cleaner exception handling.</span>
+</span><span id="L-7"><a href="#L-7"><span class="linenos">7</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="L-8"><a href="#L-8"><span class="linenos">8</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">errorMessage</span><span class="p">):</span>
+</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a>        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">errorMessage</span><span class="p">)</span>
+</span></pre></div>
+
+
+            </section>
+                <section id="PerplexityClientError">
+                            <input id="PerplexityClientError-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr class">
+            
+    <span class="def">class</span>
+    <span class="name">PerplexityClientError</span><wbr>(<span class="base">builtins.Exception</span>):
+
+                <label class="view-source-button" for="PerplexityClientError-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClientError"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClientError-5"><a href="#PerplexityClientError-5"><span class="linenos"> 5</span></a><span class="k">class</span> <span class="nc">PerplexityClientError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
+</span><span id="PerplexityClientError-6"><a href="#PerplexityClientError-6"><span class="linenos"> 6</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="PerplexityClientError-7"><a href="#PerplexityClientError-7"><span class="linenos"> 7</span></a><span class="sd">    Perplexity client generic errors, for cleaner exception handling.</span>
+</span><span id="PerplexityClientError-8"><a href="#PerplexityClientError-8"><span class="linenos"> 8</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="PerplexityClientError-9"><a href="#PerplexityClientError-9"><span class="linenos"> 9</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">errorMessage</span><span class="p">):</span>
+</span><span id="PerplexityClientError-10"><a href="#PerplexityClientError-10"><span class="linenos">10</span></a>        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">errorMessage</span><span class="p">)</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Perplexity client generic errors, for cleaner exception handling.</p>
+</div>
+
+
+                            <div id="PerplexityClientError.__init__" class="classattr">
+                                        <input id="PerplexityClientError.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="name">PerplexityClientError</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">errorMessage</span></span>)</span>
+
+                <label class="view-source-button" for="PerplexityClientError.__init__-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#PerplexityClientError.__init__"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="PerplexityClientError.__init__-9"><a href="#PerplexityClientError.__init__-9"><span class="linenos"> 9</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">errorMessage</span><span class="p">):</span>
+</span><span id="PerplexityClientError.__init__-10"><a href="#PerplexityClientError.__init__-10"><span class="linenos">10</span></a>        <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="n">errorMessage</span><span class="p">)</span>
+</span></pre></div>
+
+
+    
+
+                            </div>
+                            <div class="inherited">
+                                <h5>Inherited Members</h5>
+                                <dl>
+                                    <div><dt>builtins.BaseException</dt>
+                                <dd id="PerplexityClientError.with_traceback" class="function">with_traceback</dd>
+                <dd id="PerplexityClientError.args" class="variable">args</dd>
+
+            </div>
+                                </dl>
+                            </div>
+                </section>
+    </main>
+<script>
+    function escapeHTML(html) {
+        return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
+    }
+
+    const originalContent = document.querySelector("main.pdoc");
+    let currentContent = originalContent;
+
+    function setContent(innerHTML) {
+        let elem;
+        if (innerHTML) {
+            elem = document.createElement("main");
+            elem.classList.add("pdoc");
+            elem.innerHTML = innerHTML;
+        } else {
+            elem = originalContent;
+        }
+        if (currentContent !== elem) {
+            currentContent.replaceWith(elem);
+            currentContent = elem;
+        }
+    }
+
+    function getSearchTerm() {
+        return (new URL(window.location)).searchParams.get("search");
+    }
+
+    const searchBox = document.querySelector(".pdoc input[type=search]");
+    searchBox.addEventListener("input", function () {
+        let url = new URL(window.location);
+        if (searchBox.value.trim()) {
+            url.hash = "";
+            url.searchParams.set("search", searchBox.value);
+        } else {
+            url.searchParams.delete("search");
+        }
+        history.replaceState("", "", url.toString());
+        onInput();
+    });
+    window.addEventListener("popstate", onInput);
+
+
+    let search, searchErr;
+
+    async function initialize() {
+        try {
+            search = await new Promise((resolve, reject) => {
+                const script = document.createElement("script");
+                script.type = "text/javascript";
+                script.async = true;
+                script.onload = () => resolve(window.pdocSearch);
+                script.onerror = (e) => reject(e);
+                script.src = "../search.js";
+                document.getElementsByTagName("head")[0].appendChild(script);
+            });
+        } catch (e) {
+            console.error("Cannot fetch pdoc search index");
+            searchErr = "Cannot fetch search index.";
+        }
+        onInput();
+
+        document.querySelector("nav.pdoc").addEventListener("click", e => {
+            if (e.target.hash) {
+                searchBox.value = "";
+                searchBox.dispatchEvent(new Event("input"));
+            }
+        });
+    }
+
+    function onInput() {
+        setContent((() => {
+            const term = getSearchTerm();
+            if (!term) {
+                return null
+            }
+            if (searchErr) {
+                return `<h3>Error: ${searchErr}</h3>`
+            }
+            if (!search) {
+                return "<h3>Searching...</h3>"
+            }
+
+            window.scrollTo({top: 0, left: 0, behavior: 'auto'});
+
+            const results = search(term);
+
+            let html;
+            if (results.length === 0) {
+                html = `No search results for '${escapeHTML(term)}'.`
+            } else {
+                html = `<h4>${results.length} search result${results.length > 1 ? "s" : ""} for '${escapeHTML(term)}'.</h4>`;
+            }
+            for (let result of results.slice(0, 10)) {
+                let doc = result.doc;
+                let url = `../${doc.modulename.replaceAll(".", "/")}.html`;
+                if (doc.qualname) {
+                    url += `#${doc.qualname}`;
+                }
+
+                let heading;
+                switch (result.doc.kind) {
+                    case "function":
+                        if (doc.fullname.endsWith(".__init__")) {
+                            heading = `<span class="name">${doc.fullname.replace(/\.__init__$/, "")}</span>${doc.signature}`;
+                        } else {
+                            heading = `<span class="def">${doc.funcdef}</span> <span class="name">${doc.fullname}</span>${doc.signature}`;
+                        }
+                        break;
+                    case "class":
+                        heading = `<span class="def">class</span> <span class="name">${doc.fullname}</span>`;
+                        if (doc.bases)
+                            heading += `<wbr>(<span class="base">${doc.bases}</span>)`;
+                        heading += `:`;
+                        break;
+                    case "variable":
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        if (doc.annotation)
+                            heading += `<span class="annotation">${doc.annotation}</span>`;
+                        if (doc.default_value)
+                            heading += `<span class="default_value"> = ${doc.default_value}</span>`;
+                        break;
+                    default:
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        break;
+                }
+                html += `
+                        <section class="search-result">
+                        <a href="${url}" class="attr ${doc.kind}">${heading}</a>
+                        <div class="docstring">${doc.doc}</div>
+                        </section>
+                    `;
+
+            }
+            return html;
+        })());
+    }
+
+    if (getSearchTerm()) {
+        initialize();
+        searchBox.value = getSearchTerm();
+        onInput();
+    } else {
+        searchBox.addEventListener("focus", initialize, {once: true});
+    }
+
+    searchBox.addEventListener("keydown", e => {
+        if (["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) {
+            let focused = currentContent.querySelector(".search-result.focused");
+            if (!focused) {
+                currentContent.querySelector(".search-result").classList.add("focused");
+            } else if (
+                e.key === "ArrowDown"
+                && focused.nextElementSibling
+                && focused.nextElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.nextElementSibling.classList.add("focused");
+                focused.nextElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "ArrowUp"
+                && focused.previousElementSibling
+                && focused.previousElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.previousElementSibling.classList.add("focused");
+                focused.previousElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "Enter"
+            ) {
+                focused.querySelector("a").click();
+            }
+        }
+    });
+</script></body>
+</html>
\ No newline at end of file
diff --git a/docs/perplexipy/responses.html b/docs/perplexipy/responses.html
new file mode 100644
index 0000000..7761f98
--- /dev/null
+++ b/docs/perplexipy/responses.html
@@ -0,0 +1,337 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <meta name="generator" content="pdoc 14.4.0"/>
+    <title>perplexipy.responses API documentation</title>
+            <link rel="icon" href="https://cime.net/upload_area/favicon.ico"/>
+
+    <style>/*! * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}</style>
+    <style>/*! syntax-highlighting.css */pre{line-height:125%;}span.linenos{color:inherit; background-color:transparent; padding-left:5px; padding-right:20px;}.pdoc-code .hll{background-color:#ffffcc}.pdoc-code{background:#f8f8f8;}.pdoc-code .c{color:#3D7B7B; font-style:italic}.pdoc-code .err{border:1px solid #FF0000}.pdoc-code .k{color:#008000; font-weight:bold}.pdoc-code .o{color:#666666}.pdoc-code .ch{color:#3D7B7B; font-style:italic}.pdoc-code .cm{color:#3D7B7B; font-style:italic}.pdoc-code .cp{color:#9C6500}.pdoc-code .cpf{color:#3D7B7B; font-style:italic}.pdoc-code .c1{color:#3D7B7B; font-style:italic}.pdoc-code .cs{color:#3D7B7B; font-style:italic}.pdoc-code .gd{color:#A00000}.pdoc-code .ge{font-style:italic}.pdoc-code .gr{color:#E40000}.pdoc-code .gh{color:#000080; font-weight:bold}.pdoc-code .gi{color:#008400}.pdoc-code .go{color:#717171}.pdoc-code .gp{color:#000080; font-weight:bold}.pdoc-code .gs{font-weight:bold}.pdoc-code .gu{color:#800080; font-weight:bold}.pdoc-code .gt{color:#0044DD}.pdoc-code .kc{color:#008000; font-weight:bold}.pdoc-code .kd{color:#008000; font-weight:bold}.pdoc-code .kn{color:#008000; font-weight:bold}.pdoc-code .kp{color:#008000}.pdoc-code .kr{color:#008000; font-weight:bold}.pdoc-code .kt{color:#B00040}.pdoc-code .m{color:#666666}.pdoc-code .s{color:#BA2121}.pdoc-code .na{color:#687822}.pdoc-code .nb{color:#008000}.pdoc-code .nc{color:#0000FF; font-weight:bold}.pdoc-code .no{color:#880000}.pdoc-code .nd{color:#AA22FF}.pdoc-code .ni{color:#717171; font-weight:bold}.pdoc-code .ne{color:#CB3F38; font-weight:bold}.pdoc-code .nf{color:#0000FF}.pdoc-code .nl{color:#767600}.pdoc-code .nn{color:#0000FF; font-weight:bold}.pdoc-code .nt{color:#008000; font-weight:bold}.pdoc-code .nv{color:#19177C}.pdoc-code .ow{color:#AA22FF; font-weight:bold}.pdoc-code .w{color:#bbbbbb}.pdoc-code .mb{color:#666666}.pdoc-code .mf{color:#666666}.pdoc-code .mh{color:#666666}.pdoc-code .mi{color:#666666}.pdoc-code .mo{color:#666666}.pdoc-code .sa{color:#BA2121}.pdoc-code .sb{color:#BA2121}.pdoc-code .sc{color:#BA2121}.pdoc-code .dl{color:#BA2121}.pdoc-code .sd{color:#BA2121; font-style:italic}.pdoc-code .s2{color:#BA2121}.pdoc-code .se{color:#AA5D1F; font-weight:bold}.pdoc-code .sh{color:#BA2121}.pdoc-code .si{color:#A45A77; font-weight:bold}.pdoc-code .sx{color:#008000}.pdoc-code .sr{color:#A45A77}.pdoc-code .s1{color:#BA2121}.pdoc-code .ss{color:#19177C}.pdoc-code .bp{color:#008000}.pdoc-code .fm{color:#0000FF}.pdoc-code .vc{color:#19177C}.pdoc-code .vg{color:#19177C}.pdoc-code .vi{color:#19177C}.pdoc-code .vm{color:#19177C}.pdoc-code .il{color:#666666}</style>
+    <style>/*! theme.css */:root{--pdoc-background:#fff;}.pdoc{--text:#212529;--muted:#6c757d;--link:#3660a5;--link-hover:#1659c5;--code:#f8f8f8;--active:#fff598;--accent:#eee;--accent2:#c1c1c1;--nav-hover:rgba(255, 255, 255, 0.5);--name:#0066BB;--def:#008800;--annotation:#007020;}</style>
+    <style>/*! layout.css */html, body{width:100%;height:100%;}html, main{scroll-behavior:smooth;}body{background-color:var(--pdoc-background);}@media (max-width:769px){#navtoggle{cursor:pointer;position:absolute;width:50px;height:40px;top:1rem;right:1rem;border-color:var(--text);color:var(--text);display:flex;opacity:0.8;z-index:999;}#navtoggle:hover{opacity:1;}#togglestate + div{display:none;}#togglestate:checked + div{display:inherit;}main, header{padding:2rem 3vw;}header + main{margin-top:-3rem;}.git-button{display:none !important;}nav input[type="search"]{max-width:77%;}nav input[type="search"]:first-child{margin-top:-6px;}nav input[type="search"]:valid ~ *{display:none !important;}}@media (min-width:770px){:root{--sidebar-width:clamp(12.5rem, 28vw, 22rem);}nav{position:fixed;overflow:auto;height:100vh;width:var(--sidebar-width);}main, header{padding:3rem 2rem 3rem calc(var(--sidebar-width) + 3rem);width:calc(54rem + var(--sidebar-width));max-width:100%;}header + main{margin-top:-4rem;}#navtoggle{display:none;}}#togglestate{position:absolute;height:0;opacity:0;}nav.pdoc{--pad:clamp(0.5rem, 2vw, 1.75rem);--indent:1.5rem;background-color:var(--accent);border-right:1px solid var(--accent2);box-shadow:0 0 20px rgba(50, 50, 50, .2) inset;padding:0 0 0 var(--pad);overflow-wrap:anywhere;scrollbar-width:thin; scrollbar-color:var(--accent2) transparent; z-index:1}nav.pdoc::-webkit-scrollbar{width:.4rem; }nav.pdoc::-webkit-scrollbar-thumb{background-color:var(--accent2); }nav.pdoc > div{padding:var(--pad) 0;}nav.pdoc .module-list-button{display:inline-flex;align-items:center;color:var(--text);border-color:var(--muted);margin-bottom:1rem;}nav.pdoc .module-list-button:hover{border-color:var(--text);}nav.pdoc input[type=search]{display:block;outline-offset:0;width:calc(100% - var(--pad));}nav.pdoc .logo{max-width:calc(100% - var(--pad));max-height:35vh;display:block;margin:0 auto 1rem;transform:translate(calc(-.5 * var(--pad)), 0);}nav.pdoc ul{list-style:none;padding-left:0;}nav.pdoc > div > ul{margin-left:calc(0px - var(--pad));}nav.pdoc li a{padding:.2rem 0 .2rem calc(var(--pad) + var(--indent));}nav.pdoc > div > ul > li > a{padding-left:var(--pad);}nav.pdoc li{transition:all 100ms;}nav.pdoc li:hover{background-color:var(--nav-hover);}nav.pdoc a, nav.pdoc a:hover{color:var(--text);}nav.pdoc a{display:block;}nav.pdoc > h2:first-of-type{margin-top:1.5rem;}nav.pdoc .class:before{content:"class ";color:var(--muted);}nav.pdoc .function:after{content:"()";color:var(--muted);}nav.pdoc footer:before{content:"";display:block;width:calc(100% - var(--pad));border-top:solid var(--accent2) 1px;margin-top:1.5rem;padding-top:.5rem;}nav.pdoc footer{font-size:small;}</style>
+    <style>/*! content.css */.pdoc{color:var(--text);box-sizing:border-box;line-height:1.5;background:none;}.pdoc .pdoc-button{cursor:pointer;display:inline-block;border:solid black 1px;border-radius:2px;font-size:.75rem;padding:calc(0.5em - 1px) 1em;transition:100ms all;}.pdoc .pdoc-alert{padding:1rem 1rem 1rem calc(1.5rem + 24px);border:1px solid transparent;border-radius:.25rem;background-repeat:no-repeat;background-position:1rem center;margin-bottom:1rem;}.pdoc .pdoc-alert > *:last-child{margin-bottom:0;}.pdoc .pdoc-alert-note {color:#084298;background-color:#cfe2ff;border-color:#b6d4fe;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23084298%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8%2016A8%208%200%201%200%208%200a8%208%200%200%200%200%2016zm.93-9.412-1%204.705c-.07.34.029.533.304.533.194%200%20.487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703%200-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381%202.29-.287zM8%205.5a1%201%200%201%201%200-2%201%201%200%200%201%200%202z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-warning{color:#664d03;background-color:#fff3cd;border-color:#ffecb5;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23664d03%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8.982%201.566a1.13%201.13%200%200%200-1.96%200L.165%2013.233c-.457.778.091%201.767.98%201.767h13.713c.889%200%201.438-.99.98-1.767L8.982%201.566zM8%205c.535%200%20.954.462.9.995l-.35%203.507a.552.552%200%200%201-1.1%200L7.1%205.995A.905.905%200%200%201%208%205zm.002%206a1%201%200%201%201%200%202%201%201%200%200%201%200-2z%22/%3E%3C/svg%3E");}.pdoc .pdoc-alert-danger{color:#842029;background-color:#f8d7da;border-color:#f5c2c7;background-image:url("data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2224%22%20height%3D%2224%22%20fill%3D%22%23842029%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M5.52.359A.5.5%200%200%201%206%200h4a.5.5%200%200%201%20.474.658L8.694%206H12.5a.5.5%200%200%201%20.395.807l-7%209a.5.5%200%200%201-.873-.454L6.823%209.5H3.5a.5.5%200%200%201-.48-.641l2.5-8.5z%22/%3E%3C/svg%3E");}.pdoc .visually-hidden{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important;}.pdoc h1, .pdoc h2, .pdoc h3{font-weight:300;margin:.3em 0;padding:.2em 0;}.pdoc > section:not(.module-info) h1{font-size:1.5rem;font-weight:500;}.pdoc > section:not(.module-info) h2{font-size:1.4rem;font-weight:500;}.pdoc > section:not(.module-info) h3{font-size:1.3rem;font-weight:500;}.pdoc > section:not(.module-info) h4{font-size:1.2rem;}.pdoc > section:not(.module-info) h5{font-size:1.1rem;}.pdoc a{text-decoration:none;color:var(--link);}.pdoc a:hover{color:var(--link-hover);}.pdoc blockquote{margin-left:2rem;}.pdoc pre{border-top:1px solid var(--accent2);border-bottom:1px solid var(--accent2);margin-top:0;margin-bottom:1em;padding:.5rem 0 .5rem .5rem;overflow-x:auto;background-color:var(--code);}.pdoc code{color:var(--text);padding:.2em .4em;margin:0;font-size:85%;background-color:var(--accent);border-radius:6px;}.pdoc a > code{color:inherit;}.pdoc pre > code{display:inline-block;font-size:inherit;background:none;border:none;padding:0;}.pdoc > section:not(.module-info){margin-bottom:1.5rem;}.pdoc .modulename{margin-top:0;font-weight:bold;}.pdoc .modulename a{color:var(--link);transition:100ms all;}.pdoc .git-button{float:right;border:solid var(--link) 1px;}.pdoc .git-button:hover{background-color:var(--link);color:var(--pdoc-background);}.view-source-toggle-state,.view-source-toggle-state ~ .pdoc-code{display:none;}.view-source-toggle-state:checked ~ .pdoc-code{display:block;}.view-source-button{display:inline-block;float:right;font-size:.75rem;line-height:1.5rem;color:var(--muted);padding:0 .4rem 0 1.3rem;cursor:pointer;text-indent:-2px;}.view-source-button > span{visibility:hidden;}.module-info .view-source-button{float:none;display:flex;justify-content:flex-end;margin:-1.2rem .4rem -.2rem 0;}.view-source-button::before{position:absolute;content:"View Source";display:list-item;list-style-type:disclosure-closed;}.view-source-toggle-state:checked ~ .attr .view-source-button::before,.view-source-toggle-state:checked ~ .view-source-button::before{list-style-type:disclosure-open;}.pdoc .docstring{margin-bottom:1.5rem;}.pdoc section:not(.module-info) .docstring{margin-left:clamp(0rem, 5vw - 2rem, 1rem);}.pdoc .docstring .pdoc-code{margin-left:1em;margin-right:1em;}.pdoc h1:target,.pdoc h2:target,.pdoc h3:target,.pdoc h4:target,.pdoc h5:target,.pdoc h6:target,.pdoc .pdoc-code > pre > span:target{background-color:var(--active);box-shadow:-1rem 0 0 0 var(--active);}.pdoc .pdoc-code > pre > span:target{display:block;}.pdoc div:target > .attr,.pdoc section:target > .attr,.pdoc dd:target > a{background-color:var(--active);}.pdoc *{scroll-margin:2rem;}.pdoc .pdoc-code .linenos{user-select:none;}.pdoc .attr:hover{filter:contrast(0.95);}.pdoc section, .pdoc .classattr{position:relative;}.pdoc .headerlink{--width:clamp(1rem, 3vw, 2rem);position:absolute;top:0;left:calc(0rem - var(--width));transition:all 100ms ease-in-out;opacity:0;}.pdoc .headerlink::before{content:"#";display:block;text-align:center;width:var(--width);height:2.3rem;line-height:2.3rem;font-size:1.5rem;}.pdoc .attr:hover ~ .headerlink,.pdoc *:target > .headerlink,.pdoc .headerlink:hover{opacity:1;}.pdoc .attr{display:block;margin:.5rem 0 .5rem;padding:.4rem .4rem .4rem 1rem;background-color:var(--accent);overflow-x:auto;}.pdoc .classattr{margin-left:2rem;}.pdoc .name{color:var(--name);font-weight:bold;}.pdoc .def{color:var(--def);font-weight:bold;}.pdoc .signature{background-color:transparent;}.pdoc .param, .pdoc .return-annotation{white-space:pre;}.pdoc .signature.multiline .param{display:block;}.pdoc .signature.condensed .param{display:inline-block;}.pdoc .annotation{color:var(--annotation);}.pdoc .view-value-toggle-state,.pdoc .view-value-toggle-state ~ .default_value{display:none;}.pdoc .view-value-toggle-state:checked ~ .default_value{display:inherit;}.pdoc .view-value-button{font-size:.5rem;vertical-align:middle;border-style:dashed;margin-top:-0.1rem;}.pdoc .view-value-button:hover{background:white;}.pdoc .view-value-button::before{content:"show";text-align:center;width:2.2em;display:inline-block;}.pdoc .view-value-toggle-state:checked ~ .view-value-button::before{content:"hide";}.pdoc .inherited{margin-left:2rem;}.pdoc .inherited dt{font-weight:700;}.pdoc .inherited dt, .pdoc .inherited dd{display:inline;margin-left:0;margin-bottom:.5rem;}.pdoc .inherited dd:not(:last-child):after{content:", ";}.pdoc .inherited .class:before{content:"class ";}.pdoc .inherited .function a:after{content:"()";}.pdoc .search-result .docstring{overflow:auto;max-height:25vh;}.pdoc .search-result.focused > .attr{background-color:var(--active);}.pdoc .attribution{margin-top:2rem;display:block;opacity:0.5;transition:all 200ms;filter:grayscale(100%);}.pdoc .attribution:hover{opacity:1;filter:grayscale(0%);}.pdoc .attribution img{margin-left:5px;height:35px;vertical-align:middle;width:70px;transition:all 200ms;}.pdoc table{display:block;width:max-content;max-width:100%;overflow:auto;margin-bottom:1rem;}.pdoc table th{font-weight:600;}.pdoc table th, .pdoc table td{padding:6px 13px;border:1px solid var(--accent2);}</style>
+    <style>/*! custom.css */</style></head>
+<body>
+    <nav class="pdoc">
+        <label id="navtoggle" for="togglestate" class="pdoc-button"><svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'><path stroke-linecap='round' stroke="currentColor" stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/></svg></label>
+        <input id="togglestate" type="checkbox" aria-hidden="true" tabindex="-1">
+        <div>            <a class="pdoc-button module-list-button" href="../perplexipy.html">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-box-arrow-in-left" viewBox="0 0 16 16">
+  <path fill-rule="evenodd" d="M10 3.5a.5.5 0 0 0-.5-.5h-8a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 1 1 0v2A1.5 1.5 0 0 1 9.5 14h-8A1.5 1.5 0 0 1 0 12.5v-9A1.5 1.5 0 0 1 1.5 2h8A1.5 1.5 0 0 1 11 3.5v2a.5.5 0 0 1-1 0v-2z"/>
+  <path fill-rule="evenodd" d="M4.146 8.354a.5.5 0 0 1 0-.708l3-3a.5.5 0 1 1 .708.708L5.707 7.5H14.5a.5.5 0 0 1 0 1H5.707l2.147 2.146a.5.5 0 0 1-.708.708l-3-3z"/>
+</svg>                &nbsp;perplexipy</a>
+
+            <img src="https://images2.imgbox.com/57/94/AsI1WSfy_o.png" class="logo" alt="project logo"/>
+
+            <input type="search" placeholder="Search..." role="searchbox" aria-label="search"
+                   pattern=".+" required>
+
+
+
+            <h2>API Documentation</h2>
+                <ul class="memberlist">
+            <li>
+                    <a class="class" href="#Responses">Responses</a>
+                            <ul class="memberlist">
+                        <li>
+                                <a class="function" href="#Responses.__init__">Responses</a>
+                        </li>
+                </ul>
+
+            </li>
+    </ul>
+
+
+
+        <a class="attribution" title="pdoc: Python API documentation generator" href="https://pdoc.dev" target="_blank">
+            built with <span class="visually-hidden">pdoc</span><img
+                alt="pdoc logo"
+                src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20role%3D%22img%22%20aria-label%3D%22pdoc%20logo%22%20width%3D%22300%22%20height%3D%22150%22%20viewBox%3D%22-1%200%2060%2030%22%3E%3Ctitle%3Epdoc%3C/title%3E%3Cpath%20d%3D%22M29.621%2021.293c-.011-.273-.214-.475-.511-.481a.5.5%200%200%200-.489.503l-.044%201.393c-.097.551-.695%201.215-1.566%201.704-.577.428-1.306.486-2.193.182-1.426-.617-2.467-1.654-3.304-2.487l-.173-.172a3.43%203.43%200%200%200-.365-.306.49.49%200%200%200-.286-.196c-1.718-1.06-4.931-1.47-7.353.191l-.219.15c-1.707%201.187-3.413%202.131-4.328%201.03-.02-.027-.49-.685-.141-1.763.233-.721.546-2.408.772-4.076.042-.09.067-.187.046-.288.166-1.347.277-2.625.241-3.351%201.378-1.008%202.271-2.586%202.271-4.362%200-.976-.272-1.935-.788-2.774-.057-.094-.122-.18-.184-.268.033-.167.052-.339.052-.516%200-1.477-1.202-2.679-2.679-2.679-.791%200-1.496.352-1.987.9a6.3%206.3%200%200%200-1.001.029c-.492-.564-1.207-.929-2.012-.929-1.477%200-2.679%201.202-2.679%202.679A2.65%202.65%200%200%200%20.97%206.554c-.383.747-.595%201.572-.595%202.41%200%202.311%201.507%204.29%203.635%205.107-.037.699-.147%202.27-.423%203.294l-.137.461c-.622%202.042-2.515%208.257%201.727%2010.643%201.614.908%203.06%201.248%204.317%201.248%202.665%200%204.492-1.524%205.322-2.401%201.476-1.559%202.886-1.854%206.491.82%201.877%201.393%203.514%201.753%204.861%201.068%202.223-1.713%202.811-3.867%203.399-6.374.077-.846.056-1.469.054-1.537zm-4.835%204.313c-.054.305-.156.586-.242.629-.034-.007-.131-.022-.307-.157-.145-.111-.314-.478-.456-.908.221.121.432.25.675.355.115.039.219.051.33.081zm-2.251-1.238c-.05.33-.158.648-.252.694-.022.001-.125-.018-.307-.157-.217-.166-.488-.906-.639-1.573.358.344.754.693%201.198%201.036zm-3.887-2.337c-.006-.116-.018-.231-.041-.342.635.145%201.189.368%201.599.625.097.231.166.481.174.642-.03.049-.055.101-.067.158-.046.013-.128.026-.298.004-.278-.037-.901-.57-1.367-1.087zm-1.127-.497c.116.306.176.625.12.71-.019.014-.117.045-.345.016-.206-.027-.604-.332-.986-.695.41-.051.816-.056%201.211-.031zm-4.535%201.535c.209.22.379.47.358.598-.006.041-.088.138-.351.234-.144.055-.539-.063-.979-.259a11.66%2011.66%200%200%200%20.972-.573zm.983-.664c.359-.237.738-.418%201.126-.554.25.237.479.548.457.694-.006.042-.087.138-.351.235-.174.064-.694-.105-1.232-.375zm-3.381%201.794c-.022.145-.061.29-.149.401-.133.166-.358.248-.69.251h-.002c-.133%200-.306-.26-.45-.621.417.091.854.07%201.291-.031zm-2.066-8.077a4.78%204.78%200%200%201-.775-.584c.172-.115.505-.254.88-.378l-.105.962zm-.331%202.302a10.32%2010.32%200%200%201-.828-.502c.202-.143.576-.328.984-.49l-.156.992zm-.45%202.157l-.701-.403c.214-.115.536-.249.891-.376a11.57%2011.57%200%200%201-.19.779zm-.181%201.716c.064.398.194.702.298.893-.194-.051-.435-.162-.736-.398.061-.119.224-.3.438-.495zM8.87%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zm-.735-.389a1.15%201.15%200%200%200-.314.783%201.16%201.16%200%200%200%201.162%201.162c.457%200%20.842-.27%201.032-.653.026.117.042.238.042.362a1.68%201.68%200%200%201-1.679%201.679%201.68%201.68%200%200%201-1.679-1.679c0-.843.626-1.535%201.436-1.654zM5.059%205.406A1.68%201.68%200%200%201%203.38%207.085a1.68%201.68%200%200%201-1.679-1.679c0-.037.009-.072.011-.109.21.3.541.508.935.508a1.16%201.16%200%200%200%201.162-1.162%201.14%201.14%200%200%200-.474-.912c.015%200%20.03-.005.045-.005.926.001%201.679.754%201.679%201.68zM3.198%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zM1.375%208.964c0-.52.103-1.035.288-1.52.466.394%201.06.64%201.717.64%201.144%200%202.116-.725%202.499-1.738.383%201.012%201.355%201.738%202.499%201.738.867%200%201.631-.421%202.121-1.062.307.605.478%201.267.478%201.942%200%202.486-2.153%204.51-4.801%204.51s-4.801-2.023-4.801-4.51zm24.342%2019.349c-.985.498-2.267.168-3.813-.979-3.073-2.281-5.453-3.199-7.813-.705-1.315%201.391-4.163%203.365-8.423.97-3.174-1.786-2.239-6.266-1.261-9.479l.146-.492c.276-1.02.395-2.457.444-3.268a6.11%206.11%200%200%200%201.18.115%206.01%206.01%200%200%200%202.536-.562l-.006.175c-.802.215-1.848.612-2.021%201.25-.079.295.021.601.274.837.219.203.415.364.598.501-.667.304-1.243.698-1.311%201.179-.02.144-.022.507.393.787.213.144.395.26.564.365-1.285.521-1.361.96-1.381%201.126-.018.142-.011.496.427.746l.854.489c-.473.389-.971.914-.999%201.429-.018.278.095.532.316.713.675.556%201.231.721%201.653.721.059%200%20.104-.014.158-.02.207.707.641%201.64%201.513%201.64h.013c.8-.008%201.236-.345%201.462-.626.173-.216.268-.457.325-.692.424.195.93.374%201.372.374.151%200%20.294-.021.423-.068.732-.27.944-.704.993-1.021.009-.061.003-.119.002-.179.266.086.538.147.789.147.15%200%20.294-.021.423-.069.542-.2.797-.489.914-.754.237.147.478.258.704.288.106.014.205.021.296.021.356%200%20.595-.101.767-.229.438.435%201.094.992%201.656%201.067.106.014.205.021.296.021a1.56%201.56%200%200%200%20.323-.035c.17.575.453%201.289.866%201.605.358.273.665.362.914.362a.99.99%200%200%200%20.421-.093%201.03%201.03%200%200%200%20.245-.164c.168.428.39.846.68%201.068.358.273.665.362.913.362a.99.99%200%200%200%20.421-.093c.317-.148.512-.448.639-.762.251.157.495.257.726.257.127%200%20.25-.024.37-.071.427-.17.706-.617.841-1.314.022-.015.047-.022.068-.038.067-.051.133-.104.196-.159-.443%201.486-1.107%202.761-2.086%203.257zM8.66%209.925a.5.5%200%201%200-1%200c0%20.653-.818%201.205-1.787%201.205s-1.787-.552-1.787-1.205a.5.5%200%201%200-1%200c0%201.216%201.25%202.205%202.787%202.205s2.787-.989%202.787-2.205zm4.4%2015.965l-.208.097c-2.661%201.258-4.708%201.436-6.086.527-1.542-1.017-1.88-3.19-1.844-4.198a.4.4%200%200%200-.385-.414c-.242-.029-.406.164-.414.385-.046%201.249.367%203.686%202.202%204.896.708.467%201.547.7%202.51.7%201.248%200%202.706-.392%204.362-1.174l.185-.086a.4.4%200%200%200%20.205-.527c-.089-.204-.326-.291-.527-.206zM9.547%202.292c.093.077.205.114.317.114a.5.5%200%200%200%20.318-.886L8.817.397a.5.5%200%200%200-.703.068.5.5%200%200%200%20.069.703l1.364%201.124zm-7.661-.065c.086%200%20.173-.022.253-.068l1.523-.893a.5.5%200%200%200-.506-.863l-1.523.892a.5.5%200%200%200-.179.685c.094.158.261.247.432.247z%22%20transform%3D%22matrix%28-1%200%200%201%2058%200%29%22%20fill%3D%22%233bb300%22/%3E%3Cpath%20d%3D%22M.3%2021.86V10.18q0-.46.02-.68.04-.22.18-.5.28-.54%201.34-.54%201.06%200%201.42.28.38.26.44.78.76-1.04%202.38-1.04%201.64%200%203.1%201.54%201.46%201.54%201.46%203.58%200%202.04-1.46%203.58-1.44%201.54-3.08%201.54-1.64%200-2.38-.92v4.04q0%20.46-.04.68-.02.22-.18.5-.14.3-.5.42-.36.12-.98.12-.62%200-1-.12-.36-.12-.52-.4-.14-.28-.18-.5-.02-.22-.02-.68zm3.96-9.42q-.46.54-.46%201.18%200%20.64.46%201.18.48.52%201.2.52.74%200%201.24-.52.52-.52.52-1.18%200-.66-.48-1.18-.48-.54-1.26-.54-.76%200-1.22.54zm14.741-8.36q.16-.3.54-.42.38-.12%201-.12.64%200%201.02.12.38.12.52.42.16.3.18.54.04.22.04.68v11.94q0%20.46-.04.7-.02.22-.18.5-.3.54-1.7.54-1.38%200-1.54-.98-.84.96-2.34.96-1.8%200-3.28-1.56-1.48-1.58-1.48-3.66%200-2.1%201.48-3.68%201.5-1.58%203.28-1.58%201.48%200%202.3%201v-4.2q0-.46.02-.68.04-.24.18-.52zm-3.24%2010.86q.52.54%201.26.54.74%200%201.22-.54.5-.54.5-1.18%200-.66-.48-1.22-.46-.56-1.26-.56-.8%200-1.28.56-.48.54-.48%201.2%200%20.66.52%201.2zm7.833-1.2q0-2.4%201.68-3.96%201.68-1.56%203.84-1.56%202.16%200%203.82%201.56%201.66%201.54%201.66%203.94%200%201.66-.86%202.96-.86%201.28-2.1%201.9-1.22.6-2.54.6-1.32%200-2.56-.64-1.24-.66-2.1-1.92-.84-1.28-.84-2.88zm4.18%201.44q.64.48%201.3.48.66%200%201.32-.5.66-.5.66-1.48%200-.98-.62-1.46-.62-.48-1.34-.48-.72%200-1.34.5-.62.5-.62%201.48%200%20.96.64%201.46zm11.412-1.44q0%20.84.56%201.32.56.46%201.18.46.64%200%201.18-.36.56-.38.9-.38.6%200%201.46%201.06.46.58.46%201.04%200%20.76-1.1%201.42-1.14.8-2.8.8-1.86%200-3.58-1.34-.82-.64-1.34-1.7-.52-1.08-.52-2.36%200-1.3.52-2.34.52-1.06%201.34-1.7%201.66-1.32%203.54-1.32.76%200%201.48.22.72.2%201.06.4l.32.2q.36.24.56.38.52.4.52.92%200%20.5-.42%201.14-.72%201.1-1.38%201.1-.38%200-1.08-.44-.36-.34-1.04-.34-.66%200-1.24.48-.58.48-.58%201.34z%22%20fill%3D%22green%22/%3E%3C/svg%3E"/>
+        </a>
+</div>
+    </nav>
+    <main class="pdoc">
+            <section class="module-info">
+                    <h1 class="modulename">
+<a href="./../perplexipy.html">perplexipy</a><wbr>.responses    </h1>
+
+                
+                        <input id="mod-responses-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+
+                        <label class="view-source-button" for="mod-responses-view-source"><span>View Source</span></label>
+
+                        <div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt</span>
+</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a>
+</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a>
+</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="k">class</span> <span class="nc">Responses</span><span class="p">:</span>
+</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="sd">    Encapsulates all the streaming responses from a query and enables access to</span>
+</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="sd">    it using a purpose-built iterable.  Strips all the OpenAI response metadata</span>
+</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="sd">    and returns only the textual response.  It&#39;s a streaming iterable,</span>
+</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="sd">    open-ended.</span>
+</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">responsesStream</span><span class="p">):</span>
+</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_responsesStream</span> <span class="o">=</span> <span class="n">responsesStream</span>
+</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
+</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a>
+</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a>        <span class="k">return</span> <span class="bp">self</span>
+</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a>
+</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a>
+</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a>    <span class="k">def</span> <span class="fm">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a>        <span class="k">try</span><span class="p">:</span>
+</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a>            <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_responsesStream</span><span class="o">.</span><span class="fm">__next__</span><span class="p">()</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">content</span>
+</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a>        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
+</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a>            <span class="k">raise</span> <span class="n">e</span>
+</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span></pre></div>
+
+
+            </section>
+                <section id="Responses">
+                            <input id="Responses-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr class">
+            
+    <span class="def">class</span>
+    <span class="name">Responses</span>:
+
+                <label class="view-source-button" for="Responses-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#Responses"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="Responses-5"><a href="#Responses-5"><span class="linenos"> 5</span></a><span class="k">class</span> <span class="nc">Responses</span><span class="p">:</span>
+</span><span id="Responses-6"><a href="#Responses-6"><span class="linenos"> 6</span></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
+</span><span id="Responses-7"><a href="#Responses-7"><span class="linenos"> 7</span></a><span class="sd">    Encapsulates all the streaming responses from a query and enables access to</span>
+</span><span id="Responses-8"><a href="#Responses-8"><span class="linenos"> 8</span></a><span class="sd">    it using a purpose-built iterable.  Strips all the OpenAI response metadata</span>
+</span><span id="Responses-9"><a href="#Responses-9"><span class="linenos"> 9</span></a><span class="sd">    and returns only the textual response.  It&#39;s a streaming iterable,</span>
+</span><span id="Responses-10"><a href="#Responses-10"><span class="linenos">10</span></a><span class="sd">    open-ended.</span>
+</span><span id="Responses-11"><a href="#Responses-11"><span class="linenos">11</span></a><span class="sd">    &quot;&quot;&quot;</span>
+</span><span id="Responses-12"><a href="#Responses-12"><span class="linenos">12</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">responsesStream</span><span class="p">):</span>
+</span><span id="Responses-13"><a href="#Responses-13"><span class="linenos">13</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_responsesStream</span> <span class="o">=</span> <span class="n">responsesStream</span>
+</span><span id="Responses-14"><a href="#Responses-14"><span class="linenos">14</span></a>
+</span><span id="Responses-15"><a href="#Responses-15"><span class="linenos">15</span></a>
+</span><span id="Responses-16"><a href="#Responses-16"><span class="linenos">16</span></a>    <span class="k">def</span> <span class="fm">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="Responses-17"><a href="#Responses-17"><span class="linenos">17</span></a>        <span class="k">return</span> <span class="bp">self</span>
+</span><span id="Responses-18"><a href="#Responses-18"><span class="linenos">18</span></a>
+</span><span id="Responses-19"><a href="#Responses-19"><span class="linenos">19</span></a>
+</span><span id="Responses-20"><a href="#Responses-20"><span class="linenos">20</span></a>    <span class="k">def</span> <span class="fm">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
+</span><span id="Responses-21"><a href="#Responses-21"><span class="linenos">21</span></a>        <span class="k">try</span><span class="p">:</span>
+</span><span id="Responses-22"><a href="#Responses-22"><span class="linenos">22</span></a>            <span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_responsesStream</span><span class="o">.</span><span class="fm">__next__</span><span class="p">()</span><span class="o">.</span><span class="n">choices</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">delta</span><span class="o">.</span><span class="n">content</span>
+</span><span id="Responses-23"><a href="#Responses-23"><span class="linenos">23</span></a>        <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
+</span><span id="Responses-24"><a href="#Responses-24"><span class="linenos">24</span></a>            <span class="k">raise</span> <span class="n">e</span>
+</span><span id="Responses-25"><a href="#Responses-25"><span class="linenos">25</span></a>        <span class="k">return</span> <span class="n">result</span>
+</span></pre></div>
+
+
+            <div class="docstring"><p>Encapsulates all the streaming responses from a query and enables access to
+it using a purpose-built iterable.  Strips all the OpenAI response metadata
+and returns only the textual response.  It's a streaming iterable,
+open-ended.</p>
+</div>
+
+
+                            <div id="Responses.__init__" class="classattr">
+                                        <input id="Responses.__init__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
+<div class="attr function">
+            
+        <span class="name">Responses</span><span class="signature pdoc-code condensed">(<span class="param"><span class="n">responsesStream</span></span>)</span>
+
+                <label class="view-source-button" for="Responses.__init__-view-source"><span>View Source</span></label>
+
+    </div>
+    <a class="headerlink" href="#Responses.__init__"></a>
+            <div class="pdoc-code codehilite"><pre><span></span><span id="Responses.__init__-12"><a href="#Responses.__init__-12"><span class="linenos">12</span></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">responsesStream</span><span class="p">):</span>
+</span><span id="Responses.__init__-13"><a href="#Responses.__init__-13"><span class="linenos">13</span></a>        <span class="bp">self</span><span class="o">.</span><span class="n">_responsesStream</span> <span class="o">=</span> <span class="n">responsesStream</span>
+</span></pre></div>
+
+
+    
+
+                            </div>
+                </section>
+    </main>
+<script>
+    function escapeHTML(html) {
+        return document.createElement('div').appendChild(document.createTextNode(html)).parentNode.innerHTML;
+    }
+
+    const originalContent = document.querySelector("main.pdoc");
+    let currentContent = originalContent;
+
+    function setContent(innerHTML) {
+        let elem;
+        if (innerHTML) {
+            elem = document.createElement("main");
+            elem.classList.add("pdoc");
+            elem.innerHTML = innerHTML;
+        } else {
+            elem = originalContent;
+        }
+        if (currentContent !== elem) {
+            currentContent.replaceWith(elem);
+            currentContent = elem;
+        }
+    }
+
+    function getSearchTerm() {
+        return (new URL(window.location)).searchParams.get("search");
+    }
+
+    const searchBox = document.querySelector(".pdoc input[type=search]");
+    searchBox.addEventListener("input", function () {
+        let url = new URL(window.location);
+        if (searchBox.value.trim()) {
+            url.hash = "";
+            url.searchParams.set("search", searchBox.value);
+        } else {
+            url.searchParams.delete("search");
+        }
+        history.replaceState("", "", url.toString());
+        onInput();
+    });
+    window.addEventListener("popstate", onInput);
+
+
+    let search, searchErr;
+
+    async function initialize() {
+        try {
+            search = await new Promise((resolve, reject) => {
+                const script = document.createElement("script");
+                script.type = "text/javascript";
+                script.async = true;
+                script.onload = () => resolve(window.pdocSearch);
+                script.onerror = (e) => reject(e);
+                script.src = "../search.js";
+                document.getElementsByTagName("head")[0].appendChild(script);
+            });
+        } catch (e) {
+            console.error("Cannot fetch pdoc search index");
+            searchErr = "Cannot fetch search index.";
+        }
+        onInput();
+
+        document.querySelector("nav.pdoc").addEventListener("click", e => {
+            if (e.target.hash) {
+                searchBox.value = "";
+                searchBox.dispatchEvent(new Event("input"));
+            }
+        });
+    }
+
+    function onInput() {
+        setContent((() => {
+            const term = getSearchTerm();
+            if (!term) {
+                return null
+            }
+            if (searchErr) {
+                return `<h3>Error: ${searchErr}</h3>`
+            }
+            if (!search) {
+                return "<h3>Searching...</h3>"
+            }
+
+            window.scrollTo({top: 0, left: 0, behavior: 'auto'});
+
+            const results = search(term);
+
+            let html;
+            if (results.length === 0) {
+                html = `No search results for '${escapeHTML(term)}'.`
+            } else {
+                html = `<h4>${results.length} search result${results.length > 1 ? "s" : ""} for '${escapeHTML(term)}'.</h4>`;
+            }
+            for (let result of results.slice(0, 10)) {
+                let doc = result.doc;
+                let url = `../${doc.modulename.replaceAll(".", "/")}.html`;
+                if (doc.qualname) {
+                    url += `#${doc.qualname}`;
+                }
+
+                let heading;
+                switch (result.doc.kind) {
+                    case "function":
+                        if (doc.fullname.endsWith(".__init__")) {
+                            heading = `<span class="name">${doc.fullname.replace(/\.__init__$/, "")}</span>${doc.signature}`;
+                        } else {
+                            heading = `<span class="def">${doc.funcdef}</span> <span class="name">${doc.fullname}</span>${doc.signature}`;
+                        }
+                        break;
+                    case "class":
+                        heading = `<span class="def">class</span> <span class="name">${doc.fullname}</span>`;
+                        if (doc.bases)
+                            heading += `<wbr>(<span class="base">${doc.bases}</span>)`;
+                        heading += `:`;
+                        break;
+                    case "variable":
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        if (doc.annotation)
+                            heading += `<span class="annotation">${doc.annotation}</span>`;
+                        if (doc.default_value)
+                            heading += `<span class="default_value"> = ${doc.default_value}</span>`;
+                        break;
+                    default:
+                        heading = `<span class="name">${doc.fullname}</span>`;
+                        break;
+                }
+                html += `
+                        <section class="search-result">
+                        <a href="${url}" class="attr ${doc.kind}">${heading}</a>
+                        <div class="docstring">${doc.doc}</div>
+                        </section>
+                    `;
+
+            }
+            return html;
+        })());
+    }
+
+    if (getSearchTerm()) {
+        initialize();
+        searchBox.value = getSearchTerm();
+        onInput();
+    } else {
+        searchBox.addEventListener("focus", initialize, {once: true});
+    }
+
+    searchBox.addEventListener("keydown", e => {
+        if (["ArrowDown", "ArrowUp", "Enter"].includes(e.key)) {
+            let focused = currentContent.querySelector(".search-result.focused");
+            if (!focused) {
+                currentContent.querySelector(".search-result").classList.add("focused");
+            } else if (
+                e.key === "ArrowDown"
+                && focused.nextElementSibling
+                && focused.nextElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.nextElementSibling.classList.add("focused");
+                focused.nextElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "ArrowUp"
+                && focused.previousElementSibling
+                && focused.previousElementSibling.classList.contains("search-result")
+            ) {
+                focused.classList.remove("focused");
+                focused.previousElementSibling.classList.add("focused");
+                focused.previousElementSibling.scrollIntoView({
+                    behavior: "smooth",
+                    block: "nearest",
+                    inline: "nearest"
+                });
+            } else if (
+                e.key === "Enter"
+            ) {
+                focused.querySelector("a").click();
+            }
+        }
+    });
+</script></body>
+</html>
\ No newline at end of file
diff --git a/docs/search.js b/docs/search.js
new file mode 100644
index 0000000..048a1e9
--- /dev/null
+++ b/docs/search.js
@@ -0,0 +1,46 @@
+window.pdocSearch = (function(){
+/** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u<s.length;u++){var a=s[u];r[a]=this.pipeline.run(t.tokenizer(e[a]))}var l={};for(var c in o){var d=r[c]||r.any;if(d){var f=this.fieldSearch(d,c,o),h=o[c].boost;for(var p in f)f[p]=f[p]*h;for(var p in f)p in l?l[p]+=f[p]:l[p]=f[p]}}var v,g=[];for(var p in l)v={ref:p,score:l[p]},this.documentStore.hasDoc(p)&&(v.doc=this.documentStore.getDoc(p)),g.push(v);return g.sort(function(e,t){return t.score-e.score}),g},t.Index.prototype.fieldSearch=function(e,t,n){var i=n[t].bool,o=n[t].expand,r=n[t].boost,s=null,u={};return 0!==r?(e.forEach(function(e){var n=[e];1==o&&(n=this.index[t].expandToken(e));var r={};n.forEach(function(n){var o=this.index[t].getDocs(n),a=this.idf(n,t);if(s&&"AND"==i){var l={};for(var c in s)c in o&&(l[c]=o[c]);o=l}n==e&&this.fieldSearchStats(u,n,o);for(var c in o){var d=this.index[t].getTermFrequency(n,c),f=this.documentStore.getFieldLength(c,t),h=1;0!=f&&(h=1/Math.sqrt(f));var p=1;n!=e&&(p=.15*(1-(n.length-e.length)/n.length));var v=d*a*h*p;c in r?r[c]+=v:r[c]=v}},this),s=this.mergeScores(s,r,i)},this),s=this.coordNorm(s,u,e.length)):void 0},t.Index.prototype.mergeScores=function(e,t,n){if(!e)return t;if("AND"==n){var i={};for(var o in t)o in e&&(i[o]=e[o]+t[o]);return i}for(var o in t)o in e?e[o]+=t[o]:e[o]=t[o];return e},t.Index.prototype.fieldSearchStats=function(e,t,n){for(var i in n)i in e?e[i].push(t):e[i]=[t]},t.Index.prototype.coordNorm=function(e,t,n){for(var i in e)if(i in t){var o=t[i].length;e[i]=e[i]*o/n}return e},t.Index.prototype.toJSON=function(){var e={};return this._fields.forEach(function(t){e[t]=this.index[t].toJSON()},this),{version:t.version,fields:this._fields,ref:this._ref,documentStore:this.documentStore.toJSON(),index:e,pipeline:this.pipeline.toJSON()}},t.Index.prototype.use=function(e){var t=Array.prototype.slice.call(arguments,1);t.unshift(this),e.apply(this,t)},t.DocumentStore=function(e){this._save=null===e||void 0===e?!0:e,this.docs={},this.docInfo={},this.length=0},t.DocumentStore.load=function(e){var t=new this;return t.length=e.length,t.docs=e.docs,t.docInfo=e.docInfo,t._save=e.save,t},t.DocumentStore.prototype.isDocStored=function(){return this._save},t.DocumentStore.prototype.addDoc=function(t,n){this.hasDoc(t)||this.length++,this.docs[t]=this._save===!0?e(n):null},t.DocumentStore.prototype.getDoc=function(e){return this.hasDoc(e)===!1?null:this.docs[e]},t.DocumentStore.prototype.hasDoc=function(e){return e in this.docs},t.DocumentStore.prototype.removeDoc=function(e){this.hasDoc(e)&&(delete this.docs[e],delete this.docInfo[e],this.length--)},t.DocumentStore.prototype.addFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&(this.docInfo[e]||(this.docInfo[e]={}),this.docInfo[e][t]=n)},t.DocumentStore.prototype.updateFieldLength=function(e,t,n){null!==e&&void 0!==e&&0!=this.hasDoc(e)&&this.addFieldLength(e,t,n)},t.DocumentStore.prototype.getFieldLength=function(e,t){return null===e||void 0===e?0:e in this.docs&&t in this.docInfo[e]?this.docInfo[e][t]:0},t.DocumentStore.prototype.toJSON=function(){return{docs:this.docs,docInfo:this.docInfo,length:this.length,save:this._save}},t.stemmer=function(){var e={ational:"ate",tional:"tion",enci:"ence",anci:"ance",izer:"ize",bli:"ble",alli:"al",entli:"ent",eli:"e",ousli:"ous",ization:"ize",ation:"ate",ator:"ate",alism:"al",iveness:"ive",fulness:"ful",ousness:"ous",aliti:"al",iviti:"ive",biliti:"ble",logi:"log"},t={icate:"ic",ative:"",alize:"al",iciti:"ic",ical:"ic",ful:"",ness:""},n="[^aeiou]",i="[aeiouy]",o=n+"[^aeiouy]*",r=i+"[aeiou]*",s="^("+o+")?"+r+o,u="^("+o+")?"+r+o+"("+r+")?$",a="^("+o+")?"+r+o+r+o,l="^("+o+")?"+i,c=new RegExp(s),d=new RegExp(a),f=new RegExp(u),h=new RegExp(l),p=/^(.+?)(ss|i)es$/,v=/^(.+?)([^s])s$/,g=/^(.+?)eed$/,m=/^(.+?)(ed|ing)$/,y=/.$/,S=/(at|bl|iz)$/,x=new RegExp("([^aeiouylsz])\\1$"),w=new RegExp("^"+o+i+"[^aeiouwxy]$"),I=/^(.+?[^aeiou])y$/,b=/^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/,E=/^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/,D=/^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/,F=/^(.+?)(s|t)(ion)$/,_=/^(.+?)e$/,P=/ll$/,k=new RegExp("^"+o+i+"[^aeiouwxy]$"),z=function(n){var i,o,r,s,u,a,l;if(n.length<3)return n;if(r=n.substr(0,1),"y"==r&&(n=r.toUpperCase()+n.substr(1)),s=p,u=v,s.test(n)?n=n.replace(s,"$1$2"):u.test(n)&&(n=n.replace(u,"$1$2")),s=g,u=m,s.test(n)){var z=s.exec(n);s=c,s.test(z[1])&&(s=y,n=n.replace(s,""))}else if(u.test(n)){var z=u.exec(n);i=z[1],u=h,u.test(i)&&(n=i,u=S,a=x,l=w,u.test(n)?n+="e":a.test(n)?(s=y,n=n.replace(s,"")):l.test(n)&&(n+="e"))}if(s=I,s.test(n)){var z=s.exec(n);i=z[1],n=i+"i"}if(s=b,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+e[o])}if(s=E,s.test(n)){var z=s.exec(n);i=z[1],o=z[2],s=c,s.test(i)&&(n=i+t[o])}if(s=D,u=F,s.test(n)){var z=s.exec(n);i=z[1],s=d,s.test(i)&&(n=i)}else if(u.test(n)){var z=u.exec(n);i=z[1]+z[2],u=d,u.test(i)&&(n=i)}if(s=_,s.test(n)){var z=s.exec(n);i=z[1],s=d,u=f,a=k,(s.test(i)||u.test(i)&&!a.test(i))&&(n=i)}return s=P,u=d,s.test(n)&&u.test(n)&&(s=y,n=n.replace(s,"")),"y"==r&&(n=r.toLowerCase()+n.substr(1)),n};return z}(),t.Pipeline.registerFunction(t.stemmer,"stemmer"),t.stopWordFilter=function(e){return e&&t.stopWordFilter.stopWords[e]!==!0?e:void 0},t.clearStopWords=function(){t.stopWordFilter.stopWords={}},t.addStopWords=function(e){null!=e&&Array.isArray(e)!==!1&&e.forEach(function(e){t.stopWordFilter.stopWords[e]=!0},this)},t.resetStopWords=function(){t.stopWordFilter.stopWords=t.defaultStopWords},t.defaultStopWords={"":!0,a:!0,able:!0,about:!0,across:!0,after:!0,all:!0,almost:!0,also:!0,am:!0,among:!0,an:!0,and:!0,any:!0,are:!0,as:!0,at:!0,be:!0,because:!0,been:!0,but:!0,by:!0,can:!0,cannot:!0,could:!0,dear:!0,did:!0,"do":!0,does:!0,either:!0,"else":!0,ever:!0,every:!0,"for":!0,from:!0,get:!0,got:!0,had:!0,has:!0,have:!0,he:!0,her:!0,hers:!0,him:!0,his:!0,how:!0,however:!0,i:!0,"if":!0,"in":!0,into:!0,is:!0,it:!0,its:!0,just:!0,least:!0,let:!0,like:!0,likely:!0,may:!0,me:!0,might:!0,most:!0,must:!0,my:!0,neither:!0,no:!0,nor:!0,not:!0,of:!0,off:!0,often:!0,on:!0,only:!0,or:!0,other:!0,our:!0,own:!0,rather:!0,said:!0,say:!0,says:!0,she:!0,should:!0,since:!0,so:!0,some:!0,than:!0,that:!0,the:!0,their:!0,them:!0,then:!0,there:!0,these:!0,they:!0,"this":!0,tis:!0,to:!0,too:!0,twas:!0,us:!0,wants:!0,was:!0,we:!0,were:!0,what:!0,when:!0,where:!0,which:!0,"while":!0,who:!0,whom:!0,why:!0,will:!0,"with":!0,would:!0,yet:!0,you:!0,your:!0},t.stopWordFilter.stopWords=t.defaultStopWords,t.Pipeline.registerFunction(t.stopWordFilter,"stopWordFilter"),t.trimmer=function(e){if(null===e||void 0===e)throw new Error("token should not be undefined");return e.replace(/^\W+/,"").replace(/\W+$/,"")},t.Pipeline.registerFunction(t.trimmer,"trimmer"),t.InvertedIndex=function(){this.root={docs:{},df:0}},t.InvertedIndex.load=function(e){var t=new this;return t.root=e.root,t},t.InvertedIndex.prototype.addToken=function(e,t,n){for(var n=n||this.root,i=0;i<=e.length-1;){var o=e[i];o in n||(n[o]={docs:{},df:0}),i+=1,n=n[o]}var r=t.ref;n.docs[r]?n.docs[r]={tf:t.tf}:(n.docs[r]={tf:t.tf},n.df+=1)},t.InvertedIndex.prototype.hasToken=function(e){if(!e)return!1;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return!1;t=t[e[n]]}return!0},t.InvertedIndex.prototype.getNode=function(e){if(!e)return null;for(var t=this.root,n=0;n<e.length;n++){if(!t[e[n]])return null;t=t[e[n]]}return t},t.InvertedIndex.prototype.getDocs=function(e){var t=this.getNode(e);return null==t?{}:t.docs},t.InvertedIndex.prototype.getTermFrequency=function(e,t){var n=this.getNode(e);return null==n?0:t in n.docs?n.docs[t].tf:0},t.InvertedIndex.prototype.getDocFreq=function(e){var t=this.getNode(e);return null==t?0:t.df},t.InvertedIndex.prototype.removeToken=function(e,t){if(e){var n=this.getNode(e);null!=n&&t in n.docs&&(delete n.docs[t],n.df-=1)}},t.InvertedIndex.prototype.expandToken=function(e,t,n){if(null==e||""==e)return[];var t=t||[];if(void 0==n&&(n=this.getNode(e),null==n))return t;n.df>0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e<arguments.length;e++)t=arguments[e],~this.indexOf(t)||this.elements.splice(this.locationFor(t),0,t);this.length=this.elements.length},lunr.SortedSet.prototype.toArray=function(){return this.elements.slice()},lunr.SortedSet.prototype.map=function(e,t){return this.elements.map(e,t)},lunr.SortedSet.prototype.forEach=function(e,t){return this.elements.forEach(e,t)},lunr.SortedSet.prototype.indexOf=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]<u[i]?n++:s[n]>u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();o<r.length;o++)i.add(r[o]);return i},lunr.SortedSet.prototype.toJSON=function(){return this.toArray()},function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():e.elasticlunr=t()}(this,function(){return t})}();
+    /** pdoc search index */const docs = [{"fullname": "perplexipy", "modulename": "perplexipy", "kind": "module", "doc": "<p>% perplexipy(3) Version 0.0.7 | Perplexity AI high level API documentation</p>\n\n<h1 id=\"name\">Name</h1>\n\n<p><strong>perplexipy</strong> - Perplexity AI high level library</p>\n\n<h1 id=\"synopsis\">Synopsis</h1>\n\n<div class=\"pdoc-code codehilite\">\n<pre><span></span><code><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">PerplexityClient</span><span class=\"p\">()</span> \\\n<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">query</span><span class=\"p\">(</span><span class=\"s1\">&#39;What is the meaning of 42?&#39;</span><span class=\"p\">)</span> \\\n<span class=\"k\">for</span> <span class=\"n\">result</span> <span class=\"ow\">in</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">queryStreamable</span><span class=\"p\">(</span><span class=\"s1\">&#39;List of all US presidents&#39;</span><span class=\"p\">):</span> \\\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">result</span><span class=\"p\">)</span>\n</code></pre>\n</div>\n\n<h1 id=\"description\">Description</h1>\n\n<p><strong>perplexipy</strong> is a high-level, convenience library for interacting with the\nPerplexity API from any Python 3.9+ application.  The library aims to simplify\ninteractions with Perplexity models by encapsulating all the implementation\ndetails of the lower level OpenAI API.  All interaction between the code and\nthis library occurs in the form of string and native Python objects, not\nOpenAPI / Swagger mapped objects.</p>\n\n<p><strong>perplexipy</strong> implements a combination of the Perplexity AI and the\nOpenAI outputs.  API semantics follow the \"literate programming\" workflow,\nand attempt to make the resulting code as simple to follow as possible.</p>\n\n<p><a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a> is an\nAI-powered search engine that uses natural language\nprocessing and machine learning to provide accurate and comprehensive answers to\nend-user queries.  It can be argued that it outperforms OpenAI's offerings in\naccuracy and responsiveness.  <strong>perplexypi</strong> enables the creation of Python\nprograms and tools that leverage the power of Perplexity AI.</p>\n\n<h1 id=\"documentation\">Documentation</h1>\n\n<p>These documents encompass all information about <strong>perplexipy</strong>:</p>\n\n<ul>\n<li>This README file, hosted in the <strong><a href=\"https://github.com/CIME-Software/perplexipy\">perplexipy</a></strong>\nproject on GitHub and exported to the PyPI project page</li>\n<li>A <code>man</code> page autogenerated from this README file, <code>perplexipy.3</code></li>\n<li>The complete <strong>perplexipy API reference</strong></li>\n<li>The <strong>using-perplexipy.ipynb</strong> tutorial notebook - see: <a href=\"https://github.com/CIME-Software/perplexipy/issues/18\">https://github.com/CIME-Software/perplexipy/issues/18</a></li>\n</ul>\n\n<p>The <code>man</code> page can be generated from the source distribution using this command:</p>\n\n<div class=\"pdoc-code codehilite\">\n<pre><span></span><code>make<span class=\"w\"> </span>manpage\n</code></pre>\n</div>\n\n<p>The output will reside in:  <code>./manpages/perplexipy.3</code>.  The <code>man</code> page isn't\nincluded in the Python package wheel because there's no accepted standard\ninstallation that's cross-compatible among all supported operating systems and\ndistributions.</p>\n\n<h1 id=\"installation\">Installation</h1>\n\n<div class=\"pdoc-code codehilite\">\n<pre><span></span><code>pip<span class=\"w\"> </span>install<span class=\"w\"> </span>perplexipy\n</code></pre>\n</div>\n\n<p>Package information:  <a href=\"https://pypi.org/project/perplexipy\">https://pypi.org/project/perplexipy</a></p>\n\n<h1 id=\"api-key\">API key</h1>\n\n<p>Access to the Perplexity API requires a paid subscription and an API key.</p>\n\n<p>Use of <code>.env</code> is recommended for storing the private key.  There is an automatic\nconstant <code>PERPLEXITY_API_KEY</code> that gets initialized to the value of a <code>.env</code> key\nof the same name via the <code>dotenv</code> API.  Otherwise, <code>PERPLEXITY_API_KEY</code> may\nbe handled like any other secret by the implementing team.  This module provides\nno other tools or services for handling the API key.</p>\n\n<p>This key is used only during <code>PerplexityClient</code> instantiation:</p>\n\n<div class=\"pdoc-code codehilite\">\n<pre><span></span><code><span class=\"kn\">import</span> <span class=\"nn\">os</span>\n\n<span class=\"n\">key</span> <span class=\"o\">=</span> <span class=\"n\">os</span><span class=\"o\">.</span><span class=\"n\">environ</span><span class=\"p\">[</span><span class=\"s1\">&#39;PERPLEXITY_API_KEY&#39;</span><span class=\"p\">]</span>\n<span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">PerplexityClient</span><span class=\"p\">(</span><span class=\"n\">key</span> <span class=\"o\">=</span> <span class=\"n\">key</span><span class=\"p\">)</span>\n<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">query</span><span class=\"p\">(</span><span class=\"s1\">&#39;Brief answer:  greet the world in Swedish.&#39;</span><span class=\"p\">))</span>\n</code></pre>\n</div>\n\n<h1 id=\"usage\">Usage</h1>\n\n<p>See the <strong>using-perplexipy.ipynb</strong> (<a href=\"https://github.com/CIME-Software/perplexipy/issues/18\">https://github.com/CIME-Software/perplexipy/issues/18</a>) notebook for a richer example of the API's\ncapabilities.</p>\n\n<p>In general:</p>\n\n<div class=\"pdoc-code codehilite\">\n<pre><span></span><code><span class=\"n\">client</span> <span class=\"o\">=</span> <span class=\"n\">PerplexityClient</span><span class=\"p\">()</span>\n<span class=\"n\">result</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">query</span><span class=\"p\">(</span><span class=\"s1\">&#39;Show me how to declare a list in Python&#39;</span><span class=\"p\">)</span>\n<span class=\"c1\"># result is a string</span>\n\n<span class=\"n\">results</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">queryBatch</span><span class=\"p\">(</span><span class=\"s1\">&#39;Show me different ways of declaring a Python list&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">for</span> <span class=\"n\">result</span> <span class=\"ow\">in</span> <span class=\"n\">results</span><span class=\"p\">:</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">result</span><span class=\"p\">)</span>\n    <span class=\"c1\"># results is a tuple of one or more results</span>\n\n<span class=\"n\">results</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">queryStreamable</span><span class=\"p\">(</span><span class=\"s1\">&#39;Tell me why lists are important in programming&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">for</span> <span class=\"n\">result</span> <span class=\"ow\">in</span> <span class=\"n\">results</span><span class=\"p\">:</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">result</span><span class=\"p\">)</span>\n    <span class=\"c1\"># results is a long stream of data, served over time.</span>\n\n<span class=\"n\">models</span> <span class=\"o\">=</span> <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">models</span> <span class=\"c1\"># lists all models supported by Perplexity AI</span>\n\n<span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s1\">&#39;Model names:&#39;</span><span class=\"p\">)</span>\n<span class=\"k\">for</span> <span class=\"n\">model</span> <span class=\"ow\">in</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">():</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"s1\">&#39; - </span><span class=\"si\">%s</span><span class=\"s1\">&#39;</span> <span class=\"o\">%</span> <span class=\"n\">model</span><span class=\"p\">)</span>\n\n<span class=\"k\">try</span><span class=\"p\">:</span>\n    <span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"s1\">&#39;bogus-LLM-7b&#39;</span>\n<span class=\"k\">except</span> <span class=\"n\">PerplexityClientError</span> <span class=\"k\">as</span> <span class=\"n\">e</span><span class=\"p\">:</span>\n    <span class=\"nb\">print</span><span class=\"p\">(</span><span class=\"n\">e</span><span class=\"p\">)</span>\n\n<span class=\"n\">client</span><span class=\"o\">.</span><span class=\"n\">model</span> <span class=\"o\">=</span> <span class=\"n\">models</span><span class=\"o\">.</span><span class=\"n\">keys</span><span class=\"p\">()[</span><span class=\"mi\">0</span><span class=\"p\">]</span> <span class=\"c1\"># OK</span>\n</code></pre>\n</div>\n\n<h1 id=\"async-usage\">Async usage</h1>\n\n<p>Not supported at this time.</p>\n\n<h1 id=\"license\">License</h1>\n\n<p>The <strong>perplexipy</strong> package, documentation and examples are licensed under the\n<a href=\"https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt\">BSD-3 open source license</a>.</p>\n\n<h1 id=\"see-also\">See also</h1>\n\n<ul>\n<li>PyPI:  <a href='https://pipy.org/project/openai' target='_blank'>openai</a></li>\n<li><a href='https://www.perplexity.ai/' target='_blank'>Perplexity AI</a></li>\n</ul>\n\n<h1 id=\"caveats\">Caveats</h1>\n\n<p>The code should work with Python 3.7 or later, but it was only tested with\nPython 3.9.16 and later.  Download the package and install it from source if\nsupport for an earlier Python version is required.</p>\n\n<h1 id=\"bugs\">Bugs</h1>\n\n<p>Feature requests and bug reports:</p>\n\n<p><a href=\"https://github.com/CIME-Software/perplexipy/issues\">https://github.com/CIME-Software/perplexipy/issues</a></p>\n\n<hr />\n\n<h1 id=\"perplexipy-api-documentation\">perplexipy API Documentation</h1>\n"}, {"fullname": "perplexipy.PERPLEXITY_API_KEY", "modulename": "perplexipy", "qualname": "PERPLEXITY_API_KEY", "kind": "variable", "doc": "<p></p>\n", "default_value": "&#x27;&#x27;"}, {"fullname": "perplexipy.PERPLEXITY_API_URL", "modulename": "perplexipy", "qualname": "PERPLEXITY_API_URL", "kind": "variable", "doc": "<p>The default model is <strong>mistral-7b-instruct</strong> because of it's efficiency and\nperformance qualities.  Ref:  <a href=\"https://arxiv.org/abs/2310.06825\">https://arxiv.org/abs/2310.06825</a></p>\n", "default_value": "&#x27;https://api.perplexity.ai&#x27;"}, {"fullname": "perplexipy.PERPLEXITY_DEFAULT_MODEL", "modulename": "perplexipy", "qualname": "PERPLEXITY_DEFAULT_MODEL", "kind": "variable", "doc": "<p></p>\n", "default_value": "&#x27;mistral-7b-instruct&#x27;"}, {"fullname": "perplexipy.PERPLEXITY_DEFAULT_ROLE", "modulename": "perplexipy", "qualname": "PERPLEXITY_DEFAULT_ROLE", "kind": "variable", "doc": "<p></p>\n", "default_value": "&#x27;user&#x27;"}, {"fullname": "perplexipy.PERPLEXITY_TIMEOUT", "modulename": "perplexipy", "qualname": "PERPLEXITY_TIMEOUT", "kind": "variable", "doc": "<p>Immutable dictionary-like object of a model's capabilities.  Use <code>_asDict()</code> if\ndictionary manipulation is required.</p>\n", "default_value": "30.0"}, {"fullname": "perplexipy.ModelInfo", "modulename": "perplexipy", "qualname": "ModelInfo", "kind": "class", "doc": "<p>ModelInfo(parameterCount, contextLength, modelType, availability)</p>\n", "bases": "builtins.tuple"}, {"fullname": "perplexipy.ModelInfo.__init__", "modulename": "perplexipy", "qualname": "ModelInfo.__init__", "kind": "function", "doc": "<p>Create new instance of ModelInfo(parameterCount, contextLength, modelType, availability)</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"n\">parameterCount</span>, </span><span class=\"param\"><span class=\"n\">contextLength</span>, </span><span class=\"param\"><span class=\"n\">modelType</span>, </span><span class=\"param\"><span class=\"n\">availability</span></span>)</span>"}, {"fullname": "perplexipy.ModelInfo.parameterCount", "modulename": "perplexipy", "qualname": "ModelInfo.parameterCount", "kind": "variable", "doc": "<p>Alias for field number 0</p>\n"}, {"fullname": "perplexipy.ModelInfo.contextLength", "modulename": "perplexipy", "qualname": "ModelInfo.contextLength", "kind": "variable", "doc": "<p>Alias for field number 1</p>\n"}, {"fullname": "perplexipy.ModelInfo.modelType", "modulename": "perplexipy", "qualname": "ModelInfo.modelType", "kind": "variable", "doc": "<p>Alias for field number 2</p>\n"}, {"fullname": "perplexipy.ModelInfo.availability", "modulename": "perplexipy", "qualname": "ModelInfo.availability", "kind": "variable", "doc": "<p>Alias for field number 3</p>\n"}, {"fullname": "perplexipy.PerplexityClient", "modulename": "perplexipy", "qualname": "PerplexityClient", "kind": "class", "doc": "<p>PerplexityClient objects encapsulate all the API functionality.  They can be\ninstantiated across multiple contexts, each keeping its own state.</p>\n"}, {"fullname": "perplexipy.PerplexityClient.__init__", "modulename": "perplexipy", "qualname": "PerplexityClient.__init__", "kind": "function", "doc": "<p>Create a new instance of <code>perplexipy.PerplexityClient</code> using the API\n<code>key</code> to connect to the corresponding <code>endpoint</code>.</p>\n\n<h2 id=\"arguments\">Arguments</h2>\n\n<pre><code>key\n</code></pre>\n\n<p>A valid API key string.  If not present, it defaults to <code>perplexipy.PERPLEXITY_API_KEY</code>.</p>\n\n<pre><code>endpoint\n</code></pre>\n\n<p>An string representing a URL to the Perplexity API.</p>\n\n<h2 id=\"returns\">Returns</h2>\n\n<p>An instance of <code>perplexipy.PerplexityClient</code> if successful.</p>\n\n<p>Attributes:</p>\n\n<p><code>model</code> - the current model to use in queries, user configurable.</p>\n\n<p>The role is fixed to <code>\"user\"</code> for Perplexity calls, per the API\nrecommendations.</p>\n\n<h2 id=\"raises\">Raises</h2>\n\n<pre><code>PerplexityClientError\n</code></pre>\n\n<p>If the API key is empty, or doesn't match one of the valid API prefixes\nper the documentation.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"n\">key</span><span class=\"o\">=</span><span class=\"s1\">&#39;&#39;</span>, </span><span class=\"param\"><span class=\"n\">endpoint</span><span class=\"o\">=</span><span class=\"s1\">&#39;https://api.perplexity.ai&#39;</span></span>)</span>"}, {"fullname": "perplexipy.PerplexityClient.query", "modulename": "perplexipy", "qualname": "PerplexityClient.query", "kind": "function", "doc": "<p>Send a single message query to the service, receive a single response.</p>\n\n<h2 id=\"arguments\">Arguments</h2>\n\n<pre><code>query\n</code></pre>\n\n<p>A string with the query in one of the model's supported languages.</p>\n\n<h2 id=\"returns\">Returns</h2>\n\n<p>A string with a response from the Perplexity service.</p>\n\n<h2 id=\"raises\">Raises</h2>\n\n<pre><code>Exception\n</code></pre>\n\n<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has\nsomething other than text data.  The error raised passes through\nwhatever the API raised.</p>\n\n<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>\n\n<pre><code>PerplexityClientError\n</code></pre>\n\n<p>If the query is <code>None</code> or empty.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"bp\">self</span>, </span><span class=\"param\"><span class=\"n\">query</span><span class=\"p\">:</span> <span class=\"nb\">str</span></span><span class=\"return-annotation\">) -> <span class=\"nb\">str</span>:</span></span>", "funcdef": "def"}, {"fullname": "perplexipy.PerplexityClient.queryBatch", "modulename": "perplexipy", "qualname": "PerplexityClient.queryBatch", "kind": "function", "doc": "<p>Send a single message query to the service, receive a single response.</p>\n\n<h2 id=\"arguments\">Arguments</h2>\n\n<pre><code>query\n</code></pre>\n\n<p>A string with the query in one of the model's supported languages.</p>\n\n<h2 id=\"returns\">Returns</h2>\n\n<p>A tuple with a batch of 1 or more response strings.</p>\n\n<h2 id=\"raises\">Raises</h2>\n\n<pre><code>Exception\n</code></pre>\n\n<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has\nsomething other than text data.  The error raised passes through\nwhatever the API raised.</p>\n\n<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>\n\n<pre><code>PerplexityClientError\n</code></pre>\n\n<p>If the query is <code>None</code> or empty.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"bp\">self</span>, </span><span class=\"param\"><span class=\"n\">query</span><span class=\"p\">:</span> <span class=\"nb\">str</span></span><span class=\"return-annotation\">) -> <span class=\"nb\">tuple</span>:</span></span>", "funcdef": "def"}, {"fullname": "perplexipy.PerplexityClient.queryStreamable", "modulename": "perplexipy", "qualname": "PerplexityClient.queryStreamable", "kind": "function", "doc": "<p>Send a query and return a long, streamable response.</p>\n\n<h2 id=\"arguments\">Arguments</h2>\n\n<pre><code>query\n</code></pre>\n\n<p>A string with the query in one of the model's supported languages.</p>\n\n<h2 id=\"returns\">Returns</h2>\n\n<p>Returns a <code>perplexipy.Responses</code> object for streaming the textual\nresponses from the client.  The response strips all metadata and returns\nonly content strings, for simpler and easier integration.</p>\n\n<h2 id=\"raises\">Raises</h2>\n\n<pre><code>Exception\n</code></pre>\n\n<p>An <code>openai.BadRequestError</code> or similar if the query is malformed or has\nsomething other than text data.  The error raised passes through\nwhatever the API raised.</p>\n\n<p>In most cases, the API returns <code>openai.BadRequestError</code>.</p>\n\n<pre><code>PerplexityClientError\n</code></pre>\n\n<p>If the query is <code>None</code> or empty.</p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"bp\">self</span>, </span><span class=\"param\"><span class=\"n\">query</span><span class=\"p\">:</span> <span class=\"nb\">str</span></span><span class=\"return-annotation\">) -> <span class=\"n\">perplexipy</span><span class=\"o\">.</span><span class=\"n\">responses</span><span class=\"o\">.</span><span class=\"n\">Responses</span>:</span></span>", "funcdef": "def"}, {"fullname": "perplexipy.PerplexityClient.models", "modulename": "perplexipy", "qualname": "PerplexityClient.models", "kind": "variable", "doc": "<p>Provide a dictionary of the models supported by Perplexity listed in:</p>\n\n<p><a href=\"https://docs.perplexity.ai/docs/model-cards\">https://docs.perplexity.ai/docs/model-cards</a></p>\n\n<h2 id=\"returns\">Returns</h2>\n\n<p>A dictionary of supported models as the key, with a <code>perplexypy.ModelInfo</code>\nnamed tuple with the model capabilities description.  The model\ninformation attributes are:</p>\n\n<ul>\n<li><code>parameterCount</code></li>\n<li><code>contextLength</code></li>\n<li><code>modelType</code></li>\n<li><code>availability</code></li>\n</ul>\n"}, {"fullname": "perplexipy.PerplexityClient.model", "modulename": "perplexipy", "qualname": "PerplexityClient.model", "kind": "variable", "doc": "<p></p>\n", "annotation": ": str"}, {"fullname": "perplexipy.errors", "modulename": "perplexipy.errors", "kind": "module", "doc": "<p></p>\n"}, {"fullname": "perplexipy.errors.PerplexityClientError", "modulename": "perplexipy.errors", "qualname": "PerplexityClientError", "kind": "class", "doc": "<p>Perplexity client generic errors, for cleaner exception handling.</p>\n", "bases": "builtins.Exception"}, {"fullname": "perplexipy.errors.PerplexityClientError.__init__", "modulename": "perplexipy.errors", "qualname": "PerplexityClientError.__init__", "kind": "function", "doc": "<p></p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"n\">errorMessage</span></span>)</span>"}, {"fullname": "perplexipy.responses", "modulename": "perplexipy.responses", "kind": "module", "doc": "<p></p>\n"}, {"fullname": "perplexipy.responses.Responses", "modulename": "perplexipy.responses", "qualname": "Responses", "kind": "class", "doc": "<p>Encapsulates all the streaming responses from a query and enables access to\nit using a purpose-built iterable.  Strips all the OpenAI response metadata\nand returns only the textual response.  It's a streaming iterable,\nopen-ended.</p>\n"}, {"fullname": "perplexipy.responses.Responses.__init__", "modulename": "perplexipy.responses", "qualname": "Responses.__init__", "kind": "function", "doc": "<p></p>\n", "signature": "<span class=\"signature pdoc-code condensed\">(<span class=\"param\"><span class=\"n\">responsesStream</span></span>)</span>"}];
+
+    // mirrored in build-search-index.js (part 1)
+    // Also split on html tags. this is a cheap heuristic, but good enough.
+    elasticlunr.tokenizer.setSeperator(/[\s\-.;&_'"=,()]+|<[^>]*>/);
+
+    let searchIndex;
+    if (docs._isPrebuiltIndex) {
+        console.info("using precompiled search index");
+        searchIndex = elasticlunr.Index.load(docs);
+    } else {
+        console.time("building search index");
+        // mirrored in build-search-index.js (part 2)
+        searchIndex = elasticlunr(function () {
+            this.pipeline.remove(elasticlunr.stemmer);
+            this.pipeline.remove(elasticlunr.stopWordFilter);
+            this.addField("qualname");
+            this.addField("fullname");
+            this.addField("annotation");
+            this.addField("default_value");
+            this.addField("signature");
+            this.addField("bases");
+            this.addField("doc");
+            this.setRef("fullname");
+        });
+        for (let doc of docs) {
+            searchIndex.addDoc(doc);
+        }
+        console.timeEnd("building search index");
+    }
+
+    return (term) => searchIndex.search(term, {
+        fields: {
+            qualname: {boost: 4},
+            fullname: {boost: 2},
+            annotation: {boost: 2},
+            default_value: {boost: 2},
+            signature: {boost: 2},
+            bases: {boost: 2},
+            doc: {boost: 1},
+        },
+        expand: true
+    });
+})();
\ No newline at end of file
diff --git a/perplexipy/__init__.py b/perplexipy/__init__.py
index 0aa2033..bc0389c 100644
--- a/perplexipy/__init__.py
+++ b/perplexipy/__init__.py
@@ -1,7 +1,16 @@
 # See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
 
 
-__VERSION__ = '0.0.6'
+"""
+.. include:: ../README.md
+
+---
+
+# perplexipy API Documentation
+"""
+
+
+__VERSION__ = '0.0.7'
 
 
 from collections import namedtuple
@@ -9,6 +18,9 @@
 from dotenv import load_dotenv
 from openai import OpenAI
 
+from perplexipy.errors import PerplexityClientError
+from perplexipy.responses import Responses
+
 load_dotenv()
 
 import os
@@ -30,37 +42,6 @@
 PERPLEXITY_TIMEOUT = 30.0 # seconds
 
 
-class PerplexityClientError(Exception):
-    """
-    Perplexity client generic errors, for cleaner exception handling.
-    """
-    def __init__(self, errorMessage):
-        super().__init__(errorMessage)
-
-
-class Responses:
-    """
-    Encapsulates all the streaming responses from a query and enables access to
-    it using a purpose-built iterable.  Strips all the OpenAI response metadata
-    and returns only the textual response.  It's a streaming iterable,
-    open-ended.
-    """
-    def __init__(self, responsesStream):
-        self._responsesStream = responsesStream
-
-
-    def __iter__(self):
-        return self
-
-
-    def __next__(self):
-        try:
-            result = self._responsesStream.__next__().choices[0].delta.content
-        except Exception as e:
-            raise e
-        return result
-
-
 """
 Immutable dictionary-like object of a model's capabilities.  Use `_asDict()` if
 dictionary manipulation is required.
diff --git a/perplexipy/errors.py b/perplexipy/errors.py
new file mode 100644
index 0000000..3d8d5c7
--- /dev/null
+++ b/perplexipy/errors.py
@@ -0,0 +1,12 @@
+# See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
+
+
+class PerplexityClientError(Exception):
+    """
+    Perplexity client generic errors, for cleaner exception handling.
+    """
+    def __init__(self, errorMessage):
+        super().__init__(errorMessage)
+
+
+
diff --git a/perplexipy/responses.py b/perplexipy/responses.py
new file mode 100644
index 0000000..9ad6643
--- /dev/null
+++ b/perplexipy/responses.py
@@ -0,0 +1,25 @@
+# See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
+
+
+class Responses:
+    """
+    Encapsulates all the streaming responses from a query and enables access to
+    it using a purpose-built iterable.  Strips all the OpenAI response metadata
+    and returns only the textual response.  It's a streaming iterable,
+    open-ended.
+    """
+    def __init__(self, responsesStream):
+        self._responsesStream = responsesStream
+
+
+    def __iter__(self):
+        return self
+
+
+    def __next__(self):
+        try:
+            result = self._responsesStream.__next__().choices[0].delta.content
+        except Exception as e:
+            raise e
+        return result
+
diff --git a/resources/perplexipy-logo-00.png b/resources/perplexipy-logo-00.png
new file mode 100644
index 0000000..ee98161
Binary files /dev/null and b/resources/perplexipy-logo-00.png differ


Test patch:
diff --git a/tests/errors-test.py b/tests/errors-test.py
new file mode 100644
index 0000000..fa2bc4b
--- /dev/null
+++ b/tests/errors-test.py
@@ -0,0 +1,13 @@
+# See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
+
+
+from perplexipy.errors import PerplexityClientError
+
+
+# +++ tests +++
+
+def test_PerplexityClientError():
+    e = PerplexityClientError('This is a test')
+
+    assert str(e) == 'This is a test'
+
diff --git a/tests/perplexipy-test.py b/tests/perplexipy-test.py
index c680a55..84522c7 100644
--- a/tests/perplexipy-test.py
+++ b/tests/perplexipy-test.py
@@ -1,8 +1,8 @@
 # See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
 
 from perplexipy import PerplexityClient
-from perplexipy import PerplexityClientError
-from perplexipy import Responses
+from perplexipy.errors import PerplexityClientError
+from perplexipy.responses import Responses
 
 import pytest
 
diff --git a/tests/responses-test.py b/tests/responses-test.py
new file mode 100644
index 0000000..50f7a42
--- /dev/null
+++ b/tests/responses-test.py
@@ -0,0 +1,12 @@
+# See: https://github.com/CIME-Software/perplexipy/blob/master/LICENSE.txt
+
+
+import pytest
+
+
+# +++ tests +++
+
+@pytest.mark.skip('The classes and objects are tested in the main perplexipy module')
+def test_Responses():
+    pass
+