Functions, Tools and Agents with LangChain

 

OpenAl function calling

  • OpenAl has fine-tuned the gpt-3.5-turbo-0613 and gpt-4-0613 models to:
    • Accept additional arguments through which users can pass in descriptions of functions.
    • If it is relevant, return the name of the function to use, along with a JSON object with the appropriate input parameters.

LangChain Expression Language (LCEL)

Notebook Code
notion image
notion image

Advantages of LCEL

  • Async, Batch, and Streaming Support
  • Fallbacks
  • Parallelism
    • LLM calls can be time-consuming!
    • Any components that can be run in parallel are!
  • Logging is built in.
 
 

OpenAl function calling in LangChain

Notebook Code
#!/usr/bin/env python # coding: utf-8 # # OpenAI Function Calling In LangChain # In[ ]: import os import openai from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) # read local .env file openai.api_key = os.environ['OPENAI_API_KEY'] # In[ ]: from typing import List from pydantic import BaseModel, Field # ## Pydantic Syntax # # Pydantic data classes are a blend of Python's data classes with the validation power of Pydantic. # # They offer a concise way to define data structures while ensuring that the data adheres to specified types and constraints. # # In standard python you would create a class like this: # In[ ]: class User: def __init__(self, name: str, age: int, email: str): self.name = name self.age = age self.email = email # In[ ]: foo = User(name="Joe",age=32, email="[email protected]") # In[ ]: foo.name # In[ ]: foo = User(name="Joe",age="bar", email="[email protected]") # In[ ]: foo.age # In[ ]: class pUser(BaseModel): name: str age: int email: str # In[ ]: foo_p = pUser(name="Jane", age=32, email="[email protected]") # In[ ]: foo_p.name # **Note**: The next cell is expected to fail. # In[ ]: foo_p = pUser(name="Jane", age="bar", email="[email protected]") # In[ ]: class Class(BaseModel): students: List[pUser] # In[ ]: obj = Class( students=[pUser(name="Jane", age=32, email="[email protected]")] ) # In[ ]: obj # ## Pydantic to OpenAI function definition # # In[ ]: class WeatherSearch(BaseModel): """Call this with an airport code to get the weather at that airport""" airport_code: str = Field(description="airport code to get weather for") # In[ ]: from langchain.utils.openai_functions import convert_pydantic_to_openai_function # In[ ]: weather_function = convert_pydantic_to_openai_function(WeatherSearch) # In[ ]: weather_function # In[ ]: class WeatherSearch1(BaseModel): airport_code: str = Field(description="airport code to get weather for") # **Note**: The next cell is expected to generate an error. # In[ ]: convert_pydantic_to_openai_function(WeatherSearch1) # In[ ]: class WeatherSearch2(BaseModel): """Call this with an airport code to get the weather at that airport""" airport_code: str # In[ ]: convert_pydantic_to_openai_function(WeatherSearch2) # In[ ]: from langchain.chat_models import ChatOpenAI # In[ ]: model = ChatOpenAI() # In[ ]: model.invoke("what is the weather in SF today?", functions=[weather_function]) # In[ ]: model_with_function = model.bind(functions=[weather_function]) # In[ ]: model_with_function.invoke("what is the weather in sf?") # ## Forcing it to use a function # # We can force the model to use a function # In[ ]: model_with_forced_function = model.bind(functions=[weather_function], function_call={"name":"WeatherSearch"}) # In[ ]: model_with_forced_function.invoke("what is the weather in sf?") # In[ ]: model_with_forced_function.invoke("hi!") # ## Using in a chain # # We can use this model bound to function in a chain as we normally would # In[ ]: from langchain.prompts import ChatPromptTemplate # In[ ]: prompt = ChatPromptTemplate.from_messages([ ("system", "You are a helpful assistant"), ("user", "{input}") ]) # In[ ]: chain = prompt | model_with_function # In[ ]: chain.invoke({"input": "what is the weather in sf?"}) # ## Using multiple functions # # Even better, we can pass a set of function and let the LLM decide which to use based on the question context. # In[ ]: class ArtistSearch(BaseModel): """Call this to get the names of songs by a particular artist""" artist_name: str = Field(description="name of artist to look up") n: int = Field(description="number of results") # In[ ]: functions = [ convert_pydantic_to_openai_function(WeatherSearch), convert_pydantic_to_openai_function(ArtistSearch), ] # In[ ]: model_with_functions = model.bind(functions=functions) # In[ ]: model_with_functions.invoke("what is the weather in sf?") # In[ ]: model_with_functions.invoke("what are three songs by taylor swift?") # In[ ]: model_with_functions.invoke("hi!") # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]: # In[ ]:

