Using ASI:One with LangChain

Overview

ASI:One is OpenAI-compatible, so LangChain works against it with no adapter. Use ChatOpenAI and point it at https://api.asi1.ai/v1.

$pip install langchain-openai

Every example below reads the key from the environment:

$export ASI_ONE_API_KEY="your-api-key"

Connecting

1import os
2from langchain_openai import ChatOpenAI
3from langchain_core.messages import HumanMessage, SystemMessage
4
5llm = ChatOpenAI(
6 model="asi1",
7 base_url="https://api.asi1.ai/v1",
8 api_key=os.getenv("ASI_ONE_API_KEY"),
9 temperature=0.7,
10)
11
12messages = [
13 SystemMessage(content="You are a helpful AI assistant."),
14 HumanMessage(content="What is agentic AI?"),
15]
16
17response = llm.invoke(messages)
18print(response.content)

Swap model for asi1-ultra or asi1-mini to trade depth against speed. See ASI:One Models.

Streaming

1import os
2from langchain_openai import ChatOpenAI
3from langchain_core.messages import HumanMessage
4
5llm = ChatOpenAI(
6 model="asi1",
7 base_url="https://api.asi1.ai/v1",
8 api_key=os.getenv("ASI_ONE_API_KEY"),
9 streaming=True,
10)
11
12for chunk in llm.stream([HumanMessage(content="Explain blockchain in simple terms")]):
13 print(chunk.content, end="", flush=True)

Structured output

with_structured_output takes a Pydantic model and gives you back a typed object instead of a string. This is usually cleaner than handling response_format yourself. See Structured Data for the raw API.

1import os
2from typing import List
3
4from langchain_openai import ChatOpenAI
5from pydantic import BaseModel, Field
6
7
8class Product(BaseModel):
9 """A product extracted from text."""
10
11 name: str = Field(description="Product name")
12 price: float = Field(description="Price in USD")
13 category: str = Field(description="Product category")
14
15
16class ProductList(BaseModel):
17 """A list of products."""
18
19 products: List[Product] = Field(description="List of extracted products")
20
21
22llm = ChatOpenAI(
23 model="asi1",
24 base_url="https://api.asi1.ai/v1",
25 api_key=os.getenv("ASI_ONE_API_KEY"),
26)
27
28structured_llm = llm.with_structured_output(ProductList)
29
30text = """
31Our store has the following items:
32- Wireless Mouse ($29.99) - Electronics
33- Organic Coffee Beans ($14.50) - Groceries
34- Running Shoes ($89.00) - Sports
35"""
36
37result = structured_llm.invoke(f"Extract all products from this text:\n{text}")
38
39for product in result.products:
40 print(f"- {product.name}: ${product.price} ({product.category})")

Tool calling

Decorate your functions with @tool and bind them to the model. ASI:One decides which to call and returns the calls for you to execute. See Tool Calling for the underlying protocol.

1import os
2
3from langchain_core.tools import tool
4from langchain_openai import ChatOpenAI
5
6
7@tool
8def get_weather(city: str) -> str:
9 """Get the current weather for a city."""
10 # In production, call a real weather API
11 return f"The weather in {city} is sunny, 22°C"
12
13
14@tool
15def search_restaurants(city: str, cuisine: str) -> str:
16 """Search for restaurants in a city by cuisine type."""
17 return f"Found 5 {cuisine} restaurants in {city}"
18
19
20llm = ChatOpenAI(
21 model="asi1",
22 base_url="https://api.asi1.ai/v1",
23 api_key=os.getenv("ASI_ONE_API_KEY"),
24)
25
26llm_with_tools = llm.bind_tools([get_weather, search_restaurants])
27
28response = llm_with_tools.invoke(
29 "What's the weather in Tokyo and find me some sushi restaurants there?"
30)
31print(response.tool_calls)

Using ASI:One’s own parameters

LangChain sends the parameters the OpenAI API defines, so ASI:One’s own parameters go through extra_body:

1llm = ChatOpenAI(
2 model="asi1",
3 base_url="https://api.asi1.ai/v1",
4 api_key=os.getenv("ASI_ONE_API_KEY"),
5 extra_body={"enable_thinking": True, "thinking_budget": 2048},
6)

Planner mode needs one more thing: its x-session-id is a header rather than a body field, so it goes through default_headers instead.

1llm = ChatOpenAI(
2 model="asi1",
3 base_url="https://api.asi1.ai/v1",
4 api_key=os.getenv("ASI_ONE_API_KEY"),
5 extra_body={"planner_mode": True},
6 default_headers={"x-session-id": "4f9c2b18-6d1e-4a77-9f30-2c5b8e7a1d64"},
7)

Use a fresh session id for each new job and keep it constant for every request belonging to that job. See Reasoning and Planner Mode.

Each endpoint supports its own set of OpenAI parameters, so check OpenAI Compatibility before relying on a LangChain setting that maps onto one of them.

Next steps

  1. Chat Completions API - The endpoint ChatOpenAI talks to, in full
  2. OpenAI Compatibility - Which parameters are supported on each endpoint
  3. ASI:One Models - Choosing between asi1, asi1-ultra and asi1-mini
  4. Tool Calling - The raw tool-calling protocol