Overview

Opper is a Unified API that makes it easy to build AI code that is model independent, structured and performant. SDKs are available for Python and Typescript, and they provide a toolkit to perform various common LLM operations.

About this Guide

This guide is optimized for advocating for best practices of building with Opper. It is a good reference for developers, as well as for prompting code editors like Cursor. For a more simple get started, you might want to check out our Get Started guide.

Key concepts

Here are the key concepts of Opper:

  • A call is a primitive but powerful way of interacting with a generative model. It is a structured definition of a task, with clear input and output schemas where schema annotations are used for prompting. Each call has a "name", which allows it to be managed as a function.
  • A model is an LLM. A full list of supported LLMs are available at https://docs.opper.ai/capabilities/models.
  • A span is a log of a call. But unlike ordinary logs, a span is built to be able to hold metrics, evaluations and be tied together with other spans to form what is called a trace. A trace is a chain of spans.
  • A metric is a data point that you can attach to a span. It is a flexible way to provide feedback on the success of a call from code. It can be used for storing results end user feedback such as thumbs up or down, performance timers or the result of small checks.
  • A dataset is a collection of example outputs that can act as ground truth for success of a task. Dataset entries can be used for testing changes to prompts, alternative models and be used as examples for the model.
  • A index is database equipped with semantic similiarty functionallity. You can use it to index knowledge and retrieve the semantically relevant parts of it. Good for memory or knowledge applications.

Best practices

Here are the best practices for building reliable AI implementations with these primitives:

  • Break up tasks in to steps and implement calls for each step. This helps build an easy to maintain and easy to optimize pipeline.
  • Always define clear schemas for the output, with descriptions for fields to improve the understanding for the model
  • Define a schema for the input with descriptions for fields to improve the understanding for the model, and leave out explanation of this in instructions.
  • Sparingly use natural language instructions, use schemas and field descriptions to define the instructions as much as possible.
  • Always start a trace to have subsequent calls and indexing operations as children of the parent span. This will make it easier to understand the flow of the application in the Opper UI.
  • Leave out the model unless you have a specific reason to do so, model optimization is preferably a later optimization.
  • Perform small and simple evaluations of outputs of calls in code to verify quality or assumptions, to be able to spot issues early
  • Include a field thoughts as the first item in the output schema to improve quality of the response.

Examples

Get started

We recommend storing your API key for Opper as an environment variable. The SDKs will automatically try to load the key from the environment variable OPPER_API_KEY. You can generate API keys at https://platform.opper.ai

Making calls to models with schemas

In this example we complete a task to extract structured room information from a text. Note how we define input and output schemas for the task and use field descriptions as the primary means to prompt the model.

Performing tracing and logging

In this example, we implement tracing of a translation task where the an article will be translate to 3 languages by 3 calls. Note how a trace is started as a context manager which makes the individual translations fold into this parent span.

Performing evals with metrics

In this example, we evaluate accuracy of a task and save a metric. Note how this test is fast and small and tests the main instruction. Metric will be filterable in the UI.

Performing knowledge indexing and retrieval

Here is an example of how to index and retrieve data with the Opper SDK. Note how we pick a descriptive index name, and how we add metadata to documents to be able to use that information when composing responses.