PyDantic

  • Pydantic is a 'data validation library' for python.
  • Works with python type annotations. But rather than static type checking, they are actively used at runtime for data validation and conversion.
  • Provides built-in methods to serialize/deserialize models to/from JSON, dictionaries, etc.
  • LangChain leverages Pydantic to create JSON Scheme describing function.
 

Tagging and extraction using OpenAl function calling

Notebook Code
import os import openai from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) # read local .env file openai.api_key = os.environ['OPENAI_API_KEY'] from typing import List from pydantic import BaseModel, Field from langchain.utils.openai_functions import convert_pydantic_to_openai_function class Tagging(BaseModel): """Tag the piece of text with particular info.""" sentiment: str = Field(description="sentiment of text, should be `pos`, `neg`, or `neutral`") language: str = Field(description="language of text (should be ISO 639-1 code)") convert_pydantic_to_openai_function(Tagging) from langchain.prompts import ChatPromptTemplate from langchain.chat_models import ChatOpenAI model = ChatOpenAI(temperature=0) tagging_functions = [convert_pydantic_to_openai_function(Tagging)] prompt = ChatPromptTemplate.from_messages([ ("system", "Think carefully, and then tag the text as instructed"), ("user", "{input}") ]) model_with_functions = model.bind( functions=tagging_functions, function_call={"name": "Tagging"} ) tagging_chain = prompt | model_with_functions tagging_chain.invoke({"input": "I love langchain"}) tagging_chain.invoke({"input": "non mi piace questo cibo"}) from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser tagging_chain = prompt | model_with_functions | JsonOutputFunctionsParser() tagging_chain.invoke({"input": "non mi piace questo cibo"}) ## Extraction # Extraction is similar to tagging, but used for extracting multiple pieces of information. from typing import Optional class Person(BaseModel): """Information about a person.""" name: str = Field(description="person's name") age: Optional[int] = Field(description="person's age") class Information(BaseModel): """Information to extract.""" people: List[Person] = Field(description="List of info about people") convert_pydantic_to_openai_function(Information) extraction_functions = [convert_pydantic_to_openai_function(Information)] extraction_model = model.bind(functions=extraction_functions, function_call={"name": "Information"}) extraction_model.invoke("Joe is 30, his mom is Martha") prompt = ChatPromptTemplate.from_messages([ ("system", "Extract the relevant information, if not explicitly provided do not guess. Extract partial info"), ("human", "{input}") ]) extraction_chain = prompt | extraction_model extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}) extraction_chain = prompt | extraction_model | JsonOutputFunctionsParser() extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}) from langchain.output_parsers.openai_functions import JsonKeyOutputFunctionsParser extraction_chain = prompt | extraction_model | JsonKeyOutputFunctionsParser(key_name="people") extraction_chain.invoke({"input": "Joe is 30, his mom is Martha"}) ## Doing it for real # We can apply tagging to a larger body of text. # For example, let's load this blog post and extract tag information from a sub-set of the text. from langchain.document_loaders import WebBaseLoader loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/") documents = loader.load() doc = documents[0] page_content = doc.page_content[:10000] print(page_content[:1000]) class Overview(BaseModel): """Overview of a section of text.""" summary: str = Field(description="Provide a concise summary of the content.") language: str = Field(description="Provide the language that the content is written in.") keywords: str = Field(description="Provide keywords related to the content.") overview_tagging_function = [ convert_pydantic_to_openai_function(Overview) ] tagging_model = model.bind( functions=overview_tagging_function, function_call={"name":"Overview"} ) tagging_chain = prompt | tagging_model | JsonOutputFunctionsParser() tagging_chain.invoke({"input": page_content}) class Paper(BaseModel): """Information about papers mentioned.""" title: str author: Optional[str] class Info(BaseModel): """Information to extract""" papers: List[Paper] paper_extraction_function = [ convert_pydantic_to_openai_function(Info) ] extraction_model = model.bind( functions=paper_extraction_function, function_call={"name":"Info"} ) extraction_chain = prompt | extraction_model | JsonKeyOutputFunctionsParser(key_name="papers") extraction_chain.invoke({"input": page_content}) template = """A article will be passed to you. Extract from it all papers that are mentioned by this article. Do not extract the name of the article itself. If no papers are mentioned that's fine - you don't need to extract any! Just return an empty list. Do not make up or guess ANY extra information. Only extract what exactly is in the text.""" prompt = ChatPromptTemplate.from_messages([ ("system", template), ("human", "{input}") ]) extraction_chain = prompt | extraction_model | JsonKeyOutputFunctionsParser(key_name="papers") extraction_chain.invoke({"input": page_content}) extraction_chain.invoke({"input": "hi"}) from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter(chunk_overlap=0) splits = text_splitter.split_text(doc.page_content) len(splits) def flatten(matrix): flat_list = [] for row in matrix: flat_list += row return flat_list flatten([[1, 2], [3, 4]]) print(splits[0]) from langchain.schema.runnable import RunnableLambda prep = RunnableLambda( lambda x: [{"input": doc} for doc in text_splitter.split_text(x)] ) prep.invoke("hi") chain = prep | extraction_chain.map() | flatten chain.invoke(doc.page_content)
notion image
notion image
 
 

