general.mdc•5.17 kB
---
description:
globs:
alwaysApply: true
---
# General Client Design Guidelines
## Dependancies
The client should be as light-weight as possible as it is meant to be integrated into applications directly with no impact on the runtime. This means it should never depend on the core `phoenix` package and should only depend on things under the `phoenix.client` sub-module. The client must never depend on modules that are related to a server such as `starlette`, `sqlalchamy`, `pg` and so on. For libraries like `pandas`, implement lazy importing (importing within the specific function that requires it) rather than importing at the top-level.
## Syntax
All methods that interact with the server shoud be namespaced via `projects`, `prompts` and so on.
All arguments to the methods MUST use `kwargs` so as to make the signature as self evident as possible.
Do not do:
```python
client.prompts.get("prompt_version_id")
```
Prefer:
```python
client.prompts.get(prompt_version_id="prompt_version_id")
```
Methods should be prefixed with an action:
- `get` - gets the entity. Correlates to HTTP `GET` a specific entity. E.x. `/projects/1`
- `create` - makes a new entity. Correlates to HTTP `POST`
- `list` - get a paginated list of an entity. E.g. `GET` a list `/projects`
- `add` - attach an entity to another. E.x. `add_annotation` would be used to attach an annotation to a `span` or `trace`
- `delete` - permanently delete an entity
In addition things can be sent to the platform in bulk.
- `log` - associates a list of entities to something. E.x. `log_annotations` will send a list of annotations to a particular target such as a `span` or a `project`
## Pandas
The client should make affordances to push and pull data from the phoenix server via `pandas` DataFrames. For all bulk operations, the method should be postfixed with `dataframe` so as to make it clear that the input and output is a dataframe.
For example:
```python
client.log_annotations_dataframe(dataframe=dataframe)
df = client.get_spans_dataframe(project_name="default")
```
## Transport
For all IO to the phoenix server, JSON or JSONL over HTTP should be preferred. This is so that clients in other languages can be created (E.g. `TypeScript`), LLMs can easily interpret the data (fine-tunining), and so that non homogenious data can be sent over the wire (e.x. `metatadata` dictionaries).
In the case that a different format is needed (e.x. `DataFrame` or `CSV`), the client should perform the translation (e.g. be a fat client) unless there is a more specific endpoint that supports that MIME type.
For example:
```python
client.log_annotations(annotations=annotations)
# Syntactic sugar to log annotations as a dataframe
# Annotations are still sent over the wire as JSON
client.log_annotations_dataframe(dataframe=df)
```
## Types
Types are compiled via OpenAPI. However the user should never be exposed to these types. When a generated type should be used, re-export it form the resource or module.
Do not force the use of generated types:
```python
from phoenix.client.__generated__ import v1
span = v1.Span(...)
```
Prefer:
```python
from phoenix.client.resources.spans import Span
span = Span(...)
```
## Docstrings
All doctrings should be in the Google Style for Python docstrings.
Example:
```python
def module_level_function(param1, param2=None, *args, **kwargs):
"""This is an example of a module level function.
Function parameters should be documented in the ``Args`` section. The name
of each parameter is required. The type and description of each parameter
is optional, but should be included if not obvious.
If \*args or \*\*kwargs are accepted,
they should be listed as ``*args`` and ``**kwargs``.
The format for a parameter is::
name (type): description
The description may span multiple lines. Following
lines should be indented. The "(type)" is optional.
Multiple paragraphs are supported in parameter
descriptions.
Args:
param1 (int): The first parameter.
param2 (:obj:`str`, optional): The second parameter. Defaults to None.
Second line of description should be indented.
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
Returns:
bool: True if successful, False otherwise.
The return type is optional and may be specified at the beginning of
the ``Returns`` section followed by a colon.
The ``Returns`` section may span multiple lines and paragraphs.
Following lines should be indented to match the first line.
The ``Returns`` section supports any reStructuredText formatting,
including literal blocks::
{
'param1': param1,
'param2': param2
}
Raises:
AttributeError: The ``Raises`` section is a list of all exceptions
that are relevant to the interface.
ValueError: If `param2` is equal to `param1`.
"""
if param1 == param2:
raise ValueError('param1 may not be equal to param2')
return True
```