Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

langchain-pollinations

langchain-pollinations

A LangChain compatible provider library for Pollinations.ai

Build Coverage Status PyPI Version License Python Versions
LangChain Pollinations LangGraph


langchain-pollinations provides LangChain-native wrappers for the Pollinations.ai API, designed to plug into the modern LangChain ecosystem (v1.2x) while staying strictly aligned with Pollinations.ai endpoints.

The library exposes six public entry points:

  • ChatPollinations — chat model wrapper for the OpenAI-compatible POST /v1/chat/completions endpoint.
  • ImagePollinations — image and video generation wrapper for GET /image/{prompt}.
  • TTSPollinations — text-to-speech wrapper for POST /v1/audio/speech.
  • STTPollinations — speech-to-text wrapper for POST /v1/audio/transcriptions.
  • ModelInformation — utility for listing available text, image, audio, and OpenAI-compatible models.
  • AccountInformation — client for querying profile, balance, API key, and usage statistics.

Why Pollinations

Pollinations.ai provides a unified gateway for text generation, vision, tool use, and multimodal media—including images, video, and audio—behind a single OpenAI-compatible API surface. This library makes that gateway usable with idiomatic LangChain patterns (invoke, stream, bind_tools, with_structured_output) while keeping the public interface minimal and all configuration strictly typed via Pydantic.

Installation

pip install langchain-pollinations

Authentication

Copy .env.example to .env and set your key:

POLLINATIONS_API_KEY=sk-...your_key...

All main classes also accept an explicit api_key= parameter on construction.

ChatPollinations

ChatPollinations inherits from LangChain's BaseChatModel and supports invoke, stream, ainvoke, astream, tool calling, structured output, and multimodal messages.

Available text models

Group Models
OpenAI openai, openai-fast, openai-large, openai-audio
Google gemini, gemini-fast, gemini-large, gemini-legacy, gemini-search
Anthropic claude, claude-fast, claude-large, claude-legacy
Reasoning perplexity-reasoning, perplexity-fast, deepseek
Other mistral, grok, kimi, qwen-coder, qwen-safety, glm, minimax, nova-fast, midijourney, chickytutor

Basic usage

import dotenv
from langchain_pollinations import ChatPollinations
from langchain_core.messages import HumanMessage, SystemMessage

dotenv.load_dotenv()

llm = ChatPollinations(model="openai", temperature=0.7)
res = llm.invoke([
    SystemMessage(content="You are a concise assistant."),
    HumanMessage(content="What is the capital of France?"),
])
print(res.content)

Streaming

import dotenv
from langchain_pollinations import ChatPollinations
from langchain_core.messages import HumanMessage

dotenv.load_dotenv()

llm = ChatPollinations(model="gemini-fast")
for chunk in llm.stream([HumanMessage(content="List 5 Python tips.")]):
    print(chunk.content, end="", flush=True)

Multimodal input

ChatPollinations accepts image_url, input_audio, video_url, and file content blocks inside HumanMessage:

import dotenv
from langchain_pollinations import ChatPollinations
from langchain_core.messages import HumanMessage

dotenv.load_dotenv()

