> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lytix.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Python Quickstart

> Start collecting data from your Python project

<Info>
  **Prerequisite** Please see [here](/api-key-setup) to get and set your API Key environment variable.
</Info>

Install the Lytix pip package

```bash
pip3 install lytix-py
```

## Error Capturing

#### Error Class

You can now just replace all your `raise Exception` calls with `raise LError`. For example:

```py
from lytix_py import LError
from lytix_py.LLogger.LLogger import LLogger

async def backgroundProcess():
    logger = LLogger("background-logger", {"userId": '124'})
    logger.info("Some process is starting")
    raise LError("An unexpected error")

async def main(): 
    await backgroundProcess()


if __name__ == "__main__":
    logger  = LLogger("main")
    logger.runInAsyncContext(main)
```

The error, along with the last 20 log lines will automatically get pushed to the Lytix platform [here](https://lab.lytix.co/home/errors)

![title](https://mintlify.s3-us-west-1.amazonaws.com/lytix/images/node-quickstart/LErrorExample.png)

#### Error Increment

You can also send an error along with related logs without throwing an error by using the `increment` method.

```py
from lytix_py.LError import LErrorIncrement
from lytix_py.LLogger.LLogger import LLogger

async def backgroundProcess():
    logger = LLogger("background-logger", {"userId": '124'})
    logger.info("Some context on the user here")
    try:
        raise Exception("LIncrement error happened")
    except Exception as e:
        logger.error("LIncrement error happened")
        LErrorIncrement("Some error")
                        
async def main(): 
    logger = LLogger("main-logger")
    logger.info("Starting in our main LIncrement process")
    await backgroundProcess()


if __name__ == "__main__":
    logger  = LLogger("main")
    logger.runInAsyncContext(main)
```

#### Fast API Integration

Lytix also supports capturing errors in FastAPI. To get started first hook up our Lytix middleware:

```py
from lytix_py.FastAPIMiddleware.LytixMiddleware import LytixMiddleware
from fastapi import FastAPI

...
app = FastAPI()

app.add_middleware(LytixMiddleware)
...
```

Now you can throw errors in your FastAPI routes or subcalls as follows:

```py

# main.py
@app.get("/")
async def read_root():
    logger = LLogger("read-root")
    logger.info('In the main view here...')
    await backgroundFastAPIProcess()
    return {"Hello": "World"}

# backgroundProcess.py
async def backgroundFastAPIProcess(): 
    logger = LLogger("background-fast-api-process")
    logger.info("In the background here")

    """
    All the logs associated with this request will get sent to lytix
    """
    raise LError("Some error")
```

#### Examples

To see all examples please check the Github repo [here](https://github.com/Lytix-Labs/lytix-py/tree/master/example)

## LLM Model Input Output Collection

Lytix supports automatically collecting the input and output of LLM models. To do this you can use the following

```py
from lytix_py import MetricCollector


# Note the metricMetadata is optional
MetricCollector.captureModelIO(
  modelName="testModelName",
  modelInput="Whats the capital of France?",
  modelOutput="Paris is the capital of France", 
  metricMetadata={"env": "dev"}
)
```

Lytix will automatically process the input and output of the LLM model and push the metrics to the Lytix platform. You can see your model metrics in the Lytix platform [here](https://lytix.co/home/llm/).

### LLM Model Trace Collection

Lytix also supports capturing trace information (e.g. duration) for the LLM model. To do this you can use the following

```py
from lytix_py import MetricCollector

userInput = "Whats the capital of France?"

"""
This callback is expecting the model output to be returned
"""
async def callback(*args): 
  ...
  return "Paris is the capital of france"

response = await MetricCollector.captureModelTrace(
  modelName="testModelName", 
  modelInput=userInput, 
  callback=callback
)
```

You'll now see the model duration trace in the Lytix platform [here](https://lab.lytix.co/home/).

![title](https://mintlify.s3-us-west-1.amazonaws.com/lytix/images/node-quickstart/llm-trace.png)

### LLM Model Logs Collection

Similar to traces, we can also capture logs when a model is called. This will auto push the logs to the Lytix platform and associated with this trace

```py
from lytix_py import MetricCollector

userInput = "Whats the capital of France?"

"""
This callback is expecting the model output to be returned
"""
async def callback(logger): 
  ...
  logger.info("Inside the callback")
  return "Paris is the capital of france"

response = await MetricCollector.captureModelTrace(
  modelName="testModelName", 
  modelInput=userInput, 
  callback=callback
)
```

<Frame type="glass" caption="Model IO event with associated logs">
  <img width={500} src="https://mintlify.s3-us-west-1.amazonaws.com/lytix/images/python-quickstart/captureModelLogsExample.png" alt="captureModelLogsExample" />
</Frame>

## Manual Metric Collection

You always have the option to manually push metrics to the Lytix platform with custom names and metadata.

The following example pushes a metric to the Lytix platform with the name `testMetic` and the value `1` along with the `env: prod` metadata.

```python
from lytix_py import MetricCollector

MetricCollector.increment("testMetic", 1, {"env": "prod"})
```

You then have access to that on the Lytix platform and can filter on any of the metadata passed.

![title](https://mintlify.s3-us-west-1.amazonaws.com/lytix/images/node-quickstart/testMetricExample.png)
