LangChain Chatbot with Tools
Simple stdin chatbot using LangChain with tool calling (OpenRouter).
Installation
1pip install langchain langchain-openai python-dotenv
Environment Setup
1# .env
2OPENROUTER_API_KEY=your_api_key_here
3OPENROUTER_MODEL=openai/gpt-4-turbo-preview
Basic Chatbot
1import os
2from dotenv import load_dotenv
3from langchain_openai import ChatOpenAI
4from langchain.schema import HumanMessage, AIMessage, SystemMessage
5
6load_dotenv()
7
8# Initialize OpenRouter LLM
9llm = ChatOpenAI(
10 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
11 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
12 openai_api_base="https://openrouter.ai/api/v1",
13 temperature=0.7,
14)
15
16def chat():
17 """Simple chat loop"""
18 messages = [
19 SystemMessage(content="You are a helpful assistant.")
20 ]
21
22 print("Chatbot ready! Type 'quit' to exit.\n")
23
24 while True:
25 user_input = input("You: ").strip()
26
27 if user_input.lower() in ['quit', 'exit', 'q']:
28 print("Goodbye!")
29 break
30
31 if not user_input:
32 continue
33
34 # Add user message
35 messages.append(HumanMessage(content=user_input))
36
37 # Get AI response
38 response = llm.invoke(messages)
39 messages.append(AIMessage(content=response.content))
40
41 print(f"AI: {response.content}\n")
42
43if __name__ == "__main__":
44 chat()
Chatbot with Tools
1import os
2from dotenv import load_dotenv
3from langchain_openai import ChatOpenAI
4from langchain.agents import AgentExecutor, create_tool_calling_agent
5from langchain.tools import tool
6from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
7from langchain.schema import HumanMessage, AIMessage
8
9load_dotenv()
10
11# Define tools
12@tool
13def add_numbers(a: float, b: float) -> float:
14 """Add two numbers together.
15
16 Args:
17 a: First number
18 b: Second number
19
20 Returns:
21 Sum of a and b
22 """
23 return a + b
24
25@tool
26def subtract_numbers(a: float, b: float) -> float:
27 """Subtract b from a.
28
29 Args:
30 a: First number
31 b: Second number
32
33 Returns:
34 Difference of a and b
35 """
36 return a - b
37
38@tool
39def multiply_numbers(a: float, b: float) -> float:
40 """Multiply two numbers together.
41
42 Args:
43 a: First number
44 b: Second number
45
46 Returns:
47 Product of a and b
48 """
49 return a * b
50
51@tool
52def divide_numbers(a: float, b: float) -> float:
53 """Divide a by b.
54
55 Args:
56 a: Numerator
57 b: Denominator
58
59 Returns:
60 Quotient of a divided by b
61 """
62 if b == 0:
63 raise ValueError("Cannot divide by zero")
64 return a / b
65
66# Initialize LLM
67llm = ChatOpenAI(
68 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
69 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
70 openai_api_base="https://openrouter.ai/api/v1",
71 temperature=0,
72)
73
74# Create tools list
75tools = [add_numbers, subtract_numbers, multiply_numbers, divide_numbers]
76
77# Create prompt
78prompt = ChatPromptTemplate.from_messages([
79 ("system", "You are a helpful math assistant. Use the provided tools to help users with calculations."),
80 MessagesPlaceholder(variable_name="chat_history"),
81 ("human", "{input}"),
82 MessagesPlaceholder(variable_name="agent_scratchpad"),
83])
84
85# Create agent
86agent = create_tool_calling_agent(llm, tools, prompt)
87agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
88
89def chat_with_tools():
90 """Chat loop with tool support"""
91 chat_history = []
92
93 print("Math Chatbot ready! Type 'quit' to exit.")
94 print("Try: 'What is 15 + 27?' or 'Calculate 100 divided by 4'\n")
95
96 while True:
97 user_input = input("You: ").strip()
98
99 if user_input.lower() in ['quit', 'exit', 'q']:
100 print("Goodbye!")
101 break
102
103 if not user_input:
104 continue
105
106 try:
107 # Invoke agent
108 response = agent_executor.invoke({
109 "input": user_input,
110 "chat_history": chat_history
111 })
112
113 # Update history
114 chat_history.append(HumanMessage(content=user_input))
115 chat_history.append(AIMessage(content=response["output"]))
116
117 print(f"AI: {response['output']}\n")
118
119 except Exception as e:
120 print(f"Error: {e}\n")
121
122if __name__ == "__main__":
123 chat_with_tools()
Advanced: Custom Tools
1import os
2from datetime import datetime
3from dotenv import load_dotenv
4from langchain_openai import ChatOpenAI
5from langchain.agents import AgentExecutor, create_tool_calling_agent
6from langchain.tools import tool
7from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
8from langchain.schema import HumanMessage, AIMessage
9
10load_dotenv()
11
12@tool
13def get_current_time() -> str:
14 """Get the current time.
15
16 Returns:
17 Current time as a formatted string
18 """
19 return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
20
21@tool
22def calculate_age(birth_year: int) -> int:
23 """Calculate age from birth year.
24
25 Args:
26 birth_year: Year of birth
27
28 Returns:
29 Current age
30 """
31 current_year = datetime.now().year
32 return current_year - birth_year
33
34@tool
35def convert_temperature(temp: float, from_unit: str, to_unit: str) -> float:
36 """Convert temperature between Celsius, Fahrenheit, and Kelvin.
37
38 Args:
39 temp: Temperature value
40 from_unit: Source unit (C, F, or K)
41 to_unit: Target unit (C, F, or K)
42
43 Returns:
44 Converted temperature
45 """
46 from_unit = from_unit.upper()
47 to_unit = to_unit.upper()
48
49 # Convert to Celsius first
50 if from_unit == 'F':
51 celsius = (temp - 32) * 5/9
52 elif from_unit == 'K':
53 celsius = temp - 273.15
54 else:
55 celsius = temp
56
57 # Convert from Celsius to target
58 if to_unit == 'F':
59 return celsius * 9/5 + 32
60 elif to_unit == 'K':
61 return celsius + 273.15
62 else:
63 return celsius
64
65@tool
66def calculate_compound_interest(
67 principal: float,
68 rate: float,
69 time: float,
70 compounds_per_year: int = 1
71) -> dict:
72 """Calculate compound interest.
73
74 Args:
75 principal: Initial amount
76 rate: Annual interest rate (as percentage, e.g., 5 for 5%)
77 time: Time period in years
78 compounds_per_year: Number of times interest is compounded per year
79
80 Returns:
81 Dictionary with final amount and interest earned
82 """
83 rate_decimal = rate / 100
84 amount = principal * (1 + rate_decimal / compounds_per_year) ** (compounds_per_year * time)
85 interest = amount - principal
86
87 return {
88 "final_amount": round(amount, 2),
89 "interest_earned": round(interest, 2),
90 "principal": principal,
91 "rate": rate,
92 "time": time
93 }
94
95# Initialize LLM
96llm = ChatOpenAI(
97 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
98 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
99 openai_api_base="https://openrouter.ai/api/v1",
100 temperature=0,
101)
102
103# Create tools list
104tools = [
105 get_current_time,
106 calculate_age,
107 convert_temperature,
108 calculate_compound_interest
109]
110
111# Create prompt
112prompt = ChatPromptTemplate.from_messages([
113 ("system", """You are a helpful assistant with access to various tools.
114 Use the tools when needed to provide accurate information.
115 Always explain your calculations and reasoning."""),
116 MessagesPlaceholder(variable_name="chat_history"),
117 ("human", "{input}"),
118 MessagesPlaceholder(variable_name="agent_scratchpad"),
119])
120
121# Create agent
122agent = create_tool_calling_agent(llm, tools, prompt)
123agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
124
125def advanced_chat():
126 """Advanced chat with multiple tools"""
127 chat_history = []
128
129 print("Advanced Chatbot ready! Type 'quit' to exit.")
130 print("Available capabilities:")
131 print("- Get current time")
132 print("- Calculate age from birth year")
133 print("- Convert temperatures")
134 print("- Calculate compound interest")
135 print()
136
137 while True:
138 user_input = input("You: ").strip()
139
140 if user_input.lower() in ['quit', 'exit', 'q']:
141 print("Goodbye!")
142 break
143
144 if not user_input:
145 continue
146
147 try:
148 response = agent_executor.invoke({
149 "input": user_input,
150 "chat_history": chat_history
151 })
152
153 chat_history.append(HumanMessage(content=user_input))
154 chat_history.append(AIMessage(content=response["output"]))
155
156 print(f"AI: {response['output']}\n")
157
158 except Exception as e:
159 print(f"Error: {e}\n")
160
161if __name__ == "__main__":
162 advanced_chat()
With Memory
1import os
2from dotenv import load_dotenv
3from langchain_openai import ChatOpenAI
4from langchain.agents import AgentExecutor, create_tool_calling_agent
5from langchain.tools import tool
6from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
7from langchain.memory import ConversationBufferMemory
8
9load_dotenv()
10
11@tool
12def add_numbers(a: float, b: float) -> float:
13 """Add two numbers together."""
14 return a + b
15
16llm = ChatOpenAI(
17 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
18 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
19 openai_api_base="https://openrouter.ai/api/v1",
20 temperature=0,
21)
22
23tools = [add_numbers]
24
25# Memory
26memory = ConversationBufferMemory(
27 memory_key="chat_history",
28 return_messages=True
29)
30
31prompt = ChatPromptTemplate.from_messages([
32 ("system", "You are a helpful assistant. Remember the conversation context."),
33 MessagesPlaceholder(variable_name="chat_history"),
34 ("human", "{input}"),
35 MessagesPlaceholder(variable_name="agent_scratchpad"),
36])
37
38agent = create_tool_calling_agent(llm, tools, prompt)
39agent_executor = AgentExecutor(
40 agent=agent,
41 tools=tools,
42 memory=memory,
43 verbose=True
44)
45
46def chat_with_memory():
47 """Chat with conversation memory"""
48 print("Chatbot with memory ready! Type 'quit' to exit.\n")
49
50 while True:
51 user_input = input("You: ").strip()
52
53 if user_input.lower() in ['quit', 'exit', 'q']:
54 print("Goodbye!")
55 break
56
57 if not user_input:
58 continue
59
60 try:
61 response = agent_executor.invoke({"input": user_input})
62 print(f"AI: {response['output']}\n")
63 except Exception as e:
64 print(f"Error: {e}\n")
65
66if __name__ == "__main__":
67 chat_with_memory()
Streaming Responses
1import os
2from dotenv import load_dotenv
3from langchain_openai import ChatOpenAI
4from langchain.schema import HumanMessage, SystemMessage
5
6load_dotenv()
7
8llm = ChatOpenAI(
9 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
10 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
11 openai_api_base="https://openrouter.ai/api/v1",
12 streaming=True,
13 temperature=0.7,
14)
15
16def chat_streaming():
17 """Chat with streaming responses"""
18 messages = [SystemMessage(content="You are a helpful assistant.")]
19
20 print("Streaming Chatbot ready! Type 'quit' to exit.\n")
21
22 while True:
23 user_input = input("You: ").strip()
24
25 if user_input.lower() in ['quit', 'exit', 'q']:
26 print("Goodbye!")
27 break
28
29 if not user_input:
30 continue
31
32 messages.append(HumanMessage(content=user_input))
33
34 print("AI: ", end="", flush=True)
35 full_response = ""
36
37 for chunk in llm.stream(messages):
38 content = chunk.content
39 print(content, end="", flush=True)
40 full_response += content
41
42 print("\n")
43 messages.append(AIMessage(content=full_response))
44
45if __name__ == "__main__":
46 chat_streaming()
Complete Example Script
1#!/usr/bin/env python3
2"""
3LangChain Chatbot with OpenRouter
4Usage: python chatbot.py
5"""
6
7import os
8import sys
9from dotenv import load_dotenv
10from langchain_openai import ChatOpenAI
11from langchain.agents import AgentExecutor, create_tool_calling_agent
12from langchain.tools import tool
13from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
14from langchain.schema import HumanMessage, AIMessage
15
16load_dotenv()
17
18# Validate environment
19if not os.getenv("OPENROUTER_API_KEY"):
20 print("Error: OPENROUTER_API_KEY not set in .env file")
21 sys.exit(1)
22
23# Tools
24@tool
25def add(a: float, b: float) -> float:
26 """Add two numbers."""
27 return a + b
28
29@tool
30def subtract(a: float, b: float) -> float:
31 """Subtract b from a."""
32 return a - b
33
34@tool
35def multiply(a: float, b: float) -> float:
36 """Multiply two numbers."""
37 return a * b
38
39@tool
40def divide(a: float, b: float) -> float:
41 """Divide a by b."""
42 if b == 0:
43 raise ValueError("Cannot divide by zero")
44 return a / b
45
46# Setup
47llm = ChatOpenAI(
48 model=os.getenv("OPENROUTER_MODEL", "openai/gpt-4-turbo-preview"),
49 openai_api_key=os.getenv("OPENROUTER_API_KEY"),
50 openai_api_base="https://openrouter.ai/api/v1",
51 temperature=0,
52)
53
54tools = [add, subtract, multiply, divide]
55
56prompt = ChatPromptTemplate.from_messages([
57 ("system", "You are a helpful math assistant. Use tools for calculations."),
58 MessagesPlaceholder(variable_name="chat_history"),
59 ("human", "{input}"),
60 MessagesPlaceholder(variable_name="agent_scratchpad"),
61])
62
63agent = create_tool_calling_agent(llm, tools, prompt)
64agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=False)
65
66def main():
67 """Main chat loop"""
68 chat_history = []
69
70 print("🤖 Math Chatbot (OpenRouter)")
71 print("=" * 40)
72 print("Commands: quit, exit, q")
73 print("Example: 'What is 15 + 27?'")
74 print("=" * 40)
75 print()
76
77 while True:
78 try:
79 user_input = input("You: ").strip()
80
81 if user_input.lower() in ['quit', 'exit', 'q']:
82 print("👋 Goodbye!")
83 break
84
85 if not user_input:
86 continue
87
88 response = agent_executor.invoke({
89 "input": user_input,
90 "chat_history": chat_history
91 })
92
93 chat_history.append(HumanMessage(content=user_input))
94 chat_history.append(AIMessage(content=response["output"]))
95
96 print(f"🤖: {response['output']}\n")
97
98 except KeyboardInterrupt:
99 print("\n👋 Goodbye!")
100 break
101 except Exception as e:
102 print(f"❌ Error: {e}\n")
103
104if __name__ == "__main__":
105 main()
Related Snippets
- Click CLI Framework
Building CLI applications with Click in Python - FastAPI with OpenAPI
FastAPI with automatic OpenAPI documentation using Pydantic models and … - Flask Essentials
Flask web framework essentials for building web applications and APIs. … - Function Timing Decorator
Decorator to measure function execution time - Pandas DataFrames Essential Patterns
Essential patterns for working with Pandas DataFrames: creation, manipulation, … - Pydantic Data Validation
Pydantic - Data validation using Python type hints. Installation 1pip install … - Python Dataclasses
Python dataclasses for clean, boilerplate-free data structures. Basic Usage … - Python Metaclasses
Python metaclasses with visual explanations using Mermaid diagrams. What are … - Python Virtual Environments
Managing Python virtual environments and dependencies - Random Forests in Depth
Comprehensive guide to Random Forests: theory, implementation, tuning, and … - Scikit-learn Common Patterns
Common patterns and workflows for scikit-learn: preprocessing, model training, …