0
# Integrations
1
2
Seamless integration with popular ML/AI frameworks including automatic step tracking, observability, and LLM call monitoring. These integrations provide zero-configuration observability for AI applications built with industry-standard libraries.
3
4
## Capabilities
5
6
### OpenAI Integration
7
8
Automatic instrumentation of the OpenAI SDK with step tracking, token usage monitoring, and conversation logging.
9
10
```python { .api }
11
import chainlit as cl
12
13
def instrument_openai() -> None:
14
"""
15
Automatically instrument OpenAI SDK for step tracking and observability.
16
Call once during application startup to enable automatic LLM step creation.
17
18
Requirements:
19
- openai >= 1.0.0
20
21
Features:
22
- Automatic step creation for all OpenAI API calls
23
- Model name, timing, and token usage capture
24
- Message history tracking for chat completions
25
- Support for streaming responses
26
- Error handling and retry monitoring
27
28
Usage:
29
Call this function once at startup, then use OpenAI SDK normally.
30
All calls will automatically appear as steps in the Chainlit UI.
31
32
Returns:
33
None
34
"""
35
```
36
37
Usage examples for OpenAI integration:
38
39
```python
40
import chainlit as cl
41
import openai
42
43
# Initialize OpenAI instrumentation (call once at startup)
44
cl.instrument_openai()
45
46
# Initialize OpenAI client
47
openai_client = openai.AsyncOpenAI(api_key="your-api-key")
48
49
@cl.on_message
50
async def chat_with_openai(message: cl.Message):
51
"""Chat with OpenAI using automatic step tracking"""
52
53
# This call will automatically create a step in the UI
54
response = await openai_client.chat.completions.create(
55
model="gpt-3.5-turbo",
56
messages=[
57
{"role": "system", "content": "You are a helpful assistant."},
58
{"role": "user", "content": message.content}
59
],
60
temperature=0.7,
61
max_tokens=150
62
)
63
64
# Response is automatically tracked with:
65
# - Model used (gpt-3.5-turbo)
66
# - Token usage (prompt + completion tokens)
67
# - Timing information
68
# - Input messages and output response
69
70
await cl.Message(response.choices[0].message.content).send()
71
72
@cl.on_message
73
async def streaming_openai_example(message: cl.Message):
74
"""Example with streaming responses"""
75
76
# Streaming calls are also automatically instrumented
77
stream = await openai_client.chat.completions.create(
78
model="gpt-4",
79
messages=[{"role": "user", "content": message.content}],
80
stream=True,
81
temperature=0.8
82
)
83
84
# Stream response to UI
85
msg = cl.Message("")
86
await msg.send()
87
88
async for chunk in stream:
89
if chunk.choices[0].delta.content:
90
await msg.stream_token(chunk.choices[0].delta.content)
91
92
# Step automatically tracks full conversation and final token counts
93
94
@cl.on_message
95
async def function_calling_example(message: cl.Message):
96
"""Example with OpenAI function calling"""
97
98
# Function definitions
99
functions = [
100
{
101
"name": "get_weather",
102
"description": "Get current weather information",
103
"parameters": {
104
"type": "object",
105
"properties": {
106
"location": {"type": "string", "description": "City name"}
107
},
108
"required": ["location"]
109
}
110
}
111
]
112
113
# Function call - automatically tracked
114
response = await openai_client.chat.completions.create(
115
model="gpt-3.5-turbo",
116
messages=[{"role": "user", "content": message.content}],
117
functions=functions,
118
function_call="auto"
119
)
120
121
# Handle function call if requested
122
if response.choices[0].message.function_call:
123
function_name = response.choices[0].message.function_call.name
124
# Function execution is tracked in the same step
125
126
# Execute function (example)
127
if function_name == "get_weather":
128
result = "Sunny, 72°F"
129
130
# Send function result back to OpenAI
131
final_response = await openai_client.chat.completions.create(
132
model="gpt-3.5-turbo",
133
messages=[
134
{"role": "user", "content": message.content},
135
response.choices[0].message,
136
{"role": "function", "name": function_name, "content": result}
137
]
138
)
139
140
await cl.Message(final_response.choices[0].message.content).send()
141
else:
142
await cl.Message(response.choices[0].message.content).send()
143
```
144
145
### LangChain Integration
146
147
Comprehensive LangChain integration with callback handlers for step tracking and component monitoring.
148
149
```python { .api }
150
class LangchainCallbackHandler:
151
"""
152
Callback handler for LangChain integration with automatic step tracking.
153
154
Requirements:
155
- langchain >= 0.0.198
156
157
Args:
158
answer_prefix_tokens: Optional[List[str]] - Tokens that mark final answer
159
stream_final_answer: bool - Whether to stream final responses (default: False)
160
to_ignore: List[str] - LangChain component names to ignore in tracking
161
to_keep: List[str] - Components to keep even if parent is ignored
162
163
Features:
164
- Automatic step creation for LangChain components (chains, agents, tools)
165
- LLM call tracking with generation metadata
166
- Token streaming support for real-time responses
167
- Tool execution and retrieval step monitoring
168
- Hierarchical step organization matching LangChain execution flow
169
170
Returns:
171
LangchainCallbackHandler instance for use with LangChain
172
"""
173
def __init__(
174
self,
175
answer_prefix_tokens: Optional[List[str]] = None,
176
stream_final_answer: bool = False,
177
to_ignore: List[str] = [],
178
to_keep: List[str] = []
179
): ...
180
181
# Async version for async LangChain components
182
AsyncLangchainCallbackHandler = LangchainCallbackHandler
183
```
184
185
Usage examples for LangChain integration:
186
187
```python
188
import chainlit as cl
189
from langchain.chains import LLMChain
190
from langchain.prompts import ChatPromptTemplate
191
from langchain.chat_models import ChatOpenAI
192
from langchain.agents import create_openai_functions_agent, AgentExecutor
193
from langchain.tools import Tool
194
195
@cl.on_message
196
async def langchain_basic_example(message: cl.Message):
197
"""Basic LangChain integration example"""
198
199
# Create LangChain callback handler
200
callback_handler = cl.AsyncLangchainCallbackHandler(
201
stream_final_answer=True,
202
answer_prefix_tokens=["Final", "Answer"]
203
)
204
205
# Create LangChain components
206
llm = ChatOpenAI(
207
model="gpt-3.5-turbo",
208
temperature=0.7,
209
streaming=True,
210
callbacks=[callback_handler]
211
)
212
213
prompt = ChatPromptTemplate.from_messages([
214
("system", "You are a helpful assistant."),
215
("human", "{input}")
216
])
217
218
# Create and run chain - automatically creates steps
219
chain = prompt | llm
220
221
response = await chain.ainvoke(
222
{"input": message.content},
223
config={"callbacks": [callback_handler]}
224
)
225
226
# Response is automatically streamed to UI via callback handler
227
# Steps show: Chain execution -> LLM call -> Response streaming
228
229
@cl.on_message
230
async def langchain_agent_example(message: cl.Message):
231
"""LangChain agent with tools example"""
232
233
callback_handler = cl.AsyncLangchainCallbackHandler(
234
stream_final_answer=True
235
)
236
237
# Define tools
238
def calculate(expression: str) -> str:
239
"""Calculate mathematical expressions."""
240
try:
241
result = eval(expression) # Note: Use safe eval in production
242
return str(result)
243
except Exception as e:
244
return f"Error: {str(e)}"
245
246
def search_web(query: str) -> str:
247
"""Search the web for information."""
248
# Mock implementation
249
return f"Search results for: {query}"
250
251
tools = [
252
Tool(
253
name="Calculator",
254
func=calculate,
255
description="Calculate mathematical expressions"
256
),
257
Tool(
258
name="WebSearch",
259
func=search_web,
260
description="Search the web for current information"
261
)
262
]
263
264
# Create agent
265
llm = ChatOpenAI(
266
model="gpt-3.5-turbo",
267
temperature=0,
268
callbacks=[callback_handler]
269
)
270
271
agent = create_openai_functions_agent(llm, tools,
272
ChatPromptTemplate.from_messages([
273
("system", "You are a helpful assistant with access to tools."),
274
("human", "{input}"),
275
("placeholder", "{agent_scratchpad}")
276
])
277
)
278
279
agent_executor = AgentExecutor(
280
agent=agent,
281
tools=tools,
282
callbacks=[callback_handler],
283
verbose=True
284
)
285
286
# Execute agent - creates hierarchical steps:
287
# Agent Execution -> Tool Selection -> Tool Execution -> LLM Response
288
response = await agent_executor.ainvoke(
289
{"input": message.content},
290
config={"callbacks": [callback_handler]}
291
)
292
293
await cl.Message(response["output"]).send()
294
295
@cl.on_message
296
async def langchain_rag_example(message: cl.Message):
297
"""LangChain RAG (Retrieval Augmented Generation) example"""
298
299
callback_handler = cl.AsyncLangchainCallbackHandler(
300
stream_final_answer=True,
301
to_ignore=["VectorStoreRetriever"], # Ignore noisy retriever logs
302
to_keep=["RetrievalQA"] # But keep the main QA chain
303
)
304
305
# Mock retrieval setup (replace with real vector store)
306
from langchain.vectorstores import FAISS
307
from langchain.embeddings import OpenAIEmbeddings
308
from langchain.chains import RetrievalQA
309
310
# Create mock vector store
311
embeddings = OpenAIEmbeddings(callbacks=[callback_handler])
312
313
# Mock documents (replace with real document loading)
314
docs = ["Document content 1", "Document content 2"]
315
vectorstore = FAISS.from_texts(docs, embeddings)
316
317
# Create RAG chain
318
llm = ChatOpenAI(
319
model="gpt-3.5-turbo",
320
callbacks=[callback_handler]
321
)
322
323
qa_chain = RetrievalQA.from_chain_type(
324
llm=llm,
325
chain_type="stuff",
326
retriever=vectorstore.as_retriever(),
327
callbacks=[callback_handler]
328
)
329
330
# Execute RAG - creates steps for:
331
# Question Processing -> Document Retrieval -> Context Assembly -> LLM Generation
332
response = await qa_chain.ainvoke(
333
{"query": message.content},
334
config={"callbacks": [callback_handler]}
335
)
336
337
await cl.Message(response["result"]).send()
338
```
339
340
### LlamaIndex Integration
341
342
LlamaIndex integration with callback handlers for query engines, retrievers, and index operations.
343
344
```python { .api }
345
class LlamaIndexCallbackHandler:
346
"""
347
Callback handler for LlamaIndex integration with step tracking.
348
349
Args:
350
event_starts_to_ignore: List[CBEventType] - Event types to ignore at start
351
event_ends_to_ignore: List[CBEventType] - Event types to ignore at end
352
353
Features:
354
- Automatic step creation for LlamaIndex operations
355
- Query engine and retriever monitoring
356
- LLM call tracking with generation data
357
- Retrieval and embedding step tracking
358
- Source document display and citations
359
- Index construction and update monitoring
360
361
Returns:
362
LlamaIndexCallbackHandler instance for use with LlamaIndex
363
"""
364
def __init__(
365
self,
366
event_starts_to_ignore: List = [],
367
event_ends_to_ignore: List = []
368
): ...
369
```
370
371
Usage examples for LlamaIndex integration:
372
373
```python
374
import chainlit as cl
375
from llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext
376
from llama_index.llms import OpenAI
377
from llama_index.callbacks import CallbackManager
378
379
@cl.on_chat_start
380
async def setup_llamaindex():
381
"""Initialize LlamaIndex with Chainlit integration"""
382
383
# Create callback handler
384
callback_handler = cl.LlamaIndexCallbackHandler()
385
callback_manager = CallbackManager([callback_handler])
386
387
# Setup LlamaIndex components
388
llm = OpenAI(
389
model="gpt-3.5-turbo",
390
temperature=0.7
391
)
392
393
service_context = ServiceContext.from_defaults(
394
llm=llm,
395
callback_manager=callback_manager
396
)
397
398
# Load documents (creates steps for document processing)
399
documents = SimpleDirectoryReader("./docs").load_data()
400
401
# Create index (creates steps for embedding and indexing)
402
index = VectorStoreIndex.from_documents(
403
documents,
404
service_context=service_context
405
)
406
407
# Store in session
408
cl.user_session.set("index", index)
409
cl.user_session.set("service_context", service_context)
410
411
await cl.Message("Knowledge base initialized! Ask me anything about the documents.").send()
412
413
@cl.on_message
414
async def llamaindex_query(message: cl.Message):
415
"""Query LlamaIndex with automatic step tracking"""
416
417
index = cl.user_session.get("index")
418
service_context = cl.user_session.get("service_context")
419
420
if not index:
421
await cl.Message("Please wait for the knowledge base to initialize.").send()
422
return
423
424
# Create query engine - automatically tracked
425
query_engine = index.as_query_engine(
426
service_context=service_context,
427
similarity_top_k=3,
428
response_mode="compact"
429
)
430
431
# Execute query - creates hierarchical steps:
432
# Query Processing -> Document Retrieval -> Context Ranking -> LLM Generation
433
response = await query_engine.aquery(message.content)
434
435
# Send response with source citations
436
response_text = str(response)
437
438
# Extract and display source documents
439
source_nodes = response.source_nodes
440
if source_nodes:
441
sources_text = "\n\n**Sources:**\n"
442
for i, node in enumerate(source_nodes, 1):
443
source_text = node.text[:200] + "..." if len(node.text) > 200 else node.text
444
sources_text += f"{i}. {source_text}\n"
445
446
response_text += sources_text
447
448
await cl.Message(response_text).send()
449
450
@cl.on_message
451
async def llamaindex_chat_engine(message: cl.Message):
452
"""Use LlamaIndex chat engine for conversational queries"""
453
454
index = cl.user_session.get("index")
455
456
# Get or create chat engine
457
chat_engine = cl.user_session.get("chat_engine")
458
if not chat_engine:
459
chat_engine = index.as_chat_engine(
460
chat_mode="condense_question",
461
verbose=True
462
)
463
cl.user_session.set("chat_engine", chat_engine)
464
465
# Chat with context awareness - automatically creates steps
466
response = await chat_engine.achat(message.content)
467
468
await cl.Message(str(response)).send()
469
```
470
471
### Mistral AI Integration
472
473
Automatic instrumentation for Mistral AI SDK with step tracking and model monitoring.
474
475
```python { .api }
476
def instrument_mistralai() -> None:
477
"""
478
Instrument Mistral AI SDK for automatic step tracking and observability.
479
Similar to OpenAI instrumentation but for Mistral AI models.
480
481
Requirements:
482
- mistralai SDK
483
484
Features:
485
- Automatic step creation for Mistral AI API calls
486
- Model performance and token usage monitoring
487
- Support for Mistral's chat and completion endpoints
488
- Error tracking and retry monitoring
489
490
Usage:
491
Call once at startup, then use Mistral AI SDK normally.
492
All API calls automatically appear as steps in Chainlit UI.
493
494
Returns:
495
None
496
"""
497
```
498
499
Usage example for Mistral AI integration:
500
501
```python
502
import chainlit as cl
503
from mistralai.client import MistralClient
504
from mistralai.models.chat_completion import ChatMessage
505
506
# Initialize Mistral AI instrumentation
507
cl.instrument_mistralai()
508
509
# Initialize Mistral client
510
mistral_client = MistralClient(api_key="your-mistral-api-key")
511
512
@cl.on_message
513
async def chat_with_mistral(message: cl.Message):
514
"""Chat with Mistral AI using automatic step tracking"""
515
516
# This call will automatically create a step in the UI
517
response = mistral_client.chat(
518
model="mistral-large-latest",
519
messages=[
520
ChatMessage(role="system", content="You are a helpful assistant."),
521
ChatMessage(role="user", content=message.content)
522
],
523
temperature=0.7,
524
max_tokens=150
525
)
526
527
# Automatically tracked with model info, timing, and token usage
528
await cl.Message(response.choices[0].message.content).send()
529
```
530
531
### Generic Integration Patterns
532
533
Common patterns for integrating other AI/ML libraries with Chainlit observability.
534
535
```python { .api }
536
# Manual step creation for custom integrations
537
async def integrate_custom_ai_library(input_data: str) -> str:
538
"""Example of manual step tracking for custom AI libraries"""
539
540
async with cl.Step(name="Custom AI Processing", type="llm") as step:
541
step.input = {"prompt": input_data, "model": "custom-model"}
542
543
# Call your custom AI library
544
result = await your_ai_library.process(input_data)
545
546
step.output = {"response": result, "tokens_used": 150}
547
548
return result
549
550
# Step decorator for function-level tracking
551
@cl.step(name="Document Processing", type="tool")
552
async def process_document(file_path: str) -> dict:
553
"""Process document with automatic step tracking"""
554
# Function execution is automatically wrapped in a step
555
556
# Your processing logic here
557
content = await extract_text(file_path)
558
analysis = await analyze_content(content)
559
560
return {
561
"content_length": len(content),
562
"analysis": analysis
563
}
564
```
565
566
## Integration Usage Patterns
567
568
### Multi-Framework Integration
569
570
Using multiple AI frameworks together with unified observability:
571
572
```python
573
import chainlit as cl
574
575
# Initialize all integrations
576
cl.instrument_openai()
577
cl.instrument_mistralai()
578
579
@cl.on_message
580
async def multi_framework_example(message: cl.Message):
581
"""Example using multiple AI frameworks with unified tracking"""
582
583
# LangChain for complex reasoning
584
langchain_handler = cl.AsyncLangchainCallbackHandler()
585
586
# OpenAI for quick responses (automatically tracked)
587
quick_response = await openai_client.chat.completions.create(
588
model="gpt-3.5-turbo",
589
messages=[{"role": "user", "content": f"Summarize: {message.content}"}],
590
max_tokens=50
591
)
592
593
# LlamaIndex for document queries (with callback handler)
594
index = cl.user_session.get("index")
595
if index:
596
llamaindex_handler = cl.LlamaIndexCallbackHandler()
597
query_engine = index.as_query_engine(
598
callback_manager=CallbackManager([llamaindex_handler])
599
)
600
doc_response = await query_engine.aquery(message.content)
601
602
# Mistral AI for creative tasks (automatically tracked)
603
creative_response = await mistral_client.chat(
604
model="mistral-large-latest",
605
messages=[{"role": "user", "content": f"Create a creative response to: {message.content}"}]
606
)
607
608
# All calls automatically appear as separate steps with proper attribution
609
final_response = f"""
610
**Quick Summary:** {quick_response.choices[0].message.content}
611
612
**Document Context:** {str(doc_response) if 'doc_response' in locals() else 'No documents loaded'}
613
614
**Creative Take:** {creative_response.choices[0].message.content}
615
"""
616
617
await cl.Message(final_response).send()
618
```
619
620
## Core Types
621
622
```python { .api }
623
from typing import List, Optional, Any, Dict
624
from enum import Enum
625
626
# LangChain integration types
627
LangchainComponent = str # Component name for filtering
628
629
# LlamaIndex integration types
630
class CBEventType(Enum):
631
"""LlamaIndex callback event types"""
632
CHUNKING = "chunking"
633
NODE_PARSING = "node_parsing"
634
EMBEDDING = "embedding"
635
LLM = "llm"
636
QUERY = "query"
637
RETRIEVE = "retrieve"
638
SYNTHESIZE = "synthesize"
639
640
# Generic integration types
641
ModelMetadata = Dict[str, Any] # Model configuration and metadata
642
TokenUsage = Dict[str, int] # Token usage statistics
643
GenerationInfo = Dict[str, Any] # Generation metadata and settings
644
```