LangChain provider for Pollinations unified API (OpenAI-compatible chat completions + image endpoint).
Project description
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-compatiblePOST /v1/chat/completionsendpoint.ImagePollinations— image and video generation wrapper forGET /image/{prompt}.TTSPollinations— text-to-speech wrapper forPOST /v1/audio/speech.STTPollinations— speech-to-text wrapper forPOST /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 |
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file langchain_pollinations-0.3.0b2.tar.gz.
File metadata
- Download URL: langchain_pollinations-0.3.0b2.tar.gz
- Upload date:
- Size: 9.3 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
359dd8bef27ac8edf85868f1fc1b0a5e9d0d6742e26f76b616c2e7eb393e417b
|
|
| MD5 |
1402e107ee64e753b33fcfd500a3a20a
|
|
| BLAKE2b-256 |
7698f1cca53bb5346e0b5c398a7db442a2cce951040fec6c5b171026972216ce
|
Provenance
The following attestation bundles were made for langchain_pollinations-0.3.0b2.tar.gz:
Publisher:
publish.yml on onatrain/langchain-pollinations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_pollinations-0.3.0b2.tar.gz -
Subject digest:
359dd8bef27ac8edf85868f1fc1b0a5e9d0d6742e26f76b616c2e7eb393e417b - Sigstore transparency entry: 1107897873
- Sigstore integration time:
-
Permalink:
onatrain/langchain-pollinations@7675a15590c89571ff89a5bba98631f202a2ffda -
Branch / Tag:
refs/tags/v0.3.0b2 - Owner: https://github.com/onatrain
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7675a15590c89571ff89a5bba98631f202a2ffda -
Trigger Event:
push
-
Statement type:
File details
Details for the file langchain_pollinations-0.3.0b2-py3-none-any.whl.
File metadata
- Download URL: langchain_pollinations-0.3.0b2-py3-none-any.whl
- Upload date:
- Size: 62.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d96a4858d5cef1716cfc3ddf2206590eed792176e1ec07d1d942b1fdfa71be2b
|
|
| MD5 |
f22bf8edaf568410feced1a56c89ac01
|
|
| BLAKE2b-256 |
ac76cf8790f3de2f568542a29b74a3dac5cedb73028034f16a997996414cc524
|
Provenance
The following attestation bundles were made for langchain_pollinations-0.3.0b2-py3-none-any.whl:
Publisher:
publish.yml on onatrain/langchain-pollinations
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
langchain_pollinations-0.3.0b2-py3-none-any.whl -
Subject digest:
d96a4858d5cef1716cfc3ddf2206590eed792176e1ec07d1d942b1fdfa71be2b - Sigstore transparency entry: 1107897886
- Sigstore integration time:
-
Permalink:
onatrain/langchain-pollinations@7675a15590c89571ff89a5bba98631f202a2ffda -
Branch / Tag:
refs/tags/v0.3.0b2 - Owner: https://github.com/onatrain
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7675a15590c89571ff89a5bba98631f202a2ffda -
Trigger Event:
push
-
Statement type: