Skip to main content

Add your description here

Project description

lingo library logo

A minimal, async-native, and unopinionated toolkit for modern LLM applications.


PyPI - Version PyPi - Python Version Github - Open Issues PyPi - Downloads (Monthly) Github - Commits


lingo provides a powerful, two-layered API for building, testing, and deploying complex LLM workflows with precision and clarity.

The Philosophy: A Dual-Layer API

lingo is built on the idea that developers need both a high-level, declarative way to build workflows and a low-level, imperative way to control them.

  1. The High-Level Flow API: For most applications, you'll use the fluent, chainable Flow API. This allows you to define complex, reusable conversation logic with branching, tool use, and subroutines in a declarative, readable way.

  2. The Low-Level Context API: For full, fine-grained control, lingo provides the LLM and Context classes. This imperative layer is perfect for building custom chatbot loops or implementing your own conversational state logic from scratch.

Installation

pip install lingo

(Note: lingo is not yet on PyPI. This is the intended installation method.)

Quickstart: Building a Declarative Flow

Let's build a simple assistant that can check the weather, but will first decide if the user is being polite.

1. Define Tools & LLM

import asyncio
from lingo.llm import LLM, Message
from lingo.tools import tool
from lingo.flow import Flow, NoOp

llm = LLM(model="gpt-4o")

@tool
async def get_weather(location: str) -> str:
    """Gets the current weather for a specified location."""
    if "boston" in location.lower():
        return "It's 75°F and sunny in Boston."
    else:
        return f"Weather for {location} is unknown."

2. Define Reusable Sub-Flows

# A sub-flow is just another 'Flow' instance.
polite_flow = Flow().system(
    "Acknowledge the user's politeness before proceeding."
)

3. Define the Main Workflow

main_flow = (
    Flow()
    # Step 1: Add a system message to the context
    .system("You are a helpful assistant. You can check the weather.")

    # Step 2: Use an LLM to make a True/False decision
    .decide(
        prompt="Is the user being polite (e.g., asking 'please')?",
        on_true=polite_flow,  # Run the sub-flow if True
        on_false=NoOp()       # Do nothing if False
    )

    # Step 3: Equip and invoke a tool from the available list
    .invoke(get_weather)

    # Step 4: Generate a final reply using the tool's output
    .reply()
)

4. Execute the Flow

async def main():
    # Example 1: The "polite" branch
    user_query_1 = "Could you please tell me the weather in Boston?"

    # .execute() runs the full pipeline on the initial messages
    final_context = await main_flow.run(llm, [Message.user(user_query_1)])

    print(f"User: {user_query_1}")
    print(f"Assistant: {final_context.messages[-1].content}")
    # Assistant: It's 75°F and sunny in Boston. I'm happy to help!

    print("\n" + "-"*20 + "\n")

    # Example 2: The "impolite" branch
    user_query_2 = "boston weather now"
    final_context_2 = await main_flow.run(llm, [Message.user(user_query_2)])

    print(f"User: {user_query_2}")
    print(f"Assistant: {final_context_2.messages[-1].content}")
    # Assistant: It's 75°F and sunny in Boston.

if __name__ == "__main__":
    asyncio.run(main())

The Two APIs

lingo gives you the flexibility to choose the right level of abstraction.

1. High-Level API: Flow

The Flow class provides a fluent, chainable interface for declaratively building reusable workflows. You define the steps of the conversation, and lingo handles the execution.

# A flow is a composable, reusable blueprint
weather_flow = (
    Flow()
    .system("You only answer with the weather.")
    .invoke(get_weather)
    .reply()
)

# You can nest flows inside other flows
main_flow = (
    Flow()
    .choose(
        prompt="Is the user asking about weather or stocks?",
        choices={
            "weather": weather_flow,
            "stocks": stock_flow,
        }
    )
)

2. Low-Level API: LLM & Context

For maximum control, you can use the imperative API. The Context object holds the message history, and you call its methods (.reply(), .decide(), .invoke()) directly. This is ideal for building custom chatbot loops.

# Manually building a conversation turn by turn
llm = LLM(model="gpt-4o")
context = Context(llm, [Message.system("You are a chatbot.")])

while True:
    user_input = input("You: ")
    context.add(Message.user(user_input))

    # Call the LLM with the current context
    response = await context.reply()

    context.add(response)
    print(f"Bot: {response.content}")

Contributing

Contributions are welcome! lingo is an open-source project, and we'd love your help in making it better. Please feel free to open an issue or submit a pull request.

License

lingo is licensed under the MIT License. See the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lingo_ai-0.1.2.tar.gz (42.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lingo_ai-0.1.2-py3-none-any.whl (14.2 kB view details)

Uploaded Python 3

File details

Details for the file lingo_ai-0.1.2.tar.gz.

File metadata

  • Download URL: lingo_ai-0.1.2.tar.gz
  • Upload date:
  • Size: 42.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lingo_ai-0.1.2.tar.gz
Algorithm Hash digest
SHA256 189d78cb9978cd80e2d7a912c6f1c2c77c8af2d4c8ed2594017d167784900148
MD5 1f4cea64b363e605c1b0ef2d0783e6b4
BLAKE2b-256 dc33590954b472c117ae53d4e0c6a6b69de1c009cd07af4b33a230bc2e2ee748

See more details on using hashes here.

File details

Details for the file lingo_ai-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: lingo_ai-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 14.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.9 {"installer":{"name":"uv","version":"0.9.9"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for lingo_ai-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 32962282af2feefe8b537dbb560257def5ad28f5feac9cbe71a77d9ecd030c8a
MD5 72397b4a1ffe73188114c2c41d1d1885
BLAKE2b-256 057ca692e3a13a39bbd11e590b1f401a8874a299ee9ea323a022c9cc51500ee8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page