Lattice LLM
A "lightweight" Python library for building LLM-powered agents as executable Graphs. A core goals is to provide a good developer UX.
Key Features
-
Simple abstractions. Lattice aims to offer a small set of easy to use abstractions: Graphs, Nodes and Edges.
-
Graphs are used to orchestrate steps in an LLM-agent's workflow. A
Graphexecutes in breadth-first fashion and has access to caller-providedContext(e.g. an AWS Bedrock client, the current user's id etc) andState(e.g. persisted chat history). -
Nodes are simply Python functions of the form
(context: Context, state: State) -> State. They're used to make the agent do stuff. Nodes are intended to be "pure" functions that take the currentContext+Stateas input and return a copy of the updatedState. -
Edges: Connect nodes together and provide control flow. They come in two flavors:
- A tuple of the form
(Node, Node), for edges that should always be traversed. Or - A Python function of the form
(Context, State) -> Node, for dynamic routing.
- A tuple of the form
-
-
Control. Graphs are executed (by the caller) one layer of at a time. This makes it easy to support use-cases that require waiting on user input before executing the next layer of the
Graph(e.g. a chatbot running on a web-server). -
Easy to test and introspect. Execution can be started from any
Nodein theGraph. Each time aGraphlayer is executed, aGraphExecutionResultis returned, which contains the updatedState. This makes it easy toasserton the expectedStateafter anyNodeis executed in theGraph. -
Convenience. Lattice provides the following quality of life features "out of the box":
- Persistance Lattice includes a
StateStoreProtocol(interface) for persisting graphStateand aLocalStateStorethat provides an in-memory implementation. - AWS Bedrock integration. Support is provided via a
converseandconverse_with_structured_output(which returns structured output in the form of a user-provided Pydantic model) - Tools Lattice can automatically:
- Convert Python functions to the JSON schema format LLMs require for defining tools.
- Invoke tools (local Python functions) that an LLM requests to use in its responses.
- Persistance Lattice includes a
Installation
poetry add lattice_llm
Usage
from dataclasses import dataclass
from typing import Callable, Self
import boto3
from mypy_boto3_bedrock_runtime.type_defs import MessageUnionTypeDef as Message
from pydantic import BaseModel
from lattice_llm.bedrock import BedrockClient, ModelId, converse, converse_with_structured_output
from lattice_llm.bedrock.messages import text
from lattice_llm.graph import END, Graph, Node, run_chatbot_on_cli
from lattice_llm.state import LocalStateStore
@dataclass
class Context:
"""Context that a Graph can utilize as it executes. Context is not intended to be mutated"""
user_id: str
bedrock: BedrockClient
tools: list[Callable]
@dataclass
class State:
"""State that a Graph can update as it executes."""
messages: list[Message]
@classmethod
def merge(cls, a: Self, b: Self) -> Self:
return cls(messages=a.messages + b.messages)
class ConversationDetails(BaseModel):
should_continue: bool = True
"""True if the user wishes to keep conversing. False if the user has indicated a desire to end the conversation. If ambiguous, assume the user wants to continue the conversation."""
def welcome(context: Context, state: State) -> State:
"""A graph node that returns a fixed (canned) response."""
return State.merge(state, State(messages=[text("...", role="user"), text("Hello!", role="assistant")]))
def assistant(context: Context, state: State) -> State:
"""A graph node that returns a message from Claude 3.5 Sonnet via the boto3 Bedrock client"""
response = converse(
client=context.bedrock,
model_id=ModelId.CLAUDE_3_5,
messages=state.messages,
tools=context.tools,
prompt="You are a helpful assistant.",
)
message = response["output"]["message"]
return State.merge(state, State(messages=[message]))
def goodbye(context: Context, state: State) -> State:
"""A graph node that returns another fixed (canned) response to say goodbye to the user."""
return State.merge(state, State(messages=[text("Goodbye!", role="assistant")]))
def continue_or_end(context: Context, state: State) -> Node[Context, State]:
"""A conditional edge, extracts structured output from Claude, in the form of a ConversationDetails Pydantic model and uses it to determine if we should loop back to the assistant node, or proceed to the goodbye node."""
response = converse_with_structured_output(
client=context.bedrock,
model_id=ModelId.CLAUDE_3_5,
messages=state.messages,
prompt="Extract the conversation details from historical messages.",
output_schema=ConversationDetails,
)
if response.should_continue:
return assistant
else:
return goodbye
def get_temperature(city: str) -> int:
"""
Returns the current temperature for a city.
:param city: The city to pull temperature information from
:return: The temperature in degrees fahrenheit for the specified city.
"""
return 50
context = Context(bedrock=boto3.client("bedrock-runtime"), user_id="user-1", tools=[get_temperature])
graph = Graph[Context, State](
nodes=[welcome, assistant, goodbye],
edges=[
(welcome, assistant),
(assistant, continue_or_end),
(goodbye, END),
],
)
store = LocalStateStore(lambda: State(messages=[]))
run_chatbot_on_cli(graph, context, store)
Metadata
Release files for lattice-llm 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| lattice_llm-0.1.2.tar.gz | 11.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lattice_llm-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.0 kB
Release files / lattice_llm-0.1.2.tar.gz
| Download URL | lattice_llm-0.1.2.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
036d0a909408702c3bed77e17ca1815e2f8c0a317626128973d556eb6ba00ab7
|
|
BLAKE2b-256 checksum How to use checksums |
40e4453807223a69697ebf0d6be82d83cfb16d9d5f13d7f43712cd758b15b3dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.5.1 CPython/3.9.13 Darwin/23.2.0
|
Release files / lattice_llm-0.1.2-py3-none-any.whl
| Download URL | lattice_llm-0.1.2-py3-none-any.whl |
|---|---|
| Size | 13.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
5beb0e6403df9665acc5a03dd21318a6c2d3687a06ac94c6cfa8b20b9d244b55
|
|
BLAKE2b-256 checksum How to use checksums |
aa9bf966b4ac1a8e1f0430daa259eb04f7a9d2696fb4bdad26d4d7cd65aa078c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/1.5.1 CPython/3.9.13 Darwin/23.2.0
|
Security for lattice-llm 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.