Week of November 11th
Image by author.

Week of November 11th

TL;DR:


Hamilton Release Highlights:

Hamilton Framework == 1.83.1

Minor improvements:

  1. Added async support for the @pipe family of decorators. This means that you can now use this with async functions! Thanks to Jernej Frank for the contribution!
  2. Caching display flag when using Jupyter Notebooks. You can now add --display-cache as a flag to the jupyter notebook cell magic, and the visualization will display what was used in the cache for the execution. See this PR for more, thanks Thierry Jean .

?? Fixes:


Burr Release Highlights

Burr == 0.33.0

Framework level Parallelism

Super excited to ship this highly requested feature. This is to reduce the boilerplate of what you could already do with Burr.

Why might you want this? Well people want fast experiences. Parallelization is one way to do that. For example, if you're doing medical diagnosis and want to try 10 different hypotheses in parallel on the same context (i.e. patient info), or you have a list of 10 items in context you want to run the same action over in parallel (e.g. web scraping), then we've just made doing that much simpler.

How does it work? Well if you're familiar with the "map-reduce" pattern, then what we shipped will look (see below) and sound familiar:

Map Reduce like pattern that Burr now natively supports


To use this, you need to create a class, that enables you to do one of three things:

  1. Map over state
  2. Map over actions
  3. Map over both state & actions

Actions here can be a single "Burr action", or itself a whole "Burr subgraph". I'll skip the latter and use the former to explain mapping over actions and over state.

Map over State

To map over state you need to:

  1. Define the Burr action, e.g.

from burr.core import action, state
from burr.core.parallelism import MapStates, 
from typing import Callable, Generator, List

@action(reads=["prompt"], writes=["llm_output"])
def query_llm(state: State) -> State:
    return state.update(llm_output=_query_my_llm(prompt=state["prompt"]))        

You then need to define a "wrapper" class that will take the above action and map it over states and reduce the result back to state:

class TestMultiplePromptsAction(MapStates):

    def action(self) -> Action | Callable | RunnableGraph:
        # make sure to add a name to the action
        # This is not necessary for subgraphs, as actions will already have names
        return query_llm.with_name("query_llm")

    def states(self, state: State) -> Generator[State, None, None]:
        # You could easily have a list_prompts upstream action that writes to "prompts" in state
        # And loop through those
        # This hardcodes for simplicity
        for prompt in [
            "What is the meaning of life?",
            "What is the airspeed velocity of an unladen swallow?",
            "What is the best way to cook a steak?",
        ]:
            yield state.update(prompt=prompt)


    def reduce(self, states: Generator[State, None, None]) -> State:
        # This reduces the result of the map
        all_llm_outputs = []
        for state in states:
            all_llm_outputs.append(state["llm_output"])
        return state.update(all_llm_outputs=all_llm_outputs)

    def reads() -> List[str]:
        return ["prompts"]

    def writes() -> List[str]:
        return ["all_llm_outputs"]        

Then to build an application it would look something like:

app = (
    ApplicationBuilder()
    .with_action(
        prompt_generator=generate_prompts, # skipped
        multi_prompt_test=TestMultiplePrompts(), # you instantiate the class
    ).with_transitions(
        ("prompt_generator", "multi_prompt_test"),
    )
    .build()
)        

Map over Actions

For mapping over actions, the API is similar, we implement a different class and then return multiple actions:

from burr.core import action, state
from burr.core.parallelism import MapActions, RunnableGraph
from typing import Callable, Generator, List

@action(reads=["prompt", "model"], writes=["llm_output"])
def query_llm(state: State, model: str) -> State:
    # we parameterize model and create multiple actions below
    llm_output = _query_my_llm(prompt=state["prompt"], model=model)
    return state.update(llm_output=llm_output)        

We will use the above action to generate multiple of them. In this case they look similar, but they need not be and could be very different Burr actions. Below we show how one would generate multiple actions that would all then be passed the prompt state value in parallel, and the reduce together into a single output.

class TestMultipleModels(MapActions):
    # the actions method will actions to map over

    def actions(self, state: State) -> Generator[Action | Callable | RunnableGraph, None, None]:
        # Make sure to add a name to the action if you use bind() with a function,
        # note that these can be different actions, functions, etc...
        # in this case we're using `.bind()` to create multiple actions, but we can use some mix of
        # subgraphs, functions, action objects, etc...
        for action in [
            query_llm.bind(model="gpt-4").with_name("gpt_4_answer"),
            query_llm.bind(model="o1").with_name("o1_answer"),
            query_llm.bind(model="claude").with_name("claude_answer"),
        ]
            yield action

    def state(self, state: State) -> State:
        # we can set some input state if needed.
        return state

    def reduce(self, states: Generator[State, None, None]) -> State:
        # we reduce the results
        all_llm_outputs = []
        for state in states:
            all_llm_outputs.append(state["llm_output"])
        return state.update(all_llm_outputs=all_llm_outputs)

    def reads() -> List[str]:
        return ["prompt"] 

    def writes() -> List[str]:
        return ["all_llm_outputs"]        

This is just the initial rollout, there's a lot more that I didn't cover. See here for details. Otherwise a few things to expect next week and the week after:

  1. More UI updates.
  2. More executor support, e.g. Ray, Dask, etc.


Office Hours & Meetup

Hamilton Meet up: Our next meet-up will be December. Want to present? Reach out. Otherwise join/sign-up here.

Hamilton Office Hours: They happen most Tuesday 9:30am PT - 10:30am PT.

Join our slack for the link.

Burr Office Hours: They happen most Wednesdays 9:30am PT - 10:3am PT.

Join our discord for the weekly link.


Running a Maven course on Building GenAI Applications

I’m hosting a #free event with Hugo Bowne-Anderson on Maven about "Building #GenAI from First Principles".

This 30-min session is for #SoftwareEngineers and #DataScientists #MachineLearningEngineers who want to know:

#1 The first principles to know for building with GenAI.

#2 Techniques for wrangling non-determinism.

#3 Components / Processes you'll need to build out for a productive software development cycle (SDLC).

Join LIVE on Tuesday 11/19 4pm PT!

RSVP here ??:


Blog Post: Flashcard generator with Instructor + Burr

We're excited to post this example by Thierry Jean on using both the instructor and Burr libraries to create a small flashcard app. It transcribes youtube videos to create flashcards.


In the Wild:

Hamilton in a capstone RAG project

Hamilton was used as part of a RAG app for a capstone project by Eric Brichetto ! He wrote about it on LinkedIn. Hamilton was core to the scalable and modular architecture he built, and to learn more you can watch his video walkthrough explanation of it.

Burr: powering wingman SQL assistant

Salesteq Inc. continues to build more production use cases with Burr! We're excited to see where they take the platform!

Burr featured by Unwind AI

Super excited Burr was picked up by Unwind AI . They did an excellent job of putting together a video and explaining in plain terms the value and features that Burr provides:

Here's what makes it special:
→ Visual debugging in real-time
→ Built for production from day one
→ Works with any Python code, not just LLMs
→ Simple building blocks, powerful results
→ Complete toolkit for deployment
The magic? State machines.
Instead of adding endless print statements or digging through logs, Burr shows you exactly how your agent thinks through an interactive graph.
Want to know why your chatbot gave that response? Just click on any node to see the exact state and data at that moment.
Need to add safety checks? Draw the logic flow and Burr handles the rest.
Building features like:
? Conversation history
? Complex decision trees
? Streaming responses
? State persistence
? Safety guardrails
All become visual building blocks you can see and debug.

To see the video, check out the post:


要查看或添加评论,请登录