Tools and Routing

Notebook Code
import os import openai from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) # read local .env file openai.api_key = os.environ['OPENAI_API_KEY'] from langchain.agents import tool @tool def search(query: str) -> str: """Search for weather online""" return "42f" from pydantic import BaseModel, Field class SearchInput(BaseModel): query: str = Field(description="Thing to search for") @tool(args_schema=SearchInput) def search(query: str) -> str: """Search for the weather online.""" return "42f" search.args search.run("sf") import requests from pydantic import BaseModel, Field import datetime # Define the input schema class OpenMeteoInput(BaseModel): latitude: float = Field(..., description="Latitude of the location to fetch weather data for") longitude: float = Field(..., description="Longitude of the location to fetch weather data for") @tool(args_schema=OpenMeteoInput) def get_current_temperature(latitude: float, longitude: float) -> dict: """Fetch current temperature for given coordinates.""" BASE_URL = "https://api.open-meteo.com/v1/forecast" # Parameters for the request params = { 'latitude': latitude, 'longitude': longitude, 'hourly': 'temperature_2m', 'forecast_days': 1, } # Make the request response = requests.get(BASE_URL, params=params) if response.status_code == 200: results = response.json() else: raise Exception(f"API Request failed with status code: {response.status_code}") current_utc_time = datetime.datetime.utcnow() time_list = [datetime.datetime.fromisoformat(time_str.replace('Z', '+00:00')) for time_str in results['hourly']['time']] temperature_list = results['hourly']['temperature_2m'] closest_time_index = min(range(len(time_list)), key=lambda i: abs(time_list[i] - current_utc_time)) current_temperature = temperature_list[closest_time_index] return f'The current temperature is {current_temperature}°C' get_current_temperature.name get_current_temperature.description get_current_temperature.args from langchain.tools.render import format_tool_to_openai_function format_tool_to_openai_function(get_current_temperature) ''' {'name': 'get_current_temperature', 'description': 'get_current_temperature(latitude: float, longitude: float) -> dict - Fetch current temperature for given coordinates.', 'parameters': {'title': 'OpenMeteoInput', 'type': 'object', 'properties': {'latitude': {'title': 'Latitude', 'description': 'Latitude of the location to fetch weather data for', 'type': 'number'}, 'longitude': {'title': 'Longitude', 'description': 'Longitude of the location to fetch weather data for', 'type': 'number'}}, 'required': ['latitude', 'longitude']}} ''' get_current_temperature({"latitude": 13, "longitude": 14}) # 'The current temperature is 27.6°C' import wikipedia @tool def search_wikipedia(query: str) -> str: """Run Wikipedia search and get page summaries.""" page_titles = wikipedia.search(query) summaries = [] for page_title in page_titles[: 3]: try: wiki_page = wikipedia.page(title=page_title, auto_suggest=False) summaries.append(f"Page: {page_title}\nSummary: {wiki_page.summary}") except ( self.wiki_client.exceptions.PageError, self.wiki_client.exceptions.DisambiguationError, ): pass if not summaries: return "No good Wikipedia Search Result was found" return "\n\n".join(summaries) search_wikipedia.name # search_wikipedia search_wikipedia.description # 'search_wikipedia(query: str) -> str - Run Wikipedia search and get page summaries.' format_tool_to_openai_function(search_wikipedia) ''' {'name': 'search_wikipedia', 'description': 'search_wikipedia(query: str) -> str - Run Wikipedia search and get page summaries.', 'parameters': {'title': 'search_wikipediaSchemaSchema', 'type': 'object', 'properties': {'query': {'title': 'Query', 'type': 'string'}}, 'required': ['query']}} ''' search_wikipedia({"query": "langchain"}) from langchain.chains.openai_functions.openapi import openapi_spec_to_openai_fn from langchain.utilities.openapi import OpenAPISpec text = """ { "openapi": "3.0.0", "info": { "version": "1.0.0", "title": "Swagger Petstore", "license": { "name": "MIT" } }, "servers": [ { "url": "http://petstore.swagger.io/v1" } ], "paths": { "/pets": { "get": { "summary": "List all pets", "operationId": "listPets", "tags": [ "pets" ], "parameters": [ { "name": "limit", "in": "query", "description": "How many items to return at one time (max 100)", "required": false, "schema": { "type": "integer", "maximum": 100, "format": "int32" } } ], "responses": { "200": { "description": "A paged array of pets", "headers": { "x-next": { "description": "A link to the next page of responses", "schema": { "type": "string" } } }, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pets" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } }, "post": { "summary": "Create a pet", "operationId": "createPets", "tags": [ "pets" ], "responses": { "201": { "description": "Null response" }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } }, "/pets/{petId}": { "get": { "summary": "Info for a specific pet", "operationId": "showPetById", "tags": [ "pets" ], "parameters": [ { "name": "petId", "in": "path", "required": true, "description": "The id of the pet to retrieve", "schema": { "type": "string" } } ], "responses": { "200": { "description": "Expected response to a valid request", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } }, "default": { "description": "unexpected error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } } } } } } }, "components": { "schemas": { "Pet": { "type": "object", "required": [ "id", "name" ], "properties": { "id": { "type": "integer", "format": "int64" }, "name": { "type": "string" }, "tag": { "type": "string" } } }, "Pets": { "type": "array", "maxItems": 100, "items": { "$ref": "#/components/schemas/Pet" } }, "Error": { "type": "object", "required": [ "code", "message" ], "properties": { "code": { "type": "integer", "format": "int32" }, "message": { "type": "string" } } } } } } """ spec = OpenAPISpec.from_text(text) pet_openai_functions, pet_callables = openapi_spec_to_openai_fn(spec) pet_openai_functions ''' [{'name': 'listPets', 'description': 'List all pets', 'parameters': {'type': 'object', 'properties': {'params': {'type': 'object', 'properties': {'limit': {'type': 'integer', 'maximum': 100.0, 'schema_format': 'int32', 'description': 'How many items to return at one time (max 100)'}}, 'required': []}}}}, {'name': 'createPets', 'description': 'Create a pet', 'parameters': {'type': 'object', 'properties': {}}}, {'name': 'showPetById', 'description': 'Info for a specific pet', 'parameters': {'type': 'object', 'properties': {'path_params': {'type': 'object', 'properties': {'petId': {'type': 'string', 'description': 'The id of the pet to retrieve'}}, 'required': ['petId']}}}}] ''' from langchain.chat_models import ChatOpenAI model = ChatOpenAI(temperature=0).bind(functions=pet_openai_functions) model.invoke("what are three pets names") # AIMessage(content='', additional_kwargs={'function_call': {'name': 'listPets', 'arguments': '{\n "params": {\n "limit": 3\n }\n}'}}) model.invoke("tell me about pet with id 42") # AIMessage(content='', additional_kwargs={'function_call': {'name': 'showPetById', 'arguments': '{\n "path_params": {\n "petId": "42"\n }\n}'}}) # Routing ''' In lesson 3, we show an example of function calling deciding between two candidate functions. Given our tools above, let's format these as OpenAI functions and show this same behavior. ''' functions = [ format_tool_to_openai_function(f) for f in [ search_wikipedia, get_current_temperature ] ] model = ChatOpenAI(temperature=0).bind(functions=functions) model.invoke("what is the weather in sf right now") ''' AIMessage(content='', additional_kwargs={'function_call': {'name': 'get_current_temperature', 'arguments': '{\n "latitude": 37.7749,\n "longitude": -122.4194\n}'}}) ''' model.invoke("what is langchain") # AIMessage(content='', additional_kwargs={'function_call': {'name': 'search_wikipedia', 'arguments': '{\n "query": "langchain"\n}'}}) from langchain.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_messages([ ("system", "You are helpful but sassy assistant"), ("user", "{input}"), ]) chain = prompt | model chain.invoke({"input": "what is the weather in sf right now"}) # AIMessage(content='', additional_kwargs={'function_call': {'name': 'get_current_temperature', 'arguments': '{\n "latitude": 37.7749,\n "longitude": -122.4194\n}'}}) from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser chain = prompt | model | OpenAIFunctionsAgentOutputParser() result = chain.invoke({"input": "what is the weather in sf right now"}) result.tool # get_current_temperature result.tool_input # {'latitude': 37.7749, 'longitude': -122.4194} result = chain.invoke({"input": "hi!"}) type(result) result.return_values # {'output': 'Hello! How can I assist you today?'} from langchain.schema.agent import AgentFinish def route(result): if isinstance(result, AgentFinish): return result.return_values['output'] else: tools = { "search_wikipedia": search_wikipedia, "get_current_temperature": get_current_temperature, } return tools[result.tool].run(result.tool_input) chain = prompt | model | OpenAIFunctionsAgentOutputParser() | route result = chain.invoke({"input": "What is the weather in san francisco right now?"}) result result = chain.invoke({"input": "What is langchain?"}) chain.invoke({"input": "hi!"})
notion image
 
 

