[PYTHON/LANGCHAIN] AsyncCallbackHandler 클래스 : on_llm_start/on_llm_end 메소드를 재정의해서 커스텀 비동기 콜백 핸들러 만들기
■ AsyncCallbackHandler 클래스의 on_llm_start/on_llm_end 메소드를 재정의해서 커스텀 비동기 콜백 핸들러를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶
■ AsyncCallbackHandler 클래스의 on_llm_start/on_llm_end 메소드를 재정의해서 커스텀 비동기 콜백 핸들러를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶
■ BaseCallbackHandler 클래스의 on_llm_new_token 메소드를 재정의해서 커스텀 콜백 핸들러를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ ChatOpenAI 클래스의 생성자에서 callbacks 인자를 사용해 콜백 핸들러 리스트를 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶
■ RunnableSequence 클래스의 with_config 메소드에서 callbacks 인자를 사용해 콜백 핸들러 리스트를 설정하는 방법을 보여준다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
from dotenv import load_dotenv from langchain_core.callbacks import BaseCallbackHandler from typing import Dict from typing import Any from typing import List from langchain_core.messages import BaseMessage from langchain_core.outputs import LLMResult from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI load_dotenv() class CustomCallbackHandler(BaseCallbackHandler): def on_chat_model_start(self, serializedDictionary : Dict[str, Any], messageListList : List[List[BaseMessage]], **keywordArgumentDictionary) -> None: print("on_chat_model_start") print() def on_llm_end(self, result : LLMResult, **keywordArgumentDictionary) -> None: print(f"on_llm_end : {result}") print() def on_chain_start(self, serializedDictionary: Dict[str, Any], inputDictionary : Dict[str, Any], **keywordArgumentDictionary) -> None: if serializedDictionary: print(f"on_chain_start : {serializedDictionary.get("name")}") else: print(f"on_chain_start : {serializedDictionary}") print() def on_chain_end(self, outputDictionary : Dict[str, Any], **keywordArgumentDictionary) -> None: print(f"on_chain_end : {outputDictionary}") print() chatPromptTemplate = ChatPromptTemplate.from_template("What is 1 + {number}?") chatOpenAI = ChatOpenAI(model = "gpt-4o") runnableSequence = chatPromptTemplate | chatOpenAI callBackHandlerList = [CustomCallbackHandler()] runnableBinding = runnableSequence.with_config(callbacks = callBackHandlerList) responseAIMessage = runnableBinding.invoke({"number" : "2"}) print(responseAIMessage) """ on_chain_start : None on_chain_start : ChatPromptTemplate on_chain_end : messages=[HumanMessage(content='What is 1 + 2?', additional_kwargs={}, response_metadata={})] on_chat_model_start on_llm_end : generations=[[ChatGeneration(text='1 + 2 equals 3.', generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content='1 + 2 equals 3.', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 15, 'total_tokens': 23, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_831e067d82', 'finish_reason': 'stop', 'logprobs': None}, id='run-a0d0dff3-4469-49a3-96ad-41ed409bf28d-0', usage_metadata={'input_tokens': 15, 'output_tokens': 8, 'total_tokens': 23, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}))]] llm_output={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 15, 'total_tokens': 23, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_831e067d82'} run=None type='LLMResult' on_chain_end : content='1 + 2 equals 3.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 15, 'total_tokens': 23, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_831e067d82', 'finish_reason': 'stop', 'logprobs': None} id='run-a0d0dff3-4469-49a3-96ad-41ed409bf28d-0' usage_metadata={'input_tokens': 15, 'output_tokens': 8, 'total_tokens': 23, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}} content='1 + 2 equals 3.' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 15, 'total_tokens': 23, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_831e067d82', 'finish_reason': 'stop', 'logprobs': None} id='run-a0d0dff3-4469-49a3-96ad-41ed409bf28d-0' usage_metadata={'input_tokens': 15, 'output_tokens': 8, 'total_tokens': 23, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}} """ |
▶ requirements.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
aiohappyeyeballs==2.4.3 aiohttp==3.11.6 aiosignal==1.3.1 annotated-types==0.7.0 anyio==4.6.2.post1 attrs==24.2.0 certifi==2024.8.30 charset-normalizer==3.4.0 colorama==0.4.6 distro==1.9.0 frozenlist==1.5.0 greenlet==3.1.1 h11==0.14.0 httpcore==1.0.7 httpx==0.27.2 idna==3.10 jiter==0.7.1 jsonpatch==1.33 jsonpointer==3.0.0 langchain==0.3.7 langchain-core==0.3.19 langchain-openai==0.2.9 langchain-text-splitters==0.3.2 langsmith==0.1.143 multidict==6.1.0 numpy==1.26.4 openai==1.54.5 orjson==3.10.11 packaging==24.2 propcache==0.2.0 pydantic==2.9.2 pydantic_core==2.23.4 python-dotenv==1.0.1 PyYAML==6.0.2 regex==2024.11.6 requests==2.32.3 requests-toolbelt==1.0.0 sniffio==1.3.1 SQLAlchemy==2.0.36 tenacity==9.0.0 tiktoken==0.8.0 tqdm==4.67.0 typing_extensions==4.12.2 urllib3==2.2.3 yarl==1.17.2 |
※ pip
■ RunnableSequence 클래스의 invoke 메소드에서 config 인자를 사용해 콜백 핸들러를 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶
■ BaseCallbackHandler 클래스를 사용해 커스텀 콜백 핸들러를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
from dotenv import load_dotenv from langchain_core.callbacks import BaseCallbackHandler from typing import Dict from typing import Any from typing import List from langchain_core.messages import BaseMessage from langchain_core.outputs import LLMResult from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI load_dotenv() class CustomCallbackHandler(BaseCallbackHandler): def on_chat_model_start(self, serializedDictionary : Dict[str, Any], messageListList : List[List[BaseMessage]], **keywordArgumentDictionary) -> None: print("on_chat_model_start") print() def on_llm_end(self, result : LLMResult, **keywordArgumentDictionary) -> None: print(f"on_llm_end : {result}") print() def on_chain_start(self, serializedDictionary : Dict[str, Any], inputDictionary : Dict[str, Any], **keywordArgumentDictionary) -> None: if serializedDictionary: print(f"on_chain_start : {serializedDictionary.get("name")}") else: print(f"on_chain_start : {serializedDictionary}") print() def on_chain_end(self, outputDictionary : Dict[str, Any], **keywordArgumentDictionary) -> None: print(f"on_chain_end : {outputDictionary}") print() chatPromptTemplate = ChatPromptTemplate.from_template("What is 1 + {number}?") chatOpenAI = ChatOpenAI(model = "gpt-4o") runnableSequence = chatPromptTemplate | chatOpenAI callBackHandlerList = [CustomCallbackHandler()] responseAIMessage = runnableSequence.invoke({"number" : "2"}, config = {"callbacks" : callBackHandlerList}) print("-" * 100) print(responseAIMessage) |
▶
■ create_react_agent 함수의 state_modifier 인자를 사용해 장기 실행 에이전트의 중간 단계를 제거하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다.
■ AgentExecutor 클래스의 생성자에서 trim_intermediate_steps 인자를 사용해 장기 실행 에이전트의 중간 단계를 제거하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에
■ AgentExecutor 클래스의 생성자에서 early_stopping_method/max_iterations 인자를 사용해 반복 제한/시간 제한 중단 문자열을 반환하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에
■ CompiledStateGraph 클래스에서 asyncio 패키지의 create_task/wait_for 함수를 사용해 최대 실행 시간을 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다.
■ CompiledStateGraph 클래스의 step_timeout 속성을 사용해 최대 실행 시간을 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ AgentExecutor 클래스의 생성자에서 max_execution_time 인자를 사용해 최대 실행 시간을 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶
■ CompiledStateGraph 클래스의 stream 메소드에서 재귀 제한 수를 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langgraph.prebuilt import create_react_agent from langgraph.errors import GraphRecursionError load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") @tool def magicFunction(input : int) -> int: """Applies a magic function to an input.""" return input + 2 toolList = [magicFunction] query = "what is the value of magicFunction(3)?" RECURSION_LIMIT_COUNT = 2 * 3 + 1 compiledStateGraph = create_react_agent(chatOpenAI, tools = toolList) try: for addableValuesDict in compiledStateGraph.stream( {"messages" : [("human", query)]}, {"recursion_limit" : RECURSION_LIMIT_COUNT}, stream_mode = "values" ): print(addableValuesDict["messages"][-1]) except GraphRecursionError: print({"input" : query, "output" : "Agent stopped due to max iterations."}) |
■ AgentExecutor 클래스의 생성자에서 max_iterations 인자를 사용해 사용자 지정 반복 횟수 초과 실행시 중단하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env
■ AgentExecutor 클래스의 생성자에서 return_intermediate_steps 인자를 사용해 중단 단계를 반환하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ AgentExecutor 클래스의 stream 메소드를 사용해 질의 응답하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain_core.prompts import ChatPromptTemplate from langchain.agents import create_tool_calling_agent from langchain.agents import AgentExecutor load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") chatPromptTemplate = ChatPromptTemplate.from_messages( [ ("system" , "You are a helpful assistant."), ("human" , "{input}" ), ("placeholder", "{agent_scratchpad}" ) ] ) @tool def magicFunction(input : int) -> int: """Applies a magic function to an input.""" return input + 2 toolList = [magicFunction] runnableSequence = create_tool_calling_agent(chatOpenAI, toolList, prompt = chatPromptTemplate) agentExecutor = AgentExecutor(agent = runnableSequence, tools = toolList) query = "what is the value of magic_function(3)?" for addableDict in agentExecutor.stream({"input" : query}): print(addableDict) print("-" * 100) """ {'actions': [ToolAgentAction(tool='magic_function', tool_input={'input': 3}, log="\nInvoking: `magic_function` with `{'input': 3}`\n\n\n", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'function': {'arguments': '{"input":3}', 'name': 'magic_function'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b'}, id='run-15ad5b62-46c6-411d-b7f6-fcee0f04d6cd', tool_calls=[{'name': 'magic_function', 'args': {'input': 3}, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'type': 'tool_call'}], tool_call_chunks=[{'name': 'magic_function', 'args': '{"input":3}', 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'index': 0, 'type': 'tool_call_chunk'}])], tool_call_id='call_7iH5SstP0NB75GGRzulZZ53J')], 'messages': [AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'function': {'arguments': '{"input":3}', 'name': 'magic_function'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b'}, id='run-15ad5b62-46c6-411d-b7f6-fcee0f04d6cd', tool_calls=[{'name': 'magic_function', 'args': {'input': 3}, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'type': 'tool_call'}], tool_call_chunks=[{'name': 'magic_function', 'args': '{"input":3}', 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'index': 0, 'type': 'tool_call_chunk'}])]} {'steps': [AgentStep(action=ToolAgentAction(tool='magic_function', tool_input={'input': 3}, log="\nInvoking: `magic_function` with `{'input': 3}`\n\n\n", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'function': {'arguments': '{"input":3}', 'name': 'magic_function'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b'}, id='run-15ad5b62-46c6-411d-b7f6-fcee0f04d6cd', tool_calls=[{'name': 'magic_function', 'args': {'input': 3}, 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'type': 'tool_call'}], tool_call_chunks=[{'name': 'magic_function', 'args': '{"input":3}', 'id': 'call_7iH5SstP0NB75GGRzulZZ53J', 'index': 0, 'type': 'tool_call_chunk'}])], tool_call_id='call_7iH5SstP0NB75GGRzulZZ53J'), observation=5)], 'messages': [FunctionMessage(content='5', additional_kwargs={}, response_metadata={}, name='magic_function')]} {'output': 'The value of `magic_function(3)` is 5.', 'messages': [AIMessage(content='The value of `magic_function(3)` is 5.', additional_kwargs={}, response_metadata={})]} (env) king@cosmos:~/testproject$ python main.py <class 'langchain_core.runnables.utils.AddableDict'> (env) king@cosmos:~/testproject$ python main.py {'actions': [ToolAgentAction(tool='magicFunction', tool_input={'input': 3}, log="\nInvoking: `magicFunction` with `{'input': 3}`\n\n\n", message_log=[AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'function': {'arguments': '{"input":3}', 'name': 'magicFunction'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b'}, id='run-e8b2e03f-f3a8-4b68-90ab-5dcfbb35659e', tool_calls=[{'name': 'magicFunction', 'args': {'input': 3}, 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'type': 'tool_call'}], tool_call_chunks=[{'name': 'magicFunction', 'args': '{"input":3}', 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'index': 0, 'type': 'tool_call_chunk'}])], tool_call_id='call_Qv8SUJFIEtg02siem3SE7Nxj')], 'messages': [AIMessageChunk(content='', additional_kwargs={'tool_calls': [{'index': 0, 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'function': {'arguments': '{"input":3}', 'name': 'magicFunction'}, 'type': 'function'}]}, response_metadata={'finish_reason': 'tool_calls', 'model_name': 'gpt-4o-2024-08-06', 'system_fingerprint': 'fp_6b68a8204b'}, id='run-e8b2e03f-f3a8-4b68-90ab-5dcfbb35659e', tool_calls=[{'name': 'magicFunction', 'args': {'input': 3}, 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'type': 'tool_call'}], tool_call_chunks=[{'name': 'magicFunction', 'args': '{"input":3}', 'id': 'call_Qv8SUJFIEtg02siem3SE7Nxj', 'index': 0, 'type': 'tool_call_chunk'}])]} |
{'steps':
■ create_react_agent 함수의 checkpointer 인자에서 MemorySaver 객체를 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain_core.messages import SystemMessage from langgraph.checkpoint.memory import MemorySaver # 인 메모리 체크 포인터 from langgraph.prebuilt import create_react_agent load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") @tool def magicFunction(input : int) -> int: """Applies a magic function to an input.""" return input + 2 toolList = [magicFunction] systemMessage = SystemMessage(content = "You are a helpful assistant. Respond only in Korean.") memorySaver = MemorySaver() compiledStateGraph = create_react_agent( chatOpenAI, toolList, state_modifier = systemMessage, checkpointer = memorySaver ) configurationDictionary = {"configurable" : {"thread_id" : "thread1"}} addableValuesDict1 = compiledStateGraph.invoke( {"messages" : [("user", "Hi, I'm polly! What's the output of magic_function of 3?")]}, configurationDictionary, ) print(addableValuesDict1["messages"][-1].content) print("-" * 100) addableValuesDict2 = compiledStateGraph.invoke( {"messages" : [("user", "Remember my name?")]}, configurationDictionary ) print(addableValuesDict2["messages"][-1].content) print("-" * 100) addableValuesDict3 = compiledStateGraph.invoke( {"messages" : [("user", "what was that output again?")]}, configurationDictionary ) print(addableValuesDict3["messages"][-1].content) """ 매직 함수에 입력값 3을 넣으면 출력값은 5입니다. |
당신의
■ RunnableWithMessageHistory 클래스의 invoke 메소드를 사용해 채팅하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.tools import tool from langchain_core.prompts import ChatPromptTemplate from langchain.agents import create_tool_calling_agent from langchain.agents import AgentExecutor from langchain_core.chat_history import InMemoryChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") @tool def magicFunction(input : int) -> int: """Applies a magic function to an input.""" return input + 2 toolList = [magicFunction] chatPromptTemplate = ChatPromptTemplate.from_messages( [ ("system" , "You are a helpful assistant."), ("placeholder", "{chat_history}" ), ("human" , "{input}" ), ("placeholder", "{agent_scratchpad}" ) ] ) runnableSequence = create_tool_calling_agent(chatOpenAI, toolList, chatPromptTemplate) agentExecutor = AgentExecutor(agent = runnableSequence, tools = toolList) inMemoryChatMessageHistory = InMemoryChatMessageHistory(session_id = "test-session") runnableWithMessageHistory = RunnableWithMessageHistory( agentExecutor, lambda session_id : inMemoryChatMessageHistory, input_messages_key = "input", history_messages_key = "chat_history" ) configurationDictionary = {"configurable" : {"session_id" : "test-session"}} responseDictionary1 = runnableWithMessageHistory.invoke({"input" : "Hi, I'm polly! What's the output of magic_function of 3?"}, configurationDictionary) outputString1 = responseDictionary1["output"] print(outputString1) print("-" * 100) responseDictionary2 = runnableWithMessageHistory.invoke({"input" : "Remember my name?"}, configurationDictionary) outputString2 = responseDictionary2["output"] print(outputString2) print("-" * 100) responseDictionary3 = runnableWithMessageHistory.invoke({"input": "what was that output again?"}, configurationDictionary) outputString3 = responseDictionary3["output"] print(outputString3) """ Hello Polly! The output of the magic function for the input 3 is 5. |
Yes, you
■ RunnableWithMessageHistory 클래스의 생성자에서 input_messages_key/history_messages_key 인자를 사용해 RunnableWithMessageHistory 객체를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ RunnableWithMessageHistory 클래스의 invoke 메소드를 사용해 채팅하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
from dotenv import load_dotenv from langchain_community.tools.tavily_search import TavilySearchResults from langchain_community.document_loaders import WebBaseLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import FAISS from langchain.tools.retriever import create_retriever_tool from langchain_openai import ChatOpenAI from langchain import hub from langchain.agents import create_tool_calling_agent from langchain.agents import AgentExecutor from langchain_core.chat_history import BaseChatMessageHistory from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") tavilySearchResults = TavilySearchResults(max_results = 2) webBaseLoader = WebBaseLoader("https://docs.smith.langchain.com/overview") documentList = webBaseLoader.load() recursiveCharacterTextSplitter = RecursiveCharacterTextSplitter(chunk_size = 1000, chunk_overlap = 200) splitDocumentList = recursiveCharacterTextSplitter.split_documents(documentList) openAIEmbeddings = OpenAIEmbeddings() faiss = FAISS.from_documents(splitDocumentList, openAIEmbeddings) vectorStoreRetriever = faiss.as_retriever() vectorStoreRetrieverTool = create_retriever_tool( vectorStoreRetriever, "langsmith_search", "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!", ) toolList = [tavilySearchResults, vectorStoreRetrieverTool] chatPromptTemplate = hub.pull("hwchase17/openai-functions-agent") runnableSequence = create_tool_calling_agent(chatOpenAI, toolList, chatPromptTemplate) agentExecutor = AgentExecutor(agent = runnableSequence, tools = toolList) sessionIDDictionary = {} def getChatMessageHistory(sessionID : str) -> BaseChatMessageHistory: if sessionID not in sessionIDDictionary: sessionIDDictionary[sessionID] = ChatMessageHistory() return sessionIDDictionary[sessionID] runnableWithMessageHistory = RunnableWithMessageHistory( agentExecutor, getChatMessageHistory, input_messages_key = "input", history_messages_key = "chat_history", ) responseDictionary1 = runnableWithMessageHistory.invoke( {"input" : "hi! I'm bob"}, config = {"configurable" : {"session_id" : "<foo>"}} ) print(responseDictionary1) print("-" * 100) responseDictionary2 = runnableWithMessageHistory.invoke( {"input" : "what's my name?"}, config = {"configurable" : {"session_id" : "<foo>"}} ) print(responseDictionary2) print("-" * 100) """ {'input': "hi! I'm bob", 'chat_history': [], 'output': 'Hello Bob! How can I assist you today?'} |
{'input': "what's
■ RunnableWithMessageHistory 클래스의 생성자에서 input_messages_key/history_messages_key 인자를 사용해 RunnableWithMessageHistory 객체를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ AgentExecutor 클래스의 invoke 메소드 사용시 채팅 히스토리를 설정하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
from dotenv import load_dotenv from langchain_community.tools.tavily_search import TavilySearchResults from langchain_community.document_loaders import WebBaseLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import FAISS from langchain.tools.retriever import create_retriever_tool from langchain_openai import ChatOpenAI from langchain import hub from langchain.agents import create_tool_calling_agent from langchain.agents import AgentExecutor from langchain_core.messages import HumanMessage from langchain_core.messages import AIMessage load_dotenv() chatOpenAI = ChatOpenAI(model = "gpt-4o") tavilySearchResults = TavilySearchResults(max_results = 2) webBaseLoader = WebBaseLoader("https://docs.smith.langchain.com/overview") documentList = webBaseLoader.load() recursiveCharacterTextSplitter = RecursiveCharacterTextSplitter(chunk_size = 1000, chunk_overlap = 200) splitDocumentList = recursiveCharacterTextSplitter.split_documents(documentList) openAIEmbeddings = OpenAIEmbeddings() faiss = FAISS.from_documents(splitDocumentList, openAIEmbeddings) vectorStoreRetriever = faiss.as_retriever() vectorStoreRetrieverTool = create_retriever_tool( vectorStoreRetriever, "langsmith_search", "Search for information about LangSmith. For any questions about LangSmith, you must use this tool!", ) toolList = [tavilySearchResults, vectorStoreRetrieverTool] chatPromptTemplate = hub.pull("hwchase17/openai-functions-agent") runnableSequence = create_tool_calling_agent(chatOpenAI, toolList, chatPromptTemplate) agentExecutor = AgentExecutor(agent = runnableSequence, tools = toolList) responseDictionary = agentExecutor.invoke( { "chat_history" : [ HumanMessage(content = "hi! my name is bob"), AIMessage(content = "Hello Bob! How can I assist you today?") ], "input" : "what's my name?" } ) print(responseDictionary) """ { 'chat_history' : [ HumanMessage(content = 'hi! my name is bob', additional_kwargs = {}, response_metadata = {}), AIMessage(content = 'Hello Bob! How can I assist you today?', additional_kwargs = {}, response_metadata = {}) ], 'input' : "what's my name?", 'output' : 'Your name is Bob.' } """ |
■ AgentExecutor 클래스에서 OPENAI 모델과 TAVILY 도구를 사용해 질의 응답하는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ AgentExecutor 클래스의 생성자에서 agent/tools 인자를 사용해 AgentExecutor 객체를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에 정의한다. ▶ main.py
■ create_tool_calling_agent 함수를 사용해 모델, 도구 및 프롬프트 템플리트를 결합한 RunnableSequence 객체를 만드는 방법을 보여준다. ※ OPENAI_API_KEY 환경 변수 값은 .env 파일에