Skip to main content

Writing your first LLM app

In this tutorial, we'll lead you through the process of creating your first Language Learning Model (LLM) application using Agenta. Our aim is to build an application capable of producing a compelling startup pitch based on the startup's name and core idea. By the end of the tutorial, we'll have our app set up locally, ready for iterative refinement in the playground. You'll have the ability to modify parameters, branch out new variants, and systematically assess different versions in Agenta.

Let's begin.

Installation

Run pip install agenta to install the Agenta CLI.

1. Project Initialization

Start by creating an empty project in an empty directory.

mkdir my-first-app; cd my-first-app
agenta init

Follow the prompts to initialize your project. Make sure to select start with an empty project when prompted.

Now create a virtual environment:

python3 -m venv env
source env/bin/activate

Finally let's create a requirements.txt and add within it our dependencies

langchain
agenta
python-dotenv
openai

Install the dependencies:

pip install -r requirements.txt

Now we're ready to start writing our app.

2. Write a Simple LLM App

Create a file called app.py - the main script that Agenta SDK expects. This simple script takes a startup name and idea, and generates a pitch using langchain:


from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

startup_name = "agenta"
startup_idea = "the open-source developer-first llmops platform"

default_prompt = """
please write a short linkedin message (2 SENTENCES MAX) to an investor pitching the following startup:
startup name: {startup_name}
startup idea: {startup_idea}"""

#template is a float, it is used to decide what sampling temperature to use. Default to 0.7
temperature = 0.5

llm = OpenAI(temperature=temperature)
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(startup_name=startup_name, startup_idea=startup_idea)
print(output)

3. Encapsulate Your Code in a Function

Wrap your code into a function named generate. This function will be the primary function Agenta calls, taking in strings as inputs and returning a string as an output:

from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate


default_prompt = """
please write a short linkedin message (2 SENTENCES MAX) to an investor pitching the following startup:
startup name: {startup_name}
startup idea: {startup_idea}"""


def generate(startup_name, startup_idea):
#template is a float, it is used to decide what sampling temperature to use. Default to 0.7
temperature = 0.5
llm = OpenAI(temperature=temperature)
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(startup_name=startup_name, startup_idea=startup_idea)
return output

4. Add the decorator

We'll now transform our plain Python function into an Agenta app. Use the Agenta decorator @post for this purpose. The decorator tells Agenta that this function is the main function in the app, and it specifies the inputs (and later parameters) that the app takes.

Note here that we made sure to add the type annotations to the function arguments. This is required for Agenta to be able to understand the inputs and outputs of the function.


from agenta import post
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
import os


default_prompt = """
please write a short linkedin message (2 SENTENCES MAX) to an investor pitching the following startup:
startup name: {startup_name}
startup idea: {startup_idea}"""


@post
def generate(startup_name: str, startup_idea: str) -> str:
#template is a float, it is used to decide what sampling temperature to use. Default to 0.7
temperature = 0.5
llm = OpenAI(temperature=temperature)
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(startup_name=startup_name, startup_idea=startup_idea)
return output

5. Parameter Addition

To iterate and fine-tune this app in the playground, we need to expose parameters. Accomplish this by adding additional arguments in the app function:

from agenta import post, TextParam, FloatParam
from agenta.types import MultipleChoiceParam
from dotenv import load_dotenv
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate


default_prompt = """
please write a short linkedin message (2 SENTENCES MAX) to an investor pitching the following startup:
startup name: {startup_name}
startup idea: {startup_idea}"""


@post
def generate(
startup_name: str,
startup_idea: str,
prompt_template: TextParam = default_prompt,
temperature: FloatParam = 0.5,
model: MultipleChoiceParam = MultipleChoiceParam(
choices = ["text-davinci-003", "gpt-3.5-turbo", "gpt-4"]
)
) -> str:
llm = OpenAI(temperature=temperature)
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(startup_name=startup_name, startup_idea=startup_idea)
return output

In this example, startup_name and startup_idea are required inputs, while prompt, temperature and model are optional parameters with default values. The types TextParam, FloatParam and MultipleChoiceParam are used to indicate these are parameters rather than inputs, and they will be made available for tuning in the Agenta UI. The type MultipleChoiceParam will allow the user to select from multiple choices of models, by default the model to use is text-davinci-003 since a default model to use wasn't specified. To specify a default model, modify the parameter to this:

model: MultipleChoiceParam = MultipleChoiceParam(
"text-davinci-003",
["gpt-3.5-turbo", "gpt-4"]
)

This will result to having the app use the text-davinci-003 model.

6. Text Generation Function - call_llm

The provided code snippet below defines a function call_llm that uses the chosen language model to generate text output based on the provided parameters. The function takes inputs such as model, temperature, and prompt, along with additional keyword arguments (kwargs) required for text generation.

If the chosen model is "text-davinci-003", it uses the OpenAI class from the LangChain library to run an LLMChain with the given parameters, producing text output based on the input prompt and the provided keyword arguments.

If the model is either "gpt-3.5-turbo" or "gpt-4", it uses the ChatOpenAI class from the LangChain library to generate text output in a conversational format. The function prepares a list of messages with a single HumanMessage containing the content from the input prompt formatted with the provided keyword arguments. The generated text output is then returned.


