Skip to content

Easy AI

py_simple.easy_ai

easy_ai wraps common LangChain functionality to make it easier to use.

EasyAIError

Bases: Exception

Raised when a call to an AI model or provider cannot be completed.

Parameters:

Name Type Description Default
message str

Description of what went wrong.

required

ai_chat(ai_model)

Runs an interactive chat loop in the terminal against a LangChain chat model, without you having to write the input/print loop, exit handling, or conversation memory yourself.

Prompts for input with "You: ", prints each reply prefixed with "AI: ", and keeps going until the user types "exit", "quit", "stop", or "bye" (at which point it prints a goodbye message and returns). Each turn is appended to an internal history list of HumanMessage/ AIMessage objects, and the full history is sent to the model on every call, so the model has memory of the whole conversation for as long as the loop runs. The history is local to this call and is not preserved once the loop exits. Errors from ask_ai() are caught and printed instead of raising, so a single bad call doesn't end the session.

Parameters:

Name Type Description Default
ai_model BaseChatModel

A LangChain chat model instance, such as one returned by get_model().

required

Returns:

Type Description
None

None. Runs until the user exits the loop.

Example
from py_simple import get_model, ai_chat

model = get_model("anthropic", "claude-sonnet-4-6")
ai_chat(model)
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage, AIMessage

model = ChatAnthropic(model_name="claude-sonnet-4-6")

history = []
while True:
    user_input = input("You: ")
    if user_input.lower() in ("exit", "quit", "stop", "bye"):
        print("AI: Talk to you later!")
        break
    history.append(HumanMessage(content=user_input))
    response = model.invoke(history).content
    history.append(AIMessage(content=response))
    print(f"AI: {response}")

analyze_sentiment(ai_model, text)

Sends a request to analyze the sentiment of the provided text using the
given LangChain chat model, returning a brief classification (e.g. Positive,
Negative, or Neutral).

Args:
    ai_model (BaseChatModel): A LangChain chat model instance,
        such as one returned by `get_model()`.
    text (str): The raw text string to analyze.

Returns:
    str: The sentiment classification of the text.

Raises:
    EasyAIError: If the underlying model call fails.

Example:
    === "The Py_simple Way"
        ```python
        from py_simple import get_model, analyze_sentiment

        model = get_model("anthropic", "claude-sonnet-4-6")
        sentiment = analyze_sentiment(
            model,
            "I absolutely love this new tool!",
        )
        ```

    === "The Traditional Way"
        ```python
        from langchain_anthropic import ChatAnthropic
        from langchain_core.messages import HumanMessage

        model = ChatAnthropic(model_name="claude-sonnet-4-6")
        sentiment = model.invoke([
            HumanMessage(
                content=(
                    "Analyze the sentiment of the following text and "
                    "respond with a single word "
                    "(e.g., Positive, Negative, Neutral):

" "I absolutely love this new tool!" ) ) ]).content ```

ask_ai(ai_model, question)

Sends a question to a LangChain chat model and returns the content of the response, without you having to reach into the returned message object yourself.

Parameters:

Name Type Description Default
ai_model BaseChatModel

A LangChain chat model instance, such as one returned by get_model().

required
question str | list

Either a single question as plain text, or a list of LangChain message objects (HumanMessage/AIMessage) representing the conversation so far. Pass a list to give the model memory of prior turns; the caller is responsible for building and updating that list.

required

Returns:

Type Description
str | list[str | dict[Any, Any]]

The model's response content. Usually a plain string, but

str | list[str | dict[Any, Any]]

some providers may return a list of content blocks instead.

Raises:

Type Description
EasyAIError

If the underlying call to the model fails for any reason (e.g. invalid API key, network error, timeout).

Example
from py_simple import get_model, ask_ai

model = get_model("anthropic", "claude-sonnet-4-6")
answer = ask_ai(model, "hi")
from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(model_name="claude-sonnet-4-6")
answer = model.invoke("hi").content

chunk_text(text, max_chars=500)

Split text into pieces that fit inside a character limit.

Useful before sending a long note to an AI model that only accepts a short prompt. Words stay whole when they fit. A single word longer than the limit is split so nothing is dropped.

Parameters:

Name Type Description Default
text str

The text to split.

required
max_chars int

Maximum characters in each piece. Defaults to 500.

500

Returns:

Type Description
list[str]

list[str]: The pieces, in order. An empty string returns an empty list.

Raises:

Type Description
EasyAIError

If text is not a string or max_chars is less than 1.

Example
from py_simple import chunk_text

pieces = chunk_text("Pack a lunch and a notebook", max_chars=16)
text = "Pack a lunch and a notebook"
words = text.split()
pieces = []
current = ""
for word in words:
    candidate = word if not current else f"{current} {word}"
    if len(candidate) <= 16:
        current = candidate
    else:
        pieces.append(current)
        current = word