llm = ChatPollinations(model="openai-large")
res = llm.invoke([
    HumanMessage(content=[
        {"type": "text", "text": "Describe this image."},
        {"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
    ])
])
print(res.content)

Tool calling

import pprint
import dotenv
from langchain_core.tools import tool
from langchain_pollinations import ChatPollinations

dotenv.load_dotenv()

@tool
def get_weather(city: str) -> str:
    """Return the current weather for a city."""
    return f"It is sunny in {city}."

llm = ChatPollinations(model="openai").bind_tools([get_weather])
res = llm.invoke("What is the weather in Caracas?")

print("Response type:", type(res), "\n")
pprint.pprint(res.model_dump())

print("\nTool call:")
pprint.pprint(res.tool_calls)

bind_tools also accepts Pollinations built-in tools by type string:

llm = ChatPollinations(model="gemini").bind_tools([
    {"type": "google_search"},
    {"type": "code_execution"},
])

Structured output

import dotenv
from pydantic import BaseModel
from langchain_pollinations import ChatPollinations

dotenv.load_dotenv()

class MovieReview(BaseModel):
    title: str
    rating: int
    summary: str

llm = ChatPollinations(model="openai").with_structured_output(MovieReview)
review = llm.invoke("Review the movie Interstellar.")
print(review)

Async usage

All blocking methods have async counterparts: ainvoke, astream, abatch.

import asyncio
import dotenv
from langchain_pollinations import ChatPollinations
from langchain_core.messages import HumanMessage

dotenv.load_dotenv()

async def main():
    llm = ChatPollinations(model="gemini-fast")
    async for chunk in llm.astream([HumanMessage(content="List 3 Python tips.")]):
        print(chunk.content, end="", flush=True)

asyncio.run(main())

ImagePollinations

ImagePollinations targets GET /image/{prompt} and supports synchronous and asynchronous generation of images and videos with full LangChain invoke/ainvoke compatibility.

Available image / video models

Type Models
Image flux, zimage, klein, klein-large, nanobanana, nanobanana-pro, seedream, seedream-pro, kontext
Image (quality) gptimage, gptimage-large, imagen-4
Video veo, grok-video, seedance, seedance-pro, wan, ltx-2

Basic image generation

import dotenv
from langchain_pollinations import ImagePollinations

dotenv.load_dotenv()

img = ImagePollinations(model="flux", width=1024, height=1024, seed=42)
data = img.generate("a cyberpunk city at night, neon lights")
with open("city.jpg", "wb") as f:
    f.write(data)

Fluent interface with with_params()

with_params() returns a new pre-configured instance without mutating the original, making it easy to create specialized generators from a shared base:

import dotenv
from langchain_pollinations import ImagePollinations

dotenv.load_dotenv()

base = ImagePollinations(model="flux", width=1024, height=1024)

pixel_art = base.with_params(model="klein", enhance=True)
portrait  = base.with_params(width=768, height=1024, safe=True)

data1 = pixel_art.generate("a pixel art knight standing on a cliff")
with open("knight.jpg", "wb") as f:
    f.write(data1)

data2 = portrait.generate("a watercolor portrait of a scientist")
with open("scientist.jpg", "wb") as f:
    f.write(data2)

Video generation

import dotenv
from langchain_pollinations import ImagePollinations

dotenv.load_dotenv()

vid = ImagePollinations(
    model="seedance",
    duration=4,
    aspect_ratio="16:9",
    audio=True,
)
resp = vid.generate_response("two medieval horse-knights fighting with spades at sunset, cinematic")

content_type = resp.headers.get("content-type", "")
ext = ".mp4" if "video" in content_type else ".bin"
with open(f"fighting_knights{ext}", "wb") as f:
    f.write(resp.content)
print(f"Saved fighting_knights{ext} ({len(resp.content)} bytes)")

Async generation

import asyncio
import dotenv
from langchain_pollinations import ImagePollinations

dotenv.load_dotenv()

async def main():
    img = ImagePollinations(model="flux")
    data = await img.agenerate("a misty forest at dawn, soft light")
    with open("forest.jpg", "wb") as f:
        f.write(data)

asyncio.run(main())

TTSPollinations

TTSPollinations wraps POST /v1/audio/speech and converts text to audio. It supports a dynamic audio model catalog, per-instance parameter defaults, and a LangChain Runnable-compatible interface.

Available TTS models and voices

Models Notes
tts-1 Standard OpenAI TTS
elevenlabs ElevenLabs voices
elevenmusic Music generation; supports duration and instrumental

Supported output formats: mp3 (default), opus, aac, flac, wav, pcm.

Available voices include: alloy, echo, fable, onyx, shimmer, ash, ballad, coral, sage, verse, rachel, domi, bella, elli, charlotte, dorothy, sarah, emily, lily, matilda, adam, antoni, arnold, josh, sam, daniel, charlie, james, fin, callum, liam, george, brian, bill.

Basic speech generation

import dotenv
from langchain_pollinations import TTSPollinations

dotenv.load_dotenv()

tts = TTSPollinations(voice="rachel", response_format="mp3")
audio_bytes = tts.generate("Hello, welcome to langchain-pollinations.")
with open("speech.mp3", "wb") as f:
    f.write(audio_bytes)

Per-call parameter overrides

Instance defaults can be overridden on any individual call:

import dotenv
from langchain_pollinations import TTSPollinations

dotenv.load_dotenv()

tts = TTSPollinations(model="elevenlabs", voice="onyx")

# Override voice and speed for this call only
audio = tts.generate("A slower, calm narration.", speed=0.8, voice="echo")
with open("narration.mp3", "wb") as f:
    f.write(audio)

Music generation with elevenmusic

import dotenv
from langchain_pollinations import TTSPollinations

dotenv.load_dotenv()

music = TTSPollinations(
    model="elevenmusic",
    duration=30,
    instrumental=True,
    response_format="mp3",
)
audio_bytes = music.generate("An upbeat jazz theme with piano and drums")
with open("theme.mp3", "wb") as f:
    f.write(audio_bytes)

LangChain pipeline

import dotenv
from langchain_core.runnables import RunnableLambda
from langchain_pollinations import ChatPollinations, TTSPollinations

dotenv.load_dotenv()

llm = ChatPollinations(model="openai-fast")
tts = TTSPollinations(voice="shimmer")

pipeline = llm | RunnableLambda(lambda msg: msg.content) | tts
audio = pipeline.invoke("Summarize the water cycle in two sentences.")
with open("summary.mp3", "wb") as f:
    f.write(audio)

Async generation

import asyncio
import dotenv
from langchain_pollinations import TTSPollinations

dotenv.load_dotenv()

async def main():
    tts = TTSPollinations(voice="alloy", response_format="wav")
    audio = await tts.agenerate("Async text-to-speech with Pollinations.")
    with open("output.wav", "wb") as f:
        f.write(audio)

asyncio.run(main())

STTPollinations

STTPollinations wraps POST /v1/audio/transcriptions and converts audio files to text using a multipart/form-data request. It supports typed response parsing, language hints, verbose JSON output, and a LangChain Runnable-compatible interface.

Available STT models

Model Notes
whisper-large-v3 Default; high-accuracy multilingual transcription
whisper-1 Faster, lighter Whisper variant
scribe ElevenLabs Scribe model

Accepted audio input formats: mp3, mp4, mpeg, mpga, m4a, wav, webm.

Response formats: json (default), text, srt, verbose_json, vtt.

Basic transcription

import dotenv
from langchain_pollinations import STTPollinations

dotenv.load_dotenv()

stt = STTPollinations()
with open("speech.mp3", "rb") as fh:
    result = stt.transcribe(fh.read())
print(result.text)

Language hint and custom model

import dotenv
from langchain_pollinations import STTPollinations

dotenv.load_dotenv()

stt = STTPollinations(model="scribe", language="es")
with open("grabacion.wav", "rb") as fh:
    result = stt.transcribe(fh.read(), filename="grabacion.wav")
print(result.text)

Verbose JSON for segment-level data

When response_format="verbose_json", additional metadata (segments, words, language, duration) is available via result.model_extra:

import dotenv
from langchain_pollinations import STTPollinations

dotenv.load_dotenv()

stt = STTPollinations(response_format="verbose_json")
with open("interview.mp3", "rb") as fh:
    result = stt.transcribe(fh.read())

print(result.text)
print("Segments:", result.model_extra.get("segments"))
print("Detected language:", result.model_extra.get("language"))

Plain text and subtitle formats

When response_format is "text", "srt", or "vtt", the return value is a plain str:

import dotenv
from langchain_pollinations import STTPollinations

dotenv.load_dotenv()

stt = STTPollinations(response_format="srt")
with open("video_audio.mp3", "rb") as fh:
    subtitles = stt.transcribe(fh.read())  # returns str
with open("subtitles.srt", "w") as f:
    f.write(subtitles)

LangChain pipeline

import dotenv
from langchain_core.runnables import RunnableLambda
from langchain_pollinations import STTPollinations, ChatPollinations
from langchain_core.messages import HumanMessage

dotenv.load_dotenv()

stt = STTPollinations(language="en")
llm = ChatPollinations(model="openai-fast")

pipeline = (
    stt
    | RunnableLambda(lambda r: [HumanMessage(content=f"Summarize: {r.text}")])
    | llm
)

with open("meeting.mp3", "rb") as fh:
    summary = pipeline.invoke(fh.read())
print(summary.content)

Async transcription

import asyncio
import dotenv
from langchain_pollinations import STTPollinations

dotenv.load_dotenv()

async def main():
    stt = STTPollinations(model="whisper-large-v3")
    with open("audio.mp3", "rb") as fh:
        audio = fh.read()
    result = await stt.atranscribe(audio)
    print(result.text)

asyncio.run(main())

ModelInformation

import dotenv
from langchain_pollinations import ModelInformation

dotenv.load_dotenv()

info = ModelInformation()

# Text models
for m in info.list_text_models():
    print(
        m.get("name"),
        "- input_modalities: ", m.get("input_modalities"),
        "- output_modalities: ", m.get("output_modalities"),
        "- tools: ", m.get("tools"),
    )
print()

# Image models
for m in info.list_image_models():
    print(
        m.get("name"),
        "- input_modalities: ", m.get("input_modalities"),
        "- output_modalities: ", m.get("output_modalities"),
    )
print()

# Audio models (TTS + STT)
for m in info.list_audio_models():
    print(m.get("name") or m.get("id"))
print()

# All model IDs at once
available = info.get_available_models()
print("Text models:",  available["text"],  "\n")
print("Image models:", available["image"], "\n")
print("Audio models:", available["audio"], "\n")

# OpenAI-compatible /v1/models
compat = info.list_compatible_models()
print(compat)

Async equivalents: alist_text_models, alist_image_models, alist_audio_models, alist_compatible_models, aget_available_models.

AccountInformation

import dotenv
from langchain_pollinations import AccountInformation
from langchain_pollinations.account import AccountUsageDailyParams, AccountUsageParams

dotenv.load_dotenv()

account = AccountInformation()

balance = account.get_balance()
print(f"Balance: {balance['balance']} credits")

# Retrieve API key metadata
key_info = account.get_key()
print(key_info, "\n")

# Account profile
profile = account.get_profile()
print(profile.tier, profile.created_at, "\n")

# Paginated usage logs
usage = account.get_usage(params=AccountUsageParams(limit=50, format="json"))
print(usage, "\n")

# Daily aggregated usage
daily = account.get_usage_daily(params=AccountUsageDailyParams(format="json"))
print(daily, "\n")

Async equivalents: aget_profile, aget_balance, aget_key, aget_usage, aget_usage_daily.

Error handling

All errors surface as PollinationsAPIError, which carries structured fields parsed directly from the API error envelope:

from langchain_pollinations import ChatPollinations, PollinationsAPIError
from langchain_core.messages import HumanMessage

try:
    llm = ChatPollinations(model="gemini", api_key="anyway")
    res = llm.invoke([HumanMessage(content="Hello")])
    print(res.content)
except PollinationsAPIError as e:
    if e.is_auth_error:
        print("Check your POLLINATIONS_API_KEY.")
    elif e.is_payment_required:
        print("Insufficient balance. Some models are for paid-only use.")
    elif e.is_validation_error:
        print(f"Bad request: {e.details}")
    elif e.is_server_error:
        print(f"Server error {e.status_code} – consider retrying.")
    else:
        print(e.to_dict())

PollinationsAPIError exposes: status_code, message, error_code, request_id, timestamp, details, cause, and convenience properties is_auth_error, is_payment_required, is_validation_error, is_client_error, is_server_error.

Debug logging

Set POLLINATIONS_HTTP_DEBUG=true to log every outgoing request and incoming response. Authorization headers are automatically redacted in all log output.

POLLINATIONS_HTTP_DEBUG=true python my_script.py

Contributing

Issues and pull requests are welcome—especially around edge-case compatibility with LangChain agent and tool flows, LangGraph integration, and improved ergonomics for saving generated media.

License

Released under the MIT License.

Metadata

Release files for langchain-pollinations 0.3.0b3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for langchain-pollinations 0.3.0b3
File Size Uploaded
langchain_pollinations-0.3.0b3.tar.gz 9.3 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for langchain-pollinations 0.3.0b3
File Interpreter ABI Platform
langchain_pollinations-0.3.0b3-py3-none-any.whl Python 3 none any Details

Total release size: 9.4 MB

Release files / langchain_pollinations-0.3.0b3.tar.gz

Download URL langchain_pollinations-0.3.0b3.tar.gz
Size 9.3 MB
Tags Source
SHA-256 checksum
How to use checksums
55a285362a9f630398b8509db5d2b96d9eafa17dab089ac0c98c3d7989974ce0
BLAKE2b-256 checksum
How to use checksums
46726528fe8185d2bbfb16663b10a262d006de3ac19603c01a32ad1cb9bb90f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 11, 2026.

Transparency log

Release files / langchain_pollinations-0.3.0b3-py3-none-any.whl

Download URL langchain_pollinations-0.3.0b3-py3-none-any.whl
Size 62.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a60ff00be3a1d6ce6535ae6b3b5424859cb519b83dc1aaf3178bca6526734b85
BLAKE2b-256 checksum
How to use checksums
e32c3f82e9c66cbe78b30ebfa53c428d8e1176d718f29a72048e196e22238027
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 11, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page