def call_llm(model, temperature, prompt, **kwargs):
if model == "text-davinci-003":
llm = OpenAI(model=model, temperature=temperature)
chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(**kwargs)
elif model in ["gpt-3.5-turbo", "gpt-4"]:
chat = ChatOpenAI(model=model,
temperature=temperature)
messages = [
HumanMessage(content=prompt.format(**kwargs))
]
output = chat(messages).content
return output

This function facilitates the text generation process using different language models, providing the necessary flexibility for users to choose the appropriate model for their specific needs.

7. Integration of the call_llm function

The call_llm function is seamlessly integrated into the generate app to provide text generation capabilities based on user inputs and selected language models.

# other imports here
from agenta.types import MultipleChoiceParam
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage


def call_llm(model, temperature, prompt, **kwargs):
if model == "text-davinci-003":
llm = OpenAI(model=model, temperature=temperature)
chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(**kwargs)
elif model in ["gpt-3.5-turbo", "gpt-4"]:
chat = ChatOpenAI(model=model,
temperature=temperature)
message = HumanMessage(content=prompt.format(**kwargs))
output = chat(message).content
return output


@post
def generate(
startup_name: str,
startup_idea: str,
prompt_template: TextParam = default_prompt,
temperature: FloatParam = 0.5,
model: MultipleChoiceParam = MultipleChoiceParam(
choices = ["text-davinci-003", "gpt-3.5-turbo", "gpt-4"]
)
) -> str:
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

output = call_llm(
model=model, temperature=temperature, prompt=prompt,
startup_name=startup_name, startup_idea=startup_idea
)
return output

The generate app function accepts parameters such as startup_name, startup_idea, prompt_template, temperature, and model. It initializes a PromptTemplate with startup_name and startup_idea as input variables, along with the provided prompt_template. The call_llm function is then invoked with the specified model, temperature, prompt, and keyword arguments (startup_name and startup_idea).

The function utilizes the chosen language model to generate a LinkedIn message based on the prompt_template and input data (startup_name and startup_idea). The generated LinkedIn message is returned as the output of the generate app.

NOTE: The call_llm function significantly enhances the capabilities of the generate app, providing a flexible and powerful mechanism for text generation with different language models. Its seamless integration within the app allows users to easily fine-tune text generation based on their specific requirements and chosen models.

8. API Key Integration

To use openai or other APIs, you'll need appropriate keys. Create an empty .env file and add your keys to it. Then, read the keys from the environment in your code:

OPENAI_API_KEY=sk-xxxxxxx

We just need to read the keys from the environement and use them in our code.

from agenta import post, TextParam, FloatParam
from dotenv import load_dotenv
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from agenta.types import MultipleChoiceParam
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage


default_prompt = """
please write a short linkedin message (2 SENTENCES MAX) to an investor pitching the following startup:
startup name: {startup_name}
startup idea: {startup_idea}"""


def call_llm(model, temperature, prompt, **kwargs):
if model == "text-davinci-003":
llm = OpenAI(model=model, temperature=temperature)
chain = LLMChain(llm=llm, prompt=prompt)
output = chain.run(**kwargs)
elif model in ["gpt-3.5-turbo", "gpt-4"]:
chat = ChatOpenAI(model=model,
temperature=temperature)
message = HumanMessage(content=prompt.format(**kwargs))
output = chat(message).content
return output


@post
def generate(
startup_name: str,
startup_idea: str,
prompt_template: TextParam = default_prompt,
temperature: FloatParam = 0.5,
model: MultipleChoiceParam = MultipleChoiceParam(
choices = ["text-davinci-003", "gpt-3.5-turbo", "gpt-4"]
)
) -> str:
load_dotenv()
prompt = PromptTemplate(
input_variables=["startup_name", "startup_idea"],
template=prompt_template)

output = call_llm(
model=model, temperature=temperature, prompt=prompt,
startup_name=startup_name, startup_idea=startup_idea
)
return output

9. Run the code in CLI

The @post decorator allows the function to run in the Command Line Interface (CLI). Execute it using the command:

python app.py agenta "the open-source developer-first llmops platform"

Hi there, I'm excited to tell you about Agenta, the open source Dev First LLMOPS Platform. It's a revolutionary way to simplify and streamline the development process, and I'm confident it will be a game changer in the industry. Let's chat soon!

If no default value was provided in the model (MultiChoiceParam) parameter, the code would still work because the app is using the first model in the list of models provided. If you would like to specify which model to use, kindly provide the name of the model and run the command again:

python app agenta "the open-source developer-first llmops platform" --model gpt-3.5-turbo

Hi [Investor's Name], I wanted to introduce you to Agenta, an open-source developer-first llmops platform. We believe it has the potential to revolutionize the way developers manage their llmops processes. Would love to discuss further if you're interested.

10. Deploying to Agenta

Our app is still local. To make it available in the playground, add it to Agenta by running:

agenta variant serve --file_name app.py

This commands build a docker image of your app and push it to the Agenta registry. It also creates a new variant for your app in the Agenta UI. You can now go to the Agenta UI and start playing with your app.

11. Iterative Improvement in the Playground

Your app is now accessible in the Agenta UI at http://localhost. Interact with your app, experiment with different parameters, and fine-tune your app's behavior to achieve desired results.

Conclusion

Congratulations! You've crafted and deployed your first LLM app with Agenta. You can now experiment and refine it further in the playground.