Views
The page that a browser sees at a deployed LLMClient’s endpoints.
A deployed LLMClient’s endpoints, /config/ and /prompt/, are api endpoints that answer only POST.
A browser that opens one of them, or the LLMClient’s default url, instead receives a page about the
LLMClient and The Smarter Project: what its url is and how it works, the curl commands that call the
endpoints, the ways to put its chat on a web site, the LLMClient’s manifest, without the personal
information in it, and how to build one. The page is served only while the
enable_llmclient_endpoints_page waffle switch is active.
The Prompt Engineer’s Workbench shows the same content, whatever the switch, in the “Deployment” tab of
its Console: see
smarter.apps.prompt.views.detailviews.prompt_deployment_view.LLMClientDeploymentView. Both
render the @smarter/llmclient-deployment React package’s page, this one as its app, the workbench
as its component, and both build its data with deployment_page(), whose contract is
smarter.apps.llmclient.views.deployment_contract.
See also
smarter.urls.console, which serves LLMClients on their custom domains
- smarter.apps.llmclient.views.endpoints.ALLOWED_ORIGINS_YAML = 'spec:\n config:\n prompt:\n allowedOrigins:\n - https://www.example.com'
The part of an LLMClient’s manifest that allows a web site’s origin to call it.
- smarter.apps.llmclient.views.endpoints.API_KEY_YAML = 'spec:\n apiKey: <API-KEY-NAME>'
The part of an LLMClient’s manifest that attaches an api key to it, by the key’s name.
- smarter.apps.llmclient.views.endpoints.BROWSER_METHODS = ('GET', 'HEAD')
The methods that
browser_friendly()sends toLLMClientEndpointsView.('GET', 'HEAD')
- smarter.apps.llmclient.views.endpoints.DRUPAL_INSTALL_COMMANDS = 'composer config repositories.smarter-drupal vcs https://github.com/smarter-sh/smarter-drupal\ncomposer require smarter-sh/smarter-drupal\ndrush pm:install smarter_chat'
The commands that install Smarter Chat for Drupal.
- smarter.apps.llmclient.views.endpoints.EMBED_SCRIPT_URL = 'https://cdn.jsdelivr.net/npm/@smarter.sh/ui-chat@0/dist/embed.js'
Smarter Chat’s embed script, on jsDelivr, which the page’s html snippet loads.
- smarter.apps.llmclient.views.endpoints.EXAMPLE_PROMPT = 'hello world'
The prompt that the page’s example
/prompt/command sends, for an LLMClient without example prompts.
- smarter.apps.llmclient.views.endpoints.EXAMPLE_RESPONSE_CONTENT = "## The LLM's answer\n\nIn **Markdown**: headings, lists, `code`, tables and [links](https://smarter.sh)."
The assistant message’s content in the page’s example
/prompt/response.
- class smarter.apps.llmclient.views.endpoints.LLMClientEndpointsView(**kwargs)[source]
Bases:
SmarterWebHtmlViewA deployed LLMClient’s endpoints, for a browser, and The Smarter Project, which built it.
The page is the
@smarter/llmclient-deploymentReact app, in its public mode, whose data,deployment_page()’s public copy, is in the page, in ajson_script. It names no owner, and has no api keys. A host that serves no deployed LLMClient is a 404, as it is for the endpoints themselves.- property formatted_class_name: str
Returns the class name in a formatted string along with the name of this view.
- get(request, *args, **kwargs)[source]
The page, for the LLMClient that serves the request’s host.
- Parameters:
request (
HttpRequest) – The request.- Returns:
The page, or a 404 if no deployed LLMClient serves the host.
- Return type:
- smarter.apps.llmclient.views.endpoints.LOGO_PATH = 'images/logo/smarter-crop.png'
The Smarter Project’s logo, on its cdn.
- smarter.apps.llmclient.views.endpoints.MANIFEST_CACHE_TIMEOUT = 600
How long, in seconds,
cached_manifest_yaml()keeps a manifest.
- smarter.apps.llmclient.views.endpoints.MANIFEST_PII_EXCLUDE = {'status': {'username'}}
the personal information in it.
status.usernameis the owner’s username.{'status': set(['username'])}
- Type:
The fields that
manifest_yaml()leaves out of the page’s manifest
- smarter.apps.llmclient.views.endpoints.NPM_INSTALL_COMMAND = 'npm install @smarter.sh/ui-chat'
The command that installs Smarter Chat’s npm package.
- smarter.apps.llmclient.views.endpoints.SESSION_KEY_PLACEHOLDER = '<SESSION-KEY>'
The placeholder of a chat session’s key in the page’s commands, which the config api’s response replaces.
- smarter.apps.llmclient.views.endpoints.SWITCH_COMMAND = 'python manage.py waffle_switch enable_llmclient_endpoints_page off'
The command that turns off the page at deployed LLMClients’ urls, which the page shows administrators.
- smarter.apps.llmclient.views.endpoints.api_keys_url()[source]
The url of the web console’s API Keys page, which lists the account’s api keys, and turns them on and off.
It is absolute, on the platform’s domain, because the page at a deployed LLMClient’s url is on the LLMClient’s own host, whose urlconf has none of the web console’s names.
- Returns:
The url.
- Return type:
- smarter.apps.llmclient.views.endpoints.browser_friendly(api_view)[source]
Wrap a deployed LLMClient’s api view, so that a GET or HEAD receives
LLMClientEndpointsView.Only while the
enable_llmclient_endpoints_pageswitch is active. Every other request, including a GET while it is inactive, goes to the api view. The wrapper keeps the api view’s attributes, e.g.csrf_exempt.path("prompt/", browser_friendly(DefaultLLMClientApiView.as_view())),
- Parameters:
api_view (
Callable[...,HttpResponseBase]) – The api view, fromas_view().- Returns:
The wrapped view.
- Return type:
- smarter.apps.llmclient.views.endpoints.cached_manifest_yaml(llmclient_id, updated_at)[source]
The YAML of an LLMClient’s manifest, for the page, which its broker takes about a second to build.
An update of the LLMClient changes
updated_at, and so the key. A change to a resource that it refers to, e.g. a plugin added to it, shows afterMANIFEST_CACHE_TIMEOUT.- Parameters:
- Returns:
The YAML.
- Return type:
- Raises:
SAMLLMClientBrokerError – If the broker can’t build the manifest, which is then not cached.
- smarter.apps.llmclient.views.endpoints.create_api_key_command(account_number, llmclient_name)[source]
The command that a platform administrator runs to create an api key, which prints its secret once.
- smarter.apps.llmclient.views.endpoints.curl_command(url, body='', authenticated=False)[source]
A curl command that POSTs to a deployed LLMClient’s endpoint, one option per line.
- smarter.apps.llmclient.views.endpoints.deployment_page(llmclient)[source]
The data of the LLMClient’s deployment page: the LLMClient, its url, and the snippets that call it.
An LLMClient that isn’t deployed has the url that it will have once it is, and
deployedis false. The page is the workbench’s, without its owner or api keys, whichLLMClientDeploymentViewadds. The page at the LLMClient’s url is itspublic()copy.- Parameters:
llmclient (
LLMClient) – The LLMClient.- Returns:
The page.
- Return type:
- smarter.apps.llmclient.views.endpoints.embed_html(url, authenticated=False)[source]
The html that adds the LLMClient’s chat to any web page: Smarter Chat’s embed script, as a launcher.
- smarter.apps.llmclient.views.endpoints.example_prompt(llmclient)[source]
The prompt that the page’s example
/prompt/command sends: the LLMClient’s first example prompt.- Parameters:
llmclient (
LLMClient) – The LLMClient.- Returns:
Its first non-empty example prompt, or
EXAMPLE_PROMPTif it has none.- Return type:
- smarter.apps.llmclient.views.endpoints.example_response()[source]
An example of the
/prompt/endpoint’s response, abbreviated to the assistant’s Markdown message.It is built from the chat api contract’s model, so that it can’t drift from the real response.
- Returns:
The response, as indented JSON.
- Return type:
- smarter.apps.llmclient.views.endpoints.llmclient_manifest(llmclient)[source]
The LLMClient’s manifest, as
smarter describe llmclientreturns it, from its broker.- Parameters:
llmclient (
LLMClient) – The LLMClient.- Returns:
The manifest.
- Return type:
- Raises:
SAMLLMClientBrokerError – If the broker can’t build it.
- smarter.apps.llmclient.views.endpoints.manifest_yaml(manifest)[source]
The manifest as YAML, in the order of its model’s fields, without
MANIFEST_PII_EXCLUDE.- Parameters:
manifest (
SAMLLMClient) – The manifest.- Returns:
The YAML.
- Return type:
- smarter.apps.llmclient.views.endpoints.react_snippet(url, authenticated=False)[source]
A React component that displays the LLMClient’s chat, with Smarter Chat’s npm package.
The contract of the deployment page, which the @smarter/llmclient-deployment React app renders, at a
deployed LLMClient’s url and in the workbench’s Deployment tab:
The contract of an LLMClient’s deployment page: the JSON that its React app renders, as Pydantic models.
The @smarter/llmclient-deployment React package renders the page in two places:
public: the page at a deployed LLMClient’s url, which anyone can open,
LLMClientEndpointsView, which puts the page’s data in the page with Django’sjson_script, so that the app renders without a request of its own;workbench: the “Deployment” tab of the Prompt Engineer’s Workbench’s Console, which renders the package’s component, and fetches the page’s data from
LLMClientDeploymentViewwhen the tab is first opened. It adds the LLMClient’s owner and its api keys, and manages them in place.
Both views build a LLMClientDeploymentPage. The workbench’s api key actions are POSTs that answer
with an ApiKeyActionResponse, the page as it now is, or an ErrorResponse. The JSON is
camelCase.
manage.py export_llmclient_deployment_schema writes the models’ JSON Schema to
llmclient-deployment.schema.json, beside this module, from which @smarter/llmclient-deployment
generates its TypeScript types (make llmclient-deployment-contract). A test fails if the committed
schema is out of date.
The public page names no owner and has no api keys: LLMClientDeploymentPage.public() leaves them out.
- class smarter.apps.llmclient.views.deployment_contract.ApiKeyActionResponse(**data)[source]
Bases:
LLMClientDeploymentModelThe page after an api key action, and a new key’s secret.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- page: LLMClientDeploymentPage
- class smarter.apps.llmclient.views.deployment_contract.AttachApiKeyRequest(**data)[source]
Bases:
LLMClientDeploymentModelAttach one of the account’s api keys to the LLMClient, in place of any other.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.CreateApiKeyRequest(**data)[source]
Bases:
LLMClientDeploymentModelCreate an api key for the user, and attach it to the LLMClient if asked to.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentApiKey(**data)[source]
Bases:
LLMClientDeploymentModelOne of the account’s api keys that the user may manage.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentApiKeys(**data)[source]
Bases:
LLMClientDeploymentModelThe LLMClient’s api key, the account’s api keys, what the user may do, and where.
Workbench only.
- api_keys: list[DeploymentApiKey]
- attached: DeploymentAttachedApiKey | None
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentAttachedApiKey(**data)[source]
Bases:
LLMClientDeploymentModelThe LLMClient’s api key, which every request to its url needs, while it is active.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentLLMClient(**data)[source]
Bases:
LLMClientDeploymentModelThe LLMClient, as the page describes it.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentLinks(**data)[source]
Bases:
LLMClientDeploymentModelThe urls that the page links to, which depend on the platform’s configuration.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentOwnership(**data)[source]
Bases:
LLMClientDeploymentModelWho owns the LLMClient, and how a user who may not change it can clone it.
Workbench only.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.DeploymentSnippets(**data)[source]
Bases:
LLMClientDeploymentModelThe commands, manifest excerpts and code that the page shows, each in a terminal with a Copy button.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- smarter.apps.llmclient.views.deployment_contract.ErrorCode
Why an api key action failed, which the React app explains in the user’s language.
alias of
Literal[‘not_found’, ‘invalid_request’, ‘not_owner’, ‘not_admin’, ‘not_account_admin’, ‘invalid_name’, ‘duplicate_name’, ‘api_key_not_found’]
- class smarter.apps.llmclient.views.deployment_contract.ErrorResponse(**data)[source]
Bases:
LLMClientDeploymentModelWhy an api key action failed: its code, and an English message for logs and developers.
- code: Literal['not_found', 'invalid_request', 'not_owner', 'not_admin', 'not_account_admin', 'invalid_name', 'duplicate_name', 'api_key_not_found']
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.LLMClientDeploymentModel(**data)[source]
Bases:
BaseModelThe base class of the contract’s models: camelCase JSON, and no fields that a model doesn’t define.
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class smarter.apps.llmclient.views.deployment_contract.LLMClientDeploymentPage(**data)[source]
Bases:
LLMClientDeploymentModelEverything that the page shows.
- api_keys: DeploymentApiKeys | None
- links: DeploymentLinks
- llmclient: DeploymentLLMClient
- model_config = {'alias_generator': <function to_camel>, 'extra': 'forbid', 'json_schema_serialization_defaults_required': True, 'serialize_by_alias': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- ownership: DeploymentOwnership | None
- public()[source]
The page at the deployed LLMClient’s url, which anyone can open: without its owner or api keys.
- Returns:
A copy of the page.
- Return type:
- snippets: DeploymentSnippets
- smarter.apps.llmclient.views.deployment_contract.PageMode
at the deployed LLMClient’s url, or in the workbench’s “Deployment” tab.
- Type:
Where the page is
alias of
Literal[‘public’, ‘workbench’]
- smarter.apps.llmclient.views.deployment_contract.REQUEST_MODELS: tuple[type[BaseModel], ...] = (<class 'smarter.apps.llmclient.views.deployment_contract.CreateApiKeyRequest'>, <class 'smarter.apps.llmclient.views.deployment_contract.AttachApiKeyRequest'>)
fields with defaults may be left out.
( <class 'smarter.apps.llmclient.views.deployment_contract.CreateApiKeyRequest'>, <class 'smarter.apps.llmclient.views.deployment_contract.AttachApiKeyRequest'>, )
- Type:
What the api accepts
- smarter.apps.llmclient.views.deployment_contract.RESPONSE_MODELS: tuple[type[BaseModel], ...] = (<class 'smarter.apps.llmclient.views.deployment_contract.LLMClientDeploymentPage'>, <class 'smarter.apps.llmclient.views.deployment_contract.ApiKeyActionResponse'>, <class 'smarter.apps.llmclient.views.deployment_contract.ErrorResponse'>)
every field, always.
( <class 'smarter.apps.llmclient.views.deployment_contract.LLMClientDeploymentPage'>, <class 'smarter.apps.llmclient.views.deployment_contract.ApiKeyActionResponse'>, <class 'smarter.apps.llmclient.views.deployment_contract.ErrorResponse'>, )
- Type:
What the views send
- smarter.apps.llmclient.views.deployment_contract.SCHEMA_PATH = PosixPath('/Users/mcdaniel/Desktop/gh/smarter-sh/smarter/smarter/smarter/apps/llmclient/views/llmclient-deployment.schema.json')
The committed JSON Schema of the contract.
- smarter.apps.llmclient.views.deployment_contract.contract_schema()[source]
The contract’s JSON Schema (draft 2020-12): one definition, in
$defs, per model.
- smarter.apps.llmclient.views.deployment_contract.contract_schema_json()[source]
The contract’s JSON Schema, as the text of
llmclient-deployment.schema.json.- Return type:
The app renders the page at a deployed LLMClient’s url, llmclient/endpoints.html, whose root element
and json_script these ids name. The “Deployment” tab of the Prompt Engineer’s Workbench renders the same
page, with the package’s component, in the @smarter/workbench app.
- smarter.apps.llmclient.templatetags.react_llmclient_deployment.DEPLOYMENT_DATA_ID = 'smarter-llmclient-deployment-data'
The id of the
json_scriptthat holds the page’s data, anLLMClientDeploymentPage.
- smarter.apps.llmclient.templatetags.react_llmclient_deployment.DEPLOYMENT_ROOT_ID = 'smarter-llmclient-deployment-root'
The id of the app’s root element.
- smarter.apps.llmclient.templatetags.react_llmclient_deployment.llmclient_deployment_react_assets()[source]
Load CSS and JS files for a React app entry point based on its manifest.json.
- Return type:
- smarter.apps.llmclient.templatetags.react_llmclient_deployment.templatetag_manager = <smarter.lib.django.templatetags.smarter_react_templatetag_manager.SmarterReactTemplateTagManager object>
Manages integration of Vite-built React assets into Django templates.
Expects to find a Vite-generated manifest.json in the file path static/react/@smarter/llmclient-deployment/.