Build a Simple LLM Application with LCEL
In this quickstart we'll show you how to build a simple LLM application with LangChain. This application will translate text from English into another language. This is a relatively simple LLM application - it's just a single LLM call plus some prompting. Still, this is a great way to get started with LangChain - a lot of features can be built with just some prompting and an LLM call!
After reading this tutorial, you'll have a high level overview of:
-
Using language models
-
Using PromptTemplates
-
Debugging and tracing your application using LangSmith
-
Deploying your application with LangGraph Platform
Let's dive in!
Setupβ
Jupyter Notebookβ
This and other tutorials are perhaps most conveniently run in a Jupyter notebooks. Going through guides in an interactive environment is a great way to better understand them. See here for instructions on how to install.
Installationβ
To install LangChain run:
- Pip
- Conda
pip install langchain
conda install langchain -c conda-forge
For more details, see our Installation guide.
LangSmithβ
Many of the applications you build with LangChain will contain multiple steps with multiple invocations of LLM calls. As these applications get more and more complex, it becomes crucial to be able to inspect what exactly is going on inside your chain or agent. The best way to do this is with LangSmith.
After you sign up at the link above, make sure to set your environment variables to start logging traces:
export LANGCHAIN_TRACING_V2="true"
export LANGCHAIN_API_KEY="..."
Or, if in a notebook, you can set them with:
import getpass
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
Using Language Modelsβ
First up, let's learn how to use a language model by itself. LangChain supports many different language models that you can use interchangeably. For details on getting started with a specific model, refer to supported integrations.
- OpenAI
- Anthropic
- Azure
- Cohere
- NVIDIA
- FireworksAI
- Groq
- MistralAI
- TogetherAI
- AWS
pip install -qU langchain-openai
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
model = ChatOpenAI(model="gpt-4o-mini")
pip install -qU langchain-anthropic
import getpass
import os
os.environ["ANTHROPIC_API_KEY"] = getpass.getpass()
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-3-5-sonnet-20240620")
pip install -qU langchain-openai
import getpass
import os
os.environ["AZURE_OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import AzureChatOpenAI
model = AzureChatOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
azure_deployment=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"],
)
pip install -qU langchain-google-vertexai
import getpass
import os
os.environ["GOOGLE_API_KEY"] = getpass.getpass()
from langchain_google_vertexai import ChatVertexAI
model = ChatVertexAI(model="gemini-1.5-flash")
pip install -qU langchain-cohere
import getpass
import os
os.environ["COHERE_API_KEY"] = getpass.getpass()
from langchain_cohere import ChatCohere
model = ChatCohere(model="command-r-plus")
pip install -qU langchain-nvidia-ai-endpoints
import getpass
import os
os.environ["NVIDIA_API_KEY"] = getpass.getpass()
from langchain_nvidia_ai_endpoints import ChatNVIDIA
model = ChatNVIDIA(model="meta/llama3-70b-instruct")
pip install -qU langchain-fireworks
import getpass
import os
os.environ["FIREWORKS_API_KEY"] = getpass.getpass()
from langchain_fireworks import ChatFireworks
model = ChatFireworks(model="accounts/fireworks/models/llama-v3p1-70b-instruct")
pip install -qU langchain-groq
import getpass
import os
os.environ["GROQ_API_KEY"] = getpass.getpass()
from langchain_groq import ChatGroq
model = ChatGroq(model="llama3-8b-8192")
pip install -qU langchain-mistralai
import getpass
import os
os.environ["MISTRAL_API_KEY"] = getpass.getpass()
from langchain_mistralai import ChatMistralAI
model = ChatMistralAI(model="mistral-large-latest")
pip install -qU langchain-openai
import getpass
import os
os.environ["TOGETHER_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
model = ChatOpenAI(
base_url="https://api.together.xyz/v1",
api_key=os.environ["TOGETHER_API_KEY"],
model="mistralai/Mixtral-8x7B-Instruct-v0.1",
)
pip install -qU langchain-aws
# Ensure your AWS credentials are configured
from langchain_aws import ChatBedrock
model = ChatBedrock(model_id="anthropic.claude-3-5-sonnet-20240620-v1:0")
Let's first use the model directly. ChatModels are instances of LangChain Runnables, which means they expose a standard interface for interacting with them. To simply call the model, we can pass in a list of messages to the .invoke
method.
from langchain_core.messages import HumanMessage, SystemMessage
messages = [
SystemMessage(content="Translate the following from English into Italian"),
HumanMessage(content="hi!"),
]
model.invoke(messages)
AIMessage(content='Ciao!', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 3, 'prompt_tokens': 20, 'total_tokens': 23, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_9ee9e968ea', 'finish_reason': 'stop', 'logprobs': None}, id='run-ad371806-6082-45c3-b6fa-e44622848ab2-0', usage_metadata={'input_tokens': 20, 'output_tokens': 3, 'total_tokens': 23, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})
If we've enabled LangSmith, we can see that this run is logged to LangSmith, and can see the LangSmith trace. The LangSmith trace reports token usage information, latency, standard model parameters (such as temperature), and other information.
Note that ChatModels receive message objects as input and generate message objects as output. In addition to text content, message objects convey conversational roles and hold important data, such as tool calls and token usage counts.
Prompt Templatesβ
Right now we are passing a list of messages directly into the language model. Where does this list of messages come from? Usually, it is constructed from a combination of user input and application logic. This application logic usually takes the raw user input and transforms it into a list of messages ready to pass to the language model. Common transformations include adding a system message or formatting a template with the user input.
Prompt templates are a concept in LangChain designed to assist with this transformation. They take in raw user input and return data (a prompt) that is ready to pass into a language model.
Let's create a PromptTemplate
here. It will take in two user variables:
language
: The language to translate text intotext
: The text to translate
from langchain_core.prompts import ChatPromptTemplate
system_template = "Translate the following from English into {language}"
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)
Note that ChatPromptTemplate
supports multiple message roles in a single template. We format the language
parameter into the system message, and the user text
into a user message.
The input to this prompt template is a dictionary. We can play around with this prompt template by itself to see what it does by itself
result = prompt_template.invoke({"language": "Italian", "text": "hi!"})
result
ChatPromptValue(messages=[SystemMessage(content='Translate the following from English into Italian', additional_kwargs={}, response_metadata={}), HumanMessage(content='hi!', additional_kwargs={}, response_metadata={})])
We can see that it returns a ChatPromptValue
that consists of two messages. If we want to access the messages directly we do:
result.to_messages()
[SystemMessage(content='Translate the following from English into Italian', additional_kwargs={}, response_metadata={}),
HumanMessage(content='hi!', additional_kwargs={}, response_metadata={})]
Chaining together components with LCELβ
We can now combine this with the model from above using the pipe (|
) operator:
chain = prompt_template | model
response = chain.invoke({"language": "Italian", "text": "hi!"})
print(response.content)
Ciao!
This is a simple example of using LangChain Expression Language (LCEL) to chain together LangChain modules. There are several benefits to this approach, including optimized streaming and tracing support.
If we take a look at the LangSmith trace, we can see both components show up.
Serving with LangGraph Platformβ
Now that we've built an application, we need to serve it. That's where LangGraph Platform comes in. LangGraph Platform is designed to make deploying LLM applications seamless and production-ready. You do not need to use LangGraph Platform to use LangChain, but in this guide we'll show how you can use it to deploy your application. We won't go into detail on LangGraph or LangGraph Platform concepts here; consult its documentation for detail on its features and in-depth guides.
While the first part of this guide was intended to be run in a Jupyter Notebook or script, we will now move out of that. We will use command-line tools to create a set of files and deploy them locally.
-
Create application directory and files
We will use the langgraph-cli to initialize a template application. This will give us a working scaffold of an application that we can customize. You can install
langgraph-cli
via Homebrew (on macOS) or pip. See its documentation for detail.pip install "langgraph-cli>=0.1.53"
Let's create a folder to house our application:
mkdir my-app && cd my-app
We can now use the command
langgraph new
to download a template application. This command asks you to specify:- The path -- we can select the current directory with
.
- The template -- enter
1
to select the "New LangGraph Project" template - Python or JS -- enter
1
to select Python
With that, we've created a functional, minimal application that we can customize. There are four files that we will need to change to implement our translator bot.
- The path -- we can select the current directory with
-
Define your applicaton logic
We will need to update the application to run our translator bot. This will touch two files. First, we update the application's state to include fields for the language, input text, and response:
In
src/agent/state.py
:@dataclass
class State:
"""Defines the input state for the agent, representing a narrower interface to the outside world.
This class is used to define the initial state and structure of incoming data.
See: https://langchain-ai.github.io/langgraph/concepts/low_level/#state
for more information.
"""
text: str
language: str
response: str = ""Next, we will update the application logic to run our translator bot.
In
src/agent/graph.py
:from typing import Any, Dict
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableConfig
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph
from agent.configuration import Configuration
from agent.state import State
model = ChatOpenAI(model="gpt-4o")
system_template = "Translate the following from English into {language}"
prompt_template = ChatPromptTemplate.from_messages(
[("system", system_template), ("user", "{text}")]
)
chain = prompt_template | model
async def my_node(state: State, config: RunnableConfig) -> Dict[str, Any]:
"""Each node does work."""
response = chain.invoke({"language": state.language, "text": state.text})
return {"response": response.content}
# Define a new graph
workflow = StateGraph(State, config_schema=Configuration)
# Add the node to the graph
workflow.add_node("my_node", my_node)
# Set the entrypoint as `call_model`
workflow.add_edge("__start__", "my_node")
# Compile the workflow into an executable graph
graph = workflow.compile()
graph.name = "New Graph" # This defines the custom name in LangSmith -
Specify environment variables
We should add our OpenAI API keys and other necessary settings or secrets to a
.env
file. Populate the API key in the.env.example
file and re-name it to.env
. -
Specify dependencies
Finally, we need to add
langchain-openai
or any other required packages topyproject.toml
:dependencies = [
"langgraph>=0.2.6",
"python-dotenv>=1.0.1",
"langchain-openai>=0.2",
] -
Deploy
We can again use
langgraph-cli
to deploy locally:langgraph up
This will build the application with Docker and run it behind
localhost
on your machine. -
Test
We can use the
ok
endpoint to test that the application is ready:curl --request GET --url http://localhost:8123/ok
If you receive
{"ok":true}
, the application is ready for use.
LangGraph Platform supports several means of interacting with the server. Below we will demonstrate the SDK.
Clientβ
Install with:
pip install --upgrade langgraph-sdk
Assuming our deployment is at http://localhost:8123
, below we initialize a client and identify the corresponding Assistant. An Assistant is an instance of our application.
from langgraph_sdk import get_client
client = get_client(url="http://localhost:8123")
# get default assistant
assistants = await client.assistants.search(metadata={"created_by": "system"})
assistant = assistants[0]
We can now query the Assistant in a (stateless) run:
input = {"language": "Italian", "text": "hi!"}
async for chunk in client.runs.stream(
None, # stateless run
assistant["assistant_id"],
input=input,
stream_mode="updates",
):
if chunk.data:
print(chunk.data)
{'run_id': '1efa1faa-23ce-69cb-858a-97f292fc5561', 'attempt': 1}
{'my_node': {'response': 'Ciao!'}}
Studio UIβ
Every LangGraph Platform comes with a simple built-in UI for configuring and invoking the application with streaming output and visibility into intermediate steps.
Head to https://smith.langchain.com/studio/?baseUrl=http://127.0.0.1:8123 to try it out! Pass in the same inputs as before - {"language": "italian", "text": "hi"}
- and it should respond same as before.
Conclusionβ
That's it! In this tutorial you've learned how to create your first simple LLM application. You've learned how to work with language models, how to how to create a prompt template, how to get great observability into chains you create with LangSmith, and how to deploy them with LangGraph Platform.
This just scratches the surface of what you will want to learn to become a proficient AI Engineer. Luckily - we've got a lot of other resources!
For further reading on the core concepts of LangChain, we've got detailed Conceptual Guides.
If you have more specific questions on these concepts, check out the following sections of the how-to guides:
As well as the docs for LangSmith and LangGraph Platform.