Conversational Agent

Notebook Code
import os import openai from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) # read local .env file openai.api_key = os.environ['OPENAI_API_KEY'] from langchain.tools import tool import requests from pydantic import BaseModel, Field import datetime # Define the input schema class OpenMeteoInput(BaseModel): latitude: float = Field(..., description="Latitude of the location to fetch weather data for") longitude: float = Field(..., description="Longitude of the location to fetch weather data for") @tool(args_schema=OpenMeteoInput) def get_current_temperature(latitude: float, longitude: float) -> dict: """Fetch current temperature for given coordinates.""" BASE_URL = "https://api.open-meteo.com/v1/forecast" # Parameters for the request params = { 'latitude': latitude, 'longitude': longitude, 'hourly': 'temperature_2m', 'forecast_days': 1, } # Make the request response = requests.get(BASE_URL, params=params) if response.status_code == 200: results = response.json() else: raise Exception(f"API Request failed with status code: {response.status_code}") current_utc_time = datetime.datetime.utcnow() time_list = [datetime.datetime.fromisoformat(time_str.replace('Z', '+00:00')) for time_str in results['hourly']['time']] temperature_list = results['hourly']['temperature_2m'] closest_time_index = min(range(len(time_list)), key=lambda i: abs(time_list[i] - current_utc_time)) current_temperature = temperature_list[closest_time_index] return f'The current temperature is {current_temperature}°C' import wikipedia @tool def search_wikipedia(query: str) -> str: """Run Wikipedia search and get page summaries.""" page_titles = wikipedia.search(query) summaries = [] for page_title in page_titles[: 3]: try: wiki_page = wikipedia.page(title=page_title, auto_suggest=False) summaries.append(f"Page: {page_title}\nSummary: {wiki_page.summary}") except ( self.wiki_client.exceptions.PageError, self.wiki_client.exceptions.DisambiguationError, ): pass if not summaries: return "No good Wikipedia Search Result was found" return "\n\n".join(summaries) tools = [get_current_temperature, search_wikipedia] from langchain.chat_models import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain.tools.render import format_tool_to_openai_function from langchain.agents.output_parsers import OpenAIFunctionsAgentOutputParser functions = [format_tool_to_openai_function(f) for f in tools] model = ChatOpenAI(temperature=0).bind(functions=functions) prompt = ChatPromptTemplate.from_messages([ ("system", "You are helpful but sassy assistant"), ("user", "{input}"), ]) chain = prompt | model | OpenAIFunctionsAgentOutputParser() result = chain.invoke({"input": "what is the weather is sf?"}) result.tool # 'get_current_temperature' result.tool_input # {'latitude': 37.7749, 'longitude': -122.4194} from langchain.prompts import MessagesPlaceholder prompt = ChatPromptTemplate.from_messages([ ("system", "You are helpful but sassy assistant"), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad") ]) chain = prompt | model | OpenAIFunctionsAgentOutputParser() result1 = chain.invoke({ "input": "what is the weather is sf?", "agent_scratchpad": [] }) result1.tool # 'get_current_temperature' observation = get_current_temperature(result1.tool_input) # 'The current temperature is 9.4°C' type(result1) # langchain.schema.agent.AgentActionMessageLog from langchain.agents.format_scratchpad import format_to_openai_functions result1.message_log # [AIMessage(content='', additional_kwargs={'function_call': {'name': 'get_current_temperature', 'arguments': '{\n "latitude": 37.7749,\n "longitude": -122.4194\n}'}})] format_to_openai_functions([(result1, observation), ]) # [AIMessage(content='', additional_kwargs={'function_call': {'name': 'get_current_temperature', 'arguments': '{\n "latitude": 37.7749,\n "longitude": -122.4194\n}'}}), FunctionMessage(content='The current temperature is 9.4°C', name='get_current_temperature')] result2 = chain.invoke({ "input": "what is the weather is sf?", "agent_scratchpad": format_to_openai_functions([(result1, observation)]) }) from langchain.schema.agent import AgentFinish def run_agent(user_input): intermediate_steps = [] while True: result = chain.invoke({ "input": user_input, "agent_scratchpad": format_to_openai_functions(intermediate_steps) }) if isinstance(result, AgentFinish): return result tool = { "search_wikipedia": search_wikipedia, "get_current_temperature": get_current_temperature, }[result.tool] observation = tool.run(result.tool_input) intermediate_steps.append((result, observation)) from langchain.schema.runnable import RunnablePassthrough agent_chain = RunnablePassthrough.assign( agent_scratchpad= lambda x: format_to_openai_functions(x["intermediate_steps"]) ) | chain def run_agent(user_input): intermediate_steps = [] while True: result = agent_chain.invoke({ "input": user_input, "intermediate_steps": intermediate_steps }) if isinstance(result, AgentFinish): return result tool = { "search_wikipedia": search_wikipedia, "get_current_temperature": get_current_temperature, }[result.tool] observation = tool.run(result.tool_input) intermediate_steps.append((result, observation)) run_agent("what is the weather is sf?") run_agent("what is langchain?") from langchain.agents import AgentExecutor agent_executor = AgentExecutor(agent=agent_chain, tools=tools, verbose=True) agent_executor.invoke({"input": "what is langchain?"}) prompt = ChatPromptTemplate.from_messages([ ("system", "You are helpful but sassy assistant"), MessagesPlaceholder(variable_name="chat_history"), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad") ]) agent_chain = RunnablePassthrough.assign( agent_scratchpad= lambda x: format_to_openai_functions(x["intermediate_steps"]) ) | prompt | model | OpenAIFunctionsAgentOutputParser() from langchain.memory import ConversationBufferMemory memory = ConversationBufferMemory(return_messages=True,memory_key="chat_history") agent_executor = AgentExecutor(agent=agent_chain, tools=tools, verbose=True, memory=memory) agent_executor.invoke({"input": "my name is bob"}) agent_executor.invoke({"input": "whats my name"}) # Create a Chatbot @tool def create_your_own(query: str) -> str: """This function can do whatever you would like once you fill it in """ print(type(query)) return query[::-1] tools = [get_current_temperature, search_wikipedia, create_your_own] import panel as pn # GUI pn.extension() import panel as pn import param class cbfs(param.Parameterized): def __init__(self, tools, **params): super(cbfs, self).__init__( **params) self.panels = [] self.functions = [format_tool_to_openai_function(f) for f in tools] self.model = ChatOpenAI(temperature=0).bind(functions=self.functions) self.memory = ConversationBufferMemory(return_messages=True,memory_key="chat_history") self.prompt = ChatPromptTemplate.from_messages([ ("system", "You are helpful but sassy assistant"), MessagesPlaceholder(variable_name="chat_history"), ("user", "{input}"), MessagesPlaceholder(variable_name="agent_scratchpad") ]) self.chain = RunnablePassthrough.assign( agent_scratchpad = lambda x: format_to_openai_functions(x["intermediate_steps"]) ) | self.prompt | self.model | OpenAIFunctionsAgentOutputParser() self.qa = AgentExecutor(agent=self.chain, tools=tools, verbose=False, memory=self.memory) def convchain(self, query): if not query: return inp.value = '' result = self.qa.invoke({"input": query}) self.answer = result['output'] self.panels.extend([ pn.Row('User:', pn.pane.Markdown(query, width=450)), pn.Row('ChatBot:', pn.pane.Markdown(self.answer, width=450, styles={'background-color': '#F6F6F6'})) ]) return pn.WidgetBox(*self.panels, scroll=True) def clr_history(self,count=0): self.chat_history = [] return cb = cbfs(tools) inp = pn.widgets.TextInput( placeholder='Enter text here…') conversation = pn.bind(cb.convchain, inp) tab1 = pn.Column( pn.Row(inp), pn.layout.Divider(), pn.panel(conversation, loading_indicator=True, height=400), pn.layout.Divider(), ) dashboard = pn.Column( pn.Row(pn.pane.Markdown('# QnA_Bot')), pn.Tabs(('Conversation', tab1)) ) dashboard
 
notion image
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

⚠️Disclaimer: All the screenshots, materials, and other media documents used in this article are copyrighted to the original platform or authors.