if current:
    pieces.append(current)

detect_language(text)

Guesses which language a piece of text is written in, using simple keyword scoring rules, without installing a language-detection library or calling an external API.

Parameters:

Name Type Description Default
text str

The raw text to analyze.

required

Returns:

Name Type Description
str str

The detected language name (e.g., "English"), or

str

"Unknown" if nothing could be confidently identified.

Raises:

Type Description
EasyAIError

If text is not a string or is empty/whitespace.

Example
from py_simple import detect_language

language = detect_language("Hello, how are you?")
# "English"

get_model(provider, model_name, api_key=None, base_url=None, timeout=30)

Returns a LangChain chat model instance for the given provider, without you having to remember each provider's import path and constructor arguments.

Parameters:

Name Type Description Default
provider str

Name of the LLM provider. One of "openai", "ollama", "anthropic", "google", or "mistral". Case-insensitive.

required
model_name str

Name of the model to use (e.g., "gpt-4o", "llama3", "claude-sonnet-4-6").

required
api_key str

API key for the provider, if required. Not used for "ollama". Defaults to None.

None
base_url str

Custom base URL for the provider. Used for "openai" and "ollama" (defaults to "http://localhost:11434" for ollama if not provided). Defaults to None.

None
timeout int

Request timeout in seconds. Currently only used for "anthropic". Defaults to 30.

30

Returns:

Type Description
BaseChatModel

A LangChain chat model instance corresponding to the given

BaseChatModel

provider.

Raises:

Type Description
EasyAIError

If provider isn't one of the supported providers.

Example
from py_simple import get_model

model = get_model("anthropic", "claude-sonnet-4-6")
from langchain_anthropic import ChatAnthropic

model = ChatAnthropic(
    model_name="claude-sonnet-4-6",
    timeout=30,
    stop=None
)

rewrite_text(ai_model, text, tone='calm')

Sends a request to change the tone of the provided text, without you having to change it manually.

Parameters:

Name Type Description Default
ai_model BaseChatModel

A LangChain chat model instance, such as one returned by get_model().

required
text str

Text whose tone will be changed.

required
tone str

Used to decide the tone for the text that the user wants (e.g. calm, angry, nervous, supportive, etc.). Defaults to "calm".

'calm'

Returns:

Name Type Description
str str

The text with its tone changed.

Raises:

Type Description
EasyAIError

If the underlying model call fails.

Example
from py_simple import get_model, rewrite_text

model = get_model("anthropic", "claude-sonnet-4-6")
tone = rewrite_text(
    model,
    "hello py-simple-wrap devs",
    "excited",
)
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

model = ChatAnthropic(model_name="claude-sonnet-4-6")
tone = model.invoke([
    HumanMessage(
        content="Change tone to excited: hello py-simple-wrap devs"
    )
]).content

summarize_text(ai_model, text)

Sends a request to summarize the provided text using the given
LangChain chat model, without you having to format messages manually.

Args:
    ai_model (BaseChatModel): A LangChain chat model instance,
        such as one returned by `get_model()`.
    text (str): The raw text string to be summarized.

Returns:
    str: A concise summary of the input text.

Raises:
    EasyAIError: If the underlying model call fails.

Example:
    === "The Py_simple Way"
        ```python
        from py_simple import get_model, summarize_text

        model = get_model("anthropic", "claude-sonnet-4-6")
        summary = summarize_text(model, "Long article text here...")
        ```

    === "The Traditional Way"
        ```python
        from langchain_anthropic import ChatAnthropic
        from langchain_core.messages import HumanMessage

        model = ChatAnthropic(model_name="claude-sonnet-4-6")
        summary = model.invoke(
            [HumanMessage(content="Please summarize:

Long article text here...")] ).content ```

translate_text(ai_model, text, target_lang='English')

Sends a request to translate the provided text into the target language using the given LangChain chat model, without you having to format messages manually.

Parameters:

Name Type Description Default
ai_model BaseChatModel

A LangChain chat model instance, such as one returned by get_model().

required
text str

The raw text string to be translated.

required
target_lang str

The name of the language to translate into (e.g. "French", "Spanish", "German"). Defaults to "English".

'English'

Returns:

Name Type Description
str str

The translated text.

Raises:

Type Description
EasyAIError

If the underlying model call fails.

Example
from py_simple import get_model, translate_text

model = get_model("anthropic", "claude-sonnet-4-6")
translation = translate_text(
    model,
    "Hola mundo",
    target_lang="English",
)
from langchain_anthropic import ChatAnthropic
from langchain_core.messages import HumanMessage

model = ChatAnthropic(model_name="claude-sonnet-4-6")
translation = model.invoke([
    HumanMessage(content="Translate to English: Hola mundo")
]).content