11 | """
12 |
13 | print(data)
14 | """
15 | [Document(page_content='name: Neville Hardy\nage: 56\ncountry: Niue', metadata={'source': './csv_sample.csv', 'row': 0}), Document(page_content='name: Dacia Cohen\nage: 74\ncountry: Falkland Islands (Malvinas)', metadata={'source': './csv_sample.csv', 'row': 1}), Document(page_content='name: Kathey Daniel\nage: 10\ncountry: Slovenia', metadata={'source': './csv_sample.csv', 'row': 2}), Document(page_content='name: Mallie Welch\nage: 12\ncountry: Equatorial Guinea', metadata={'source': './csv_sample.csv', 'row': 3}), Document(page_content='name: Katia Bryant\nage: 14\ncountry: Ghana', metadata={'source': './csv_sample.csv', 'row': 4}), Document(page_content='name: Laurice Robertson\nage: 53\ncountry: Saudi Arabia', metadata={'source': './csv_sample.csv', 'row': 5}), Document(page_content='name: Minh Barrett\nage: 27\ncountry: French Southern Territories', metadata={'source': './csv_sample.csv', 'row': 6}), Document(page_content='name: Latashia Perez\nage: 52\ncountry: Finland', metadata={'source': './csv_sample.csv', 'row': 7}), Document(page_content='name: Elvina Ross\nage: 68\ncountry: New Zealand', metadata={'source': './csv_sample.csv', 'row': 8})]
16 | """
17 |
18 | print(data[0].page_content)
19 | """
20 | name: Neville Hardy
21 | age: 56
22 | country: Niue
23 | """
24 |
25 | print(data[0].metadata)
26 | """
27 | {'source': './csv_sample.csv', 'row': 0}
28 | """
29 |
30 | loader = CSVLoader(
31 | file_path='./csv_sample_no_header.csv',
32 | csv_args={
33 | 'delimiter': ',',
34 | 'quotechar': '"',
35 | 'fieldnames': ['name', 'age', 'country']
36 | })
37 |
38 | data = loader.load()
39 | print(data[1].page_content)
40 | """
41 | name: Dacia Cohen
42 | age: 74
43 | country: Falkland Islands (Malvinas)
44 | """
--------------------------------------------------------------------------------
/document_loaders/csv_sample.csv:
--------------------------------------------------------------------------------
1 | name,age,country
2 | Neville Hardy,56,Niue
3 | Dacia Cohen,74,Falkland Islands (Malvinas)
4 | Kathey Daniel,10,Slovenia
5 | Mallie Welch,12,Equatorial Guinea
6 | Katia Bryant,14,Ghana
7 | Laurice Robertson,53,Saudi Arabia
8 | Minh Barrett,27,French Southern Territories
9 | Latashia Perez,52,Finland
10 | Elvina Ross,68,New Zealand
--------------------------------------------------------------------------------
/document_loaders/csv_sample.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/document_loaders/csv_sample.pdf
--------------------------------------------------------------------------------
/document_loaders/csv_sample_no_header.csv:
--------------------------------------------------------------------------------
1 | Neville Hardy,56,Niue
2 | Dacia Cohen,74,Falkland Islands (Malvinas)
3 | Kathey Daniel,10,Slovenia
4 | Mallie Welch,12,Equatorial Guinea
5 | Katia Bryant,14,Ghana
6 | Laurice Robertson,53,Saudi Arabia
7 | Minh Barrett,27,French Southern Territories
8 | Latashia Perez,52,Finland
9 | Elvina Ross,68,New Zealand
--------------------------------------------------------------------------------
/document_loaders/facebook_chat.json:
--------------------------------------------------------------------------------
1 | {
2 | "image": {
3 | "creation_timestamp": 1675549016,
4 | "uri": "image_of_the_chat.jpg"
5 | },
6 | "is_still_participant": true,
7 | "joinable_mode": {
8 | "link": "",
9 | "mode": 1
10 | },
11 | "magic_words": [],
12 | "messages": [
13 | {
14 | "content": "Bye!",
15 | "sender_name": "User 2",
16 | "timestamp_ms": 1675597571851
17 | },
18 | {
19 | "content": "Oh no worries! Bye",
20 | "sender_name": "User 1",
21 | "timestamp_ms": 1675597435669
22 | },
23 | {
24 | "content": "No Im sorry it was my mistake, the blue one is not for sale",
25 | "sender_name": "User 2",
26 | "timestamp_ms": 1675596277579
27 | },
28 | {
29 | "content": "I thought you were selling the blue one!",
30 | "sender_name": "User 1",
31 | "timestamp_ms": 1675595140251
32 | },
33 | {
34 | "content": "Im not interested in this bag. Im interested in the blue one!",
35 | "sender_name": "User 1",
36 | "timestamp_ms": 1675595109305
37 | },
38 | {
39 | "content": "Here is $129",
40 | "sender_name": "User 2",
41 | "timestamp_ms": 1675595068468
42 | },
43 | {
44 | "photos": [
45 | {
46 | "creation_timestamp": 1675595059,
47 | "uri": "url_of_some_picture.jpg"
48 | }
49 | ],
50 | "sender_name": "User 2",
51 | "timestamp_ms": 1675595060730
52 | },
53 | {
54 | "content": "Online is at least $100",
55 | "sender_name": "User 2",
56 | "timestamp_ms": 1675595045152
57 | },
58 | {
59 | "content": "How much do you want?",
60 | "sender_name": "User 1",
61 | "timestamp_ms": 1675594799696
62 | },
63 | {
64 | "content": "Goodmorning! $50 is too low.",
65 | "sender_name": "User 2",
66 | "timestamp_ms": 1675577876645
67 | },
68 | {
69 | "content": "Hi! Im interested in your bag. Im offering $50. Let me know if you are interested. Thanks!",
70 | "sender_name": "User 1",
71 | "timestamp_ms": 1675549022673
72 | }
73 | ],
74 | "participants": [
75 | {
76 | "name": "User 1"
77 | },
78 | {
79 | "name": "User 2"
80 | }
81 | ],
82 | "thread_path": "inbox/User 1 and User 2 chat",
83 | "title": "User 1 and User 2 chat"
84 | }
85 |
--------------------------------------------------------------------------------
/document_loaders/html_loader.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_community.document_loaders import UnstructuredHTMLLoader
5 |
6 | # requires `pip install unstructured`
7 | loader = UnstructuredHTMLLoader("sample.html")
8 | data = loader.load()
9 | print(data)
10 | """
11 | [Document(page_content="Welcome to My Web Page\n\nThis is a simple HTML page. It's a great starting point for learning HTML.\n\nClick here to visit Example.com", metadata={'source': 'sample.html'})]
12 | """
13 |
14 | from langchain.document_loaders import BSHTMLLoader
15 |
16 | # requires `pip install beautifulsoup4 lxml`
17 | loader = BSHTMLLoader("sample.html")
18 | data = loader.load()
19 | print(data)
20 | """
21 | [Document(page_content="\n\nMy Simple Web Page\n\n\nWelcome to My Web Page\nThis is a simple HTML page. It's a great starting point for learning HTML.\nClick here to visit Example.com\n\n\n", metadata={'source': 'sample.html', 'title': 'My Simple Web Page'})]
22 | """
23 |
24 | print(data[0].page_content)
25 | """
26 |
27 |
28 | My Simple Web Page
29 |
30 |
31 | Welcome to My Web Page
32 | This is a simple HTML page. It's a great starting point for learning HTML.
33 | Click here to visit Example.com
34 |
35 |
36 |
37 | """
--------------------------------------------------------------------------------
/document_loaders/integration.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain_community.document_loaders import CSVLoader
6 | from langchain.prompts.chat import ChatPromptTemplate
7 |
8 | template = "You are a helpful assistant that extract the {column} given the data `{data}`"
9 | human_template = "What is the age of {name}"
10 |
11 | chat_prompt = ChatPromptTemplate.from_messages([
12 | ("system", template), # role
13 | ("human", human_template), # content
14 | ])
15 |
16 | loader = CSVLoader(file_path='./csv_sample.csv')
17 | data = loader.load()
18 |
19 | text_list = []
20 | for record in data:
21 | text_list.append(record.page_content)
22 |
23 | chat_prompt_output = chat_prompt.format_messages(
24 | column="age",
25 | data=("\n".join(text_list)),
26 | name="Minh Barrett")
27 | print(chat_prompt_output)
28 |
29 | chat_model = ChatOpenAI()
30 | print(chat_model.invoke(chat_prompt_output))
31 |
--------------------------------------------------------------------------------
/document_loaders/json_loader.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_community.document_loaders import JSONLoader
5 | import json
6 | from pathlib import Path
7 | from pprint import pprint
8 |
9 | # required `pip install jq`
10 | file_path='./facebook_chat.json'
11 | data = json.loads(Path(file_path).read_text())
12 | pprint(data)
13 | """
14 | {'image': {'creation_timestamp': 1675549016, 'uri': 'image_of_the_chat.jpg'},
15 | 'is_still_participant': True,
16 | 'joinable_mode': {'link': '', 'mode': 1},
17 | 'magic_words': [],
18 | 'messages': [{'content': 'Bye!',
19 | 'sender_name': 'User 2',
20 | 'timestamp_ms': 1675597571851},
21 | {'content': 'Oh no worries! Bye',
22 | 'sender_name': 'User 1',
23 | 'timestamp_ms': 1675597435669},
24 | {'content': 'No Im sorry it was my mistake, the blue one is not '
25 | 'for sale',
26 | 'sender_name': 'User 2',
27 | 'timestamp_ms': 1675596277579},
28 | {'content': 'I thought you were selling the blue one!',
29 | 'sender_name': 'User 1',
30 | 'timestamp_ms': 1675595140251},
31 | {'content': 'Im not interested in this bag. Im interested in the '
32 | 'blue one!',
33 | 'sender_name': 'User 1',
34 | 'timestamp_ms': 1675595109305},
35 | {'content': 'Here is $129',
36 | 'sender_name': 'User 2',
37 | 'timestamp_ms': 1675595068468},
38 | {'photos': [{'creation_timestamp': 1675595059,
39 | 'uri': 'url_of_some_picture.jpg'}],
40 | 'sender_name': 'User 2',
41 | 'timestamp_ms': 1675595060730},
42 | {'content': 'Online is at least $100',
43 | 'sender_name': 'User 2',
44 | 'timestamp_ms': 1675595045152},
45 | {'content': 'How much do you want?',
46 | 'sender_name': 'User 1',
47 | 'timestamp_ms': 1675594799696},
48 | {'content': 'Goodmorning! $50 is too low.',
49 | 'sender_name': 'User 2',
50 | 'timestamp_ms': 1675577876645},
51 | {'content': 'Hi! Im interested in your bag. Im offering $50. Let '
52 | 'me know if you are interested. Thanks!',
53 | 'sender_name': 'User 1',
54 | 'timestamp_ms': 1675549022673}],
55 | 'participants': [{'name': 'User 1'}, {'name': 'User 2'}],
56 | 'thread_path': 'inbox/User 1 and User 2 chat',
57 | 'title': 'User 1 and User 2 chat'}
58 | """
59 |
60 | loader = JSONLoader(
61 | file_path='./facebook_chat.json',
62 | jq_schema='.messages[].content',
63 | text_content=False)
64 |
65 | data = loader.load()
66 | pprint(data)
67 | """
68 | [Document(page_content='Bye!', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 1}),
69 | Document(page_content='Oh no worries! Bye', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 2}),
70 | Document(page_content='No Im sorry it was my mistake, the blue one is not for sale', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 3}),
71 | Document(page_content='I thought you were selling the blue one!', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 4}),
72 | Document(page_content='Im not interested in this bag. Im interested in the blue one!', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 5}),
73 | Document(page_content='Here is $129', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 6}),
74 | Document(page_content='', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 7}),
75 | Document(page_content='Online is at least $100', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 8}),
76 | Document(page_content='How much do you want?', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 9}),
77 | Document(page_content='Goodmorning! $50 is too low.', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 10}),
78 | Document(page_content='Hi! Im interested in your bag. Im offering $50. Let me know if you are interested. Thanks!', metadata={'source': '/Users/seungjoonlee/git/learn-langchain/document_loader/facebook_chat.json', 'seq_num': 11})]
79 | """
--------------------------------------------------------------------------------
/document_loaders/pdf_loader.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_community.document_loaders import PyPDFLoader
5 |
6 | # required `pip install pypdf`
7 | loader = PyPDFLoader("csv_sample.pdf")
8 | pages = loader.load_and_split()
9 |
10 | print(pages[0].page_content)
11 | """
12 | csv_sample
13 | Page 1nameagecountry
14 | Neville Hardy 56Niue
15 | Dacia Cohen 74Falkland Islands (Malvinas)
16 | Kathey Daniel 10Slovenia
17 | Mallie Welch 12Equatorial Guinea
18 | Katia Bryant 14Ghana
19 | Laurice Robertson 53Saudi Arabia
20 | Minh Barrett 27French Southern Territories
21 | Latashia Perez 52Finland
22 | Elvina Ross 68New Zealand
23 | """
24 |
--------------------------------------------------------------------------------
/document_loaders/sample.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | My Simple Web Page
5 |
6 |
7 | Welcome to My Web Page
8 | This is a simple HTML page. It's a great starting point for learning HTML.
9 | Click here to visit Example.com
10 |
11 |
12 |
--------------------------------------------------------------------------------
/document_transformers/code_splitters.py:
--------------------------------------------------------------------------------
1 | from langchain.text_splitter import (
2 | RecursiveCharacterTextSplitter,
3 | Language,
4 | )
5 |
6 | print([e.value for e in Language])
7 | """
8 | ['cpp', 'go', 'java', 'kotlin', 'js', 'ts', 'php', 'proto', 'python', 'rst', 'ruby', 'rust', 'scala', 'swift', 'markdown', 'latex', 'html', 'sol', 'csharp', 'cobol']
9 | """
10 |
11 | separators = RecursiveCharacterTextSplitter.get_separators_for_language(Language.PYTHON)
12 | print(separators)
13 | """
14 | ['\nclass ', '\ndef ', '\n\tdef ', '\n\n', '\n', ' ', '']
15 | """
16 |
17 | PYTHON_CODE = """
18 | def hello_world():
19 | print("Hello, World!")
20 |
21 | # Call the function
22 | hello_world()
23 | """
24 | python_splitter = RecursiveCharacterTextSplitter.from_language(
25 | language=Language.PYTHON, chunk_size=50, chunk_overlap=0
26 | )
27 | python_docs = python_splitter.create_documents([PYTHON_CODE])
28 | print(python_docs)
29 | """
30 | [Document(page_content='def hello_world():\n print("Hello, World!")'), Document(page_content='# Call the function\nhello_world()')]
31 | """
--------------------------------------------------------------------------------
/document_transformers/split_by_token.py:
--------------------------------------------------------------------------------
1 | from langchain.text_splitter import CharacterTextSplitter
2 |
3 |
4 | # required `pip install tiktoken`
5 | with open('./state_of_the_union.txt') as f:
6 | state_of_the_union = f.read()
7 |
8 | text_splitter = CharacterTextSplitter.from_tiktoken_encoder(
9 | chunk_size=100, chunk_overlap=0
10 | )
11 | texts = text_splitter.split_text(state_of_the_union)
12 | print(len(texts))
13 | print(texts[0])
14 |
--------------------------------------------------------------------------------
/document_transformers/text_splitters.py:
--------------------------------------------------------------------------------
1 | from langchain.text_splitter import RecursiveCharacterTextSplitter
2 |
3 |
4 | with open('./state_of_the_union.txt') as f:
5 | state_of_the_union = f.read()
6 |
7 | # default split on are ["\n\n", "\n", " ", ""]
8 | text_splitter = RecursiveCharacterTextSplitter(
9 | # Set a really small chunk size, just to show.
10 | chunk_size = 100,
11 | chunk_overlap = 20, # max overlap
12 | length_function = len,
13 | add_start_index = True,
14 | )
15 |
16 | texts = text_splitter.create_documents([state_of_the_union])
17 | print(texts[0])
18 | """
19 | page_content='Madam Speaker, Madam Vice President, our First Lady and Second Gentleman. Members of Congress and' metadata={'start_index': 0}
20 | """
21 | print(texts[1])
22 | """
23 | page_content='of Congress and the Cabinet. Justices of the Supreme Court. My fellow Americans.' metadata={'start_index': 82}
24 | """
--------------------------------------------------------------------------------
/few_shot_prompt.py:
--------------------------------------------------------------------------------
1 | from langchain.prompts.few_shot import FewShotPromptTemplate
2 | from langchain.prompts.prompt import PromptTemplate
3 |
4 | examples = [
5 | {
6 | "question": "Who lived longer, Muhammad Ali or Alan Turing?",
7 | "answer":
8 | """
9 | Are follow up questions needed here: Yes.
10 | Follow up: How old was Muhammad Ali when he died?
11 | Intermediate answer: Muhammad Ali was 74 years old when he died.
12 | Follow up: How old was Alan Turing when he died?
13 | Intermediate answer: Alan Turing was 41 years old when he died.
14 | So the final answer is: Muhammad Ali
15 | """
16 | },
17 | {
18 | "question": "When was the founder of craigslist born?",
19 | "answer":
20 | """
21 | Are follow up questions needed here: Yes.
22 | Follow up: Who was the founder of craigslist?
23 | Intermediate answer: Craigslist was founded by Craig Newmark.
24 | Follow up: When was Craig Newmark born?
25 | Intermediate answer: Craig Newmark was born on December 6, 1952.
26 | So the final answer is: December 6, 1952
27 | """
28 | },
29 | {
30 | "question": "Who was the maternal grandfather of George Washington?",
31 | "answer":
32 | """
33 | Are follow up questions needed here: Yes.
34 | Follow up: Who was the mother of George Washington?
35 | Intermediate answer: The mother of George Washington was Mary Ball Washington.
36 | Follow up: Who was the father of Mary Ball Washington?
37 | Intermediate answer: The father of Mary Ball Washington was Joseph Ball.
38 | So the final answer is: Joseph Ball
39 | """
40 | },
41 | {
42 | "question": "Are both the directors of Jaws and Casino Royale from the same country?",
43 | "answer":
44 | """
45 | Are follow up questions needed here: Yes.
46 | Follow up: Who is the director of Jaws?
47 | Intermediate Answer: The director of Jaws is Steven Spielberg.
48 | Follow up: Where is Steven Spielberg from?
49 | Intermediate Answer: The United States.
50 | Follow up: Who is the director of Casino Royale?
51 | Intermediate Answer: The director of Casino Royale is Martin Campbell.
52 | Follow up: Where is Martin Campbell from?
53 | Intermediate Answer: New Zealand.
54 | So the final answer is: No
55 | """
56 | }
57 | ]
58 |
59 | example_prompt = PromptTemplate(input_variables=["question", "answer"], template="Question: {question}\n{answer}")
60 |
61 | print(example_prompt.format(**examples[0]))
62 |
63 | prompt = FewShotPromptTemplate(
64 | examples=examples,
65 | example_prompt=example_prompt,
66 | suffix="Question: {input}",
67 | input_variables=["input"]
68 | )
69 |
70 | print(prompt.format(input="Who was the father of Mary Ball Washington?"))
71 |
72 | from langchain_openai import OpenAI
73 |
74 | # Specify the model_name on 2024-02-27
75 | # After model has been deprecated, the model does not answer any more.
76 | # OpenAI에서 기존에 되던 모델을 text-davinci-003를 없앤 후로 정확히 대답하지 않습니다.
77 | # 어떤 식으로 랭체인을 사용하는지만 보셨으면 좋겠습니다.
78 | llm = OpenAI(model_name="davinci-002")
79 | print(llm.invoke(prompt.format(input="Who was the father of Mary Ball Washington?")))
80 |
--------------------------------------------------------------------------------
/langgraph/chatbot/README.md:
--------------------------------------------------------------------------------
1 | # LangGraph
2 |
3 | LangGraph is a powerful tool developed by the LangChain team to simplify the creation and visualization of complex workflows in natural language processing (NLP) applications. It provides an intuitive interface for designing, debugging, and optimizing workflows, making it easier to build robust and scalable applications.
4 |
5 | ## Features
6 |
7 | - **Workflow Visualization**: Create and visualize complex workflows with ease.
8 | - **Debugging Tools**: Identify and resolve issues in your workflows efficiently.
9 | - **Integration with LangChain**: Seamlessly integrates with the LangChain framework for enhanced functionality.
10 | - **Scalability**: Build workflows that scale with your application's needs.
11 |
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_customizing_state.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated
2 |
3 | from langchain_openai import ChatOpenAI
4 | from langchain_community.tools.tavily_search import TavilySearchResults
5 | from langchain_core.tools import tool
6 | from typing_extensions import TypedDict
7 |
8 | from langgraph.checkpoint.memory import MemorySaver
9 | from langgraph.graph import StateGraph, START, END
10 | from langgraph.graph.message import add_messages
11 | from langgraph.prebuilt import ToolNode, tools_condition
12 |
13 | from langgraph.types import Command, interrupt
14 |
15 | class State(TypedDict):
16 | messages: Annotated[list, add_messages]
17 | name: str
18 | birthday: str
19 |
20 | graph_builder = StateGraph(State)
21 |
22 |
23 | from langchain_core.messages import ToolMessage
24 | from langchain_core.tools import InjectedToolCallId, tool
25 |
26 | from langgraph.types import Command, interrupt
27 |
28 |
29 | @tool
30 | # Note that because we are generating a ToolMessage for a state update, we
31 | # generally require the ID of the corresponding tool call. We can use
32 | # LangChain's InjectedToolCallId to signal that this argument should not
33 | # be revealed to the model in the tool's schema.
34 | def human_assistance(
35 | name: str, birthday: str, tool_call_id: Annotated[str, InjectedToolCallId]
36 | ) -> str:
37 | """Request assistance from a human."""
38 | human_response = interrupt(
39 | {
40 | "question": "Is this correct?",
41 | "name": name,
42 | "birthday": birthday,
43 | },
44 | )
45 | # If the information is correct, update the state as-is.
46 | if human_response.get("correct", "").lower().startswith("y"):
47 | verified_name = name
48 | verified_birthday = birthday
49 | response = "Correct"
50 | # Otherwise, receive information from the human reviewer.
51 | else:
52 | verified_name = human_response.get("name", name)
53 | verified_birthday = human_response.get("birthday", birthday)
54 | response = f"Made a correction: {human_response}"
55 |
56 | # This time we explicitly update the state with a ToolMessage inside
57 | # the tool.
58 | state_update = {
59 | "name": verified_name,
60 | "birthday": verified_birthday,
61 | "messages": [ToolMessage(response, tool_call_id=tool_call_id)],
62 | }
63 | # We return a Command object in the tool to update our state.
64 | return Command(update=state_update) # type: ignore
65 |
66 |
67 | tool = TavilySearchResults(max_results=2)
68 | tools = [tool, human_assistance]
69 |
70 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
71 | llm_with_tools = llm.bind_tools(tools)
72 |
73 | def chatbot(state: State):
74 | message = llm_with_tools.invoke(state["messages"])
75 | # Because we will be interrupting during tool execution,
76 | # we disable parallel tool calling to avoid repeating any
77 | # tool invocations when we resume.
78 | assert len(message.tool_calls) <= 1 # type: ignore
79 | return {"messages": [message]}
80 |
81 | graph_builder.add_node("chatbot", chatbot)
82 |
83 | tool_node = ToolNode(tools=tools)
84 | graph_builder.add_node("tools", tool_node)
85 |
86 | graph_builder.add_conditional_edges(
87 | "chatbot",
88 | tools_condition,
89 | )
90 | graph_builder.add_edge("tools", "chatbot")
91 | graph_builder.add_edge(START, "chatbot")
92 |
93 | memory = MemorySaver()
94 |
95 | graph = graph_builder.compile(checkpointer=memory)
96 |
97 | user_input = (
98 | "Can you look up when LangGraph was released? "
99 | "When you have the answer, use the human_assistance tool for review."
100 | )
101 | config = {"configurable": {"thread_id": "1"}}
102 |
103 | events = graph.stream(
104 | {"messages": [{"role": "user", "content": user_input}]},
105 | config, # type: ignore
106 | stream_mode="values",
107 | )
108 | for event in events:
109 | if "messages" in event:
110 | event["messages"][-1].pretty_print()
111 |
112 | human_command = Command(
113 | resume={
114 | "name": "LangGraph",
115 | "birthday": "Jan 17, 2024",
116 | },
117 | )
118 |
119 | events = graph.stream(human_command, config, stream_mode="values") # type: ignore
120 | for event in events:
121 | if "messages" in event:
122 | event["messages"][-1].pretty_print()
123 |
124 | snapshot = graph.get_state(config) # type: ignore
125 | print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})
126 |
127 | # Update the state with a new name
128 | snapshot = graph.update_state(config, {"name": "LangGraph (library)"}) # type: ignore
129 | snapshot = graph.get_state(config) # type: ignore
130 | print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})
131 |
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_memory.json:
--------------------------------------------------------------------------------
1 | {
2 | "StateSnapshot": {
3 | "values": {
4 | "messages": [
5 | {
6 | "type": "HumanMessage",
7 | "content": "Hi there! My name is Will.",
8 | "additional_kwargs": {},
9 | "response_metadata": {},
10 | "id": "028b7fa2-ad08-46bb-9caf-ee914c7a3a9f"
11 | },
12 | {
13 | "type": "AIMessage",
14 | "content": "Hello, Will! How can I assist you today?",
15 | "additional_kwargs": {
16 | "refusal": null
17 | },
18 | "response_metadata": {
19 | "token_usage": {
20 | "completion_tokens": 13,
21 | "prompt_tokens": 87,
22 | "total_tokens": 100,
23 | "completion_tokens_details": {
24 | "accepted_prediction_tokens": 0,
25 | "audio_tokens": 0,
26 | "reasoning_tokens": 0,
27 | "rejected_prediction_tokens": 0
28 | },
29 | "prompt_tokens_details": {
30 | "audio_tokens": 0,
31 | "cached_tokens": 0
32 | }
33 | },
34 | "model_name": "gpt-4o-2024-08-06",
35 | "system_fingerprint": "fp_898ac29719",
36 | "id": "chatcmpl-BJ1lT1eOs5OiL2HRWuMOSSK11bhgG",
37 | "finish_reason": "stop",
38 | "logprobs": null
39 | },
40 | "id": "run-26ad0d58-875f-49fb-97f9-24a5912b7f90-0",
41 | "usage_metadata": {
42 | "input_tokens": 87,
43 | "output_tokens": 13,
44 | "total_tokens": 100,
45 | "input_token_details": {
46 | "audio": 0,
47 | "cache_read": 0
48 | },
49 | "output_token_details": {
50 | "audio": 0,
51 | "reasoning": 0
52 | }
53 | }
54 | },
55 | {
56 | "type": "HumanMessage",
57 | "content": "Remember my name?",
58 | "additional_kwargs": {},
59 | "response_metadata": {},
60 | "id": "ef57b445-5073-46c3-a2af-0da2c5537455"
61 | },
62 | {
63 | "type": "AIMessage",
64 | "content": "Yes, your name is Will! How can I help you today?",
65 | "additional_kwargs": {
66 | "refusal": null
67 | },
68 | "response_metadata": {
69 | "token_usage": {
70 | "completion_tokens": 16,
71 | "prompt_tokens": 110,
72 | "total_tokens": 126,
73 | "completion_tokens_details": {
74 | "accepted_prediction_tokens": 0,
75 | "audio_tokens": 0,
76 | "reasoning_tokens": 0,
77 | "rejected_prediction_tokens": 0
78 | },
79 | "prompt_tokens_details": {
80 | "audio_tokens": 0,
81 | "cached_tokens": 0
82 | }
83 | },
84 | "model_name": "gpt-4o-2024-08-06",
85 | "system_fingerprint": "fp_898ac29719",
86 | "id": "chatcmpl-BJ1lUqUbb9SKZYgCSZxQOiahvQxhe",
87 | "finish_reason": "stop",
88 | "logprobs": null
89 | },
90 | "id": "run-67c6298d-3028-45a2-be32-6df01f1d5340-0",
91 | "usage_metadata": {
92 | "input_tokens": 110,
93 | "output_tokens": 16,
94 | "total_tokens": 126,
95 | "input_token_details": {
96 | "audio": 0,
97 | "cache_read": 0
98 | },
99 | "output_token_details": {
100 | "audio": 0,
101 | "reasoning": 0
102 | }
103 | }
104 | }
105 | ]
106 | },
107 | "next": [],
108 | "config": {
109 | "configurable": {
110 | "thread_id": "1",
111 | "checkpoint_ns": "",
112 | "checkpoint_id": "1f01244c-db8f-6dce-8004-964cf12634f9"
113 | }
114 | },
115 | "metadata": {
116 | "source": "loop",
117 | "writes": {
118 | "chatbot": {
119 | "messages": [
120 | {
121 | "type": "AIMessage",
122 | "content": "Yes, your name is Will! How can I help you today?",
123 | "additional_kwargs": {
124 | "refusal": null
125 | },
126 | "response_metadata": {
127 | "token_usage": {
128 | "completion_tokens": 16,
129 | "prompt_tokens": 110,
130 | "total_tokens": 126,
131 | "completion_tokens_details": {
132 | "accepted_prediction_tokens": 0,
133 | "audio_tokens": 0,
134 | "reasoning_tokens": 0,
135 | "rejected_prediction_tokens": 0
136 | },
137 | "prompt_tokens_details": {
138 | "audio_tokens": 0,
139 | "cached_tokens": 0
140 | }
141 | },
142 | "model_name": "gpt-4o-2024-08-06",
143 | "system_fingerprint": "fp_898ac29719",
144 | "id": "chatcmpl-BJ1lUqUbb9SKZYgCSZxQOiahvQxhe",
145 | "finish_reason": "stop",
146 | "logprobs": null
147 | },
148 | "id": "run-67c6298d-3028-45a2-be32-6df01f1d5340-0",
149 | "usage_metadata": {
150 | "input_tokens": 110,
151 | "output_tokens": 16,
152 | "total_tokens": 126,
153 | "input_token_details": {
154 | "audio": 0,
155 | "cache_read": 0
156 | },
157 | "output_token_details": {
158 | "audio": 0,
159 | "reasoning": 0
160 | }
161 | }
162 | }
163 | ]
164 | }
165 | },
166 | "step": 4,
167 | "parents": {},
168 | "thread_id": "1"
169 | },
170 | "created_at": "2025-04-05T17:38:36.701414+00:00",
171 | "parent_config": {
172 | "configurable": {
173 | "thread_id": "1",
174 | "checkpoint_ns": "",
175 | "checkpoint_id": "1f01244c-d550-6de6-8003-fd3b2449d796"
176 | }
177 | },
178 | "tasks": []
179 | }
180 | }
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_memory.py:
--------------------------------------------------------------------------------
1 | from langgraph.checkpoint.memory import MemorySaver
2 |
3 | memory = MemorySaver()
4 |
5 | from typing import Annotated
6 |
7 | from langchain_openai import ChatOpenAI
8 | from langchain_community.tools.tavily_search import TavilySearchResults
9 | from typing_extensions import TypedDict
10 |
11 | from langgraph.graph import StateGraph, START, END
12 | from langgraph.graph.message import add_messages
13 | from langgraph.prebuilt import ToolNode, tools_condition
14 |
15 |
16 | class State(TypedDict):
17 | messages: Annotated[list, add_messages]
18 |
19 | graph_builder = StateGraph(State)
20 |
21 | tool = TavilySearchResults(max_results=2)
22 | tools = [tool]
23 |
24 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
25 | llm_with_tools = llm.bind_tools(tools)
26 |
27 | def chatbot(state: State):
28 | return {"messages": [llm_with_tools.invoke(state["messages"])]}
29 |
30 |
31 | graph_builder.add_node("chatbot", chatbot)
32 |
33 | # Add a tool node to the graph
34 | # This node will be called when the tool is invoked
35 | tool_node = ToolNode(tools=[tool])
36 | graph_builder.add_node("tools", tool_node)
37 |
38 | graph_builder.add_conditional_edges(
39 | "chatbot",
40 | tools_condition,
41 | )
42 |
43 | # Any time a tool is called, we return to the chatbot to decide the next step
44 | graph_builder.add_edge("tools", "chatbot")
45 | graph_builder.add_edge(START, "chatbot")
46 |
47 | # Compile with memory
48 | graph = graph_builder.compile(checkpointer=memory)
49 | # print(graph.get_graph().draw_mermaid())
50 | # https://mermaid.live/
51 |
52 | config = {"configurable": {"thread_id": "1"}}
53 |
54 | user_input = "Hi there! My name is Will."
55 |
56 | # The config is the **second positional argument** to stream() or invoke()!
57 | events = graph.stream(
58 | {"messages": [{"role": "user", "content": user_input}]},
59 | config, # type: ignore
60 | stream_mode="values",
61 | )
62 | for event in events:
63 | event["messages"][-1].pretty_print()
64 |
65 | user_input = "Remember my name?"
66 |
67 | config = {"configurable": {"thread_id": "2"}}
68 |
69 | # The config is the **second positional argument** to stream() or invoke()!
70 | events = graph.stream(
71 | {"messages": [{"role": "user", "content": user_input}]},
72 | config, # type: ignore
73 | stream_mode="values",
74 | )
75 | for event in events:
76 | event["messages"][-1].pretty_print()
77 |
78 | # events = graph.stream(
79 | # {"messages": [{"role": "user", "content": user_input}]},
80 | # {"configurable": {"thread_id": "2"}},
81 | # stream_mode="values",
82 | # )
83 | # for event in events:
84 | # event["messages"][-1].pretty_print()
85 |
86 | # config = {"configurable": {"thread_id": "2"}}
87 |
88 | snapshot = graph.get_state(config) # type: ignore
89 | print(snapshot)
90 | # refer to chatbot_with_memory.json
91 | # print(snapshot)
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_memory_sqlite.py:
--------------------------------------------------------------------------------
1 | import sqlite3
2 | from langgraph.checkpoint.sqlite import SqliteSaver
3 |
4 | # find the current directory
5 | import os
6 | current_dir = os.path.dirname(os.path.abspath(__file__))
7 |
8 | conn = sqlite3.connect(f"{current_dir}/checkpoints.sqlite", check_same_thread=False)
9 | memory = SqliteSaver(conn)
10 |
11 | from typing import Annotated
12 |
13 | from langchain_openai import ChatOpenAI
14 | from langchain_community.tools.tavily_search import TavilySearchResults
15 | from typing_extensions import TypedDict
16 |
17 | from langgraph.graph import StateGraph, START, END
18 | from langgraph.graph.message import add_messages
19 | from langgraph.prebuilt import ToolNode, tools_condition
20 |
21 |
22 | class State(TypedDict):
23 | messages: Annotated[list, add_messages]
24 |
25 | graph_builder = StateGraph(State)
26 |
27 | tool = TavilySearchResults(max_results=2)
28 | tools = [tool]
29 |
30 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
31 | llm_with_tools = llm.bind_tools(tools)
32 |
33 | def chatbot(state: State):
34 | return {"messages": [llm_with_tools.invoke(state["messages"])]}
35 |
36 |
37 | graph_builder.add_node("chatbot", chatbot)
38 |
39 | # Add a tool node to the graph
40 | # This node will be called when the tool is invoked
41 | tool_node = ToolNode(tools=[tool])
42 | graph_builder.add_node("tools", tool_node)
43 |
44 | graph_builder.add_conditional_edges(
45 | "chatbot",
46 | tools_condition,
47 | )
48 |
49 | # Any time a tool is called, we return to the chatbot to decide the next step
50 | graph_builder.add_edge("tools", "chatbot")
51 | graph_builder.add_edge(START, "chatbot")
52 |
53 | # Compile with memory
54 | graph = graph_builder.compile(checkpointer=memory)
55 | # print(graph.get_graph().draw_mermaid())
56 | # https://mermaid.live/
57 |
58 | config = {"configurable": {"thread_id": "1"}}
59 |
60 | user_input = "Hi there! My name is Joon."
61 |
62 | # The config is the **second positional argument** to stream() or invoke()!
63 | events = graph.stream(
64 | {"messages": [{"role": "user", "content": user_input}]},
65 | config, # type: ignore
66 | stream_mode="values",
67 | )
68 | for event in events:
69 | event["messages"][-1].pretty_print()
70 |
71 | user_input = "Remember my name?"
72 |
73 | config = {"configurable": {"thread_id": "1"}}
74 |
75 | # The config is the **second positional argument** to stream() or invoke()!
76 | events = graph.stream(
77 | {"messages": [{"role": "user", "content": user_input}]},
78 | config, # type: ignore
79 | stream_mode="values",
80 | )
81 | for event in events:
82 | event["messages"][-1].pretty_print()
83 |
84 | # # events = graph.stream(
85 | # # {"messages": [{"role": "user", "content": user_input}]},
86 | # # {"configurable": {"thread_id": "2"}},
87 | # # stream_mode="values",
88 | # # )
89 | # # for event in events:
90 | # # event["messages"][-1].pretty_print()
91 |
92 | # # config = {"configurable": {"thread_id": "2"}}
93 |
94 | # snapshot = graph.get_state(config) # type: ignore
95 | # print(snapshot)
96 | # # refer to chatbot_with_memory.json
97 | # # print(snapshot)
98 |
99 | print(list(graph.get_state_history(config)))
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_time_travel.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated
2 |
3 | from langchain_openai import ChatOpenAI
4 | from langchain_community.tools.tavily_search import TavilySearchResults
5 | from langchain_core.messages import BaseMessage
6 | from typing_extensions import TypedDict
7 |
8 | from langgraph.checkpoint.memory import MemorySaver
9 | from langgraph.graph import StateGraph, START, END
10 | from langgraph.graph.message import add_messages
11 | from langgraph.prebuilt import ToolNode, tools_condition
12 |
13 |
14 | class State(TypedDict):
15 | messages: Annotated[list, add_messages]
16 |
17 |
18 | graph_builder = StateGraph(State)
19 |
20 |
21 | tool = TavilySearchResults(max_results=2)
22 | tools = [tool]
23 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
24 | llm_with_tools = llm.bind_tools(tools)
25 |
26 |
27 | def chatbot(state: State):
28 | return {"messages": [llm_with_tools.invoke(state["messages"])]}
29 |
30 |
31 | graph_builder.add_node("chatbot", chatbot)
32 |
33 | tool_node = ToolNode(tools=[tool])
34 | graph_builder.add_node("tools", tool_node)
35 |
36 | graph_builder.add_conditional_edges(
37 | "chatbot",
38 | tools_condition,
39 | )
40 | graph_builder.add_edge("tools", "chatbot")
41 | graph_builder.add_edge(START, "chatbot")
42 |
43 | memory = MemorySaver()
44 | graph = graph_builder.compile(checkpointer=memory)
45 |
46 | config = {"configurable": {"thread_id": "1"}}
47 | events = graph.stream(
48 | {
49 | "messages": [
50 | {
51 | "role": "user",
52 | "content": (
53 | "What is the population of South Korea?"
54 | "Could you do some research on it for me?"
55 | ),
56 | },
57 | ],
58 | },
59 | config, # type: ignore
60 | stream_mode="values",
61 | )
62 | for event in events:
63 | if "messages" in event:
64 | event["messages"][-1].pretty_print()
65 |
66 | _ = input()
67 |
68 | events = graph.stream(
69 | {
70 | "messages": [
71 | {
72 | "role": "user",
73 | "content": (
74 | "Ya that's helpful. How about the population of Japan?"
75 | ),
76 | },
77 | ],
78 | },
79 | config, # type: ignore
80 | stream_mode="values",
81 | )
82 | for event in events:
83 | if "messages" in event:
84 | event["messages"][-1].pretty_print()
85 |
86 | _ = input()
87 |
88 | events = graph.stream(
89 | {
90 | "messages": [
91 | {
92 | "role": "user",
93 | "content": (
94 | "Ya that's helpful. How about the population of China?"
95 | ),
96 | },
97 | ],
98 | },
99 | config, # type: ignore
100 | stream_mode="values",
101 | )
102 | for event in events:
103 | if "messages" in event:
104 | event["messages"][-1].pretty_print()
105 |
106 | _ = input()
107 |
108 | # This is a simple example of how to replay a state
109 | to_replay = None
110 | for state in graph.get_state_history(config): # type: ignore
111 | print("Num Messages: ", len(state.values["messages"]), "Next: ", state.next)
112 |
113 | if len(state.values["messages"]) > 0:
114 | print(state.values["messages"][-1].pretty_print())
115 |
116 | print("-" * 80)
117 | if len(state.values["messages"]) == 6:
118 | # ================================== Ai Message ==================================
119 | # Tool Calls:
120 | # tavily_search_results_json (call_YQAiFP2XMgBTeIZB5KHjfLkG)
121 | # Call ID: call_YQAiFP2XMgBTeIZB5KHjfLkG
122 | # Args:
123 | # query: current population of Japan 2023
124 | # None
125 | to_replay = state
126 |
127 | _ = input()
128 |
129 | print("Replay this state *********")
130 | print(to_replay.next)
131 | print(to_replay.config)
132 |
133 | # The `checkpoint_id` in the `to_replay.config` corresponds to a state we've persisted to our checkpointer.
134 | for event in graph.stream(None, to_replay.config, stream_mode="values"):
135 | if "messages" in event:
136 | event["messages"][-1].pretty_print()
137 |
--------------------------------------------------------------------------------
/langgraph/chatbot/chatbot_with_tool.py:
--------------------------------------------------------------------------------
1 | from langchain_community.tools.tavily_search import TavilySearchResults
2 |
3 | tool = TavilySearchResults(max_results=2)
4 | tools = [tool]
5 | tool.invoke("What's a 'node' in LangGraph?")
6 |
7 | """
8 | [
9 | {
10 | "title": "LangGraph Glossary - GitHub Pages",
11 | "url": "https://langchain-ai.github.io/langgraph/concepts/low_level/",
12 | "content": "In LangGraph, nodes are typically python functions (sync or async) where the first positional argument is the state, and (optionally), the second positional argument is a \"config\", containing optional configurable parameters (such as a thread_id).\nSimilar to NetworkX, you add these nodes to a graph using the add_node method:\nfrom langchain_core.runnables import RunnableConfig [...] LangGraph Glossary¶\nGraphs¶\nAt its core, LangGraph models agent workflows as graphs. You define the behavior of your agents using three key components:\n\n\nState: A shared data structure that represents the current snapshot of your application. It can be any Python type, but is typically a TypedDict or Pydantic BaseModel.\n\n\nNodes: Python functions that encode the logic of your agents. They receive the current State as input, perform some computation or side-effect, and return an updated State. [...] By composing Nodes and Edges, you can create complex, looping workflows that evolve the State over time. The real power, though, comes from how LangGraph manages that State. To emphasize: Nodes and Edges are nothing more than Python functions - they can contain an LLM or just good ol' Python code.\nIn short: nodes do the work. edges tell what to do next.",
13 | "score": 0.8995547
14 | },
15 | {
16 | "title": "A Comprehensive Guide About Langgraph: Code Included - Ionio",
17 | "url": "https://www.ionio.ai/blog/a-comprehensive-guide-about-langgraph-code-included",
18 | "content": "Now let’s take a look at each component of langgraph in detail 🚀\nNodes\nA node can be any function or tool your agent uses in langgraph and these nodes are connected with other nodes using edges. Every workflow ends with a “END” node in langgraph which shows the end of workflow. You also need to define a starting node which will be the starting point of your workflow. Optionally, you can also define an ending node if you know the ending point of your workflow.",
19 | "score": 0.8991304
20 | }
21 | ]
22 | """
23 |
24 | from typing import Annotated
25 | from typing_extensions import TypedDict
26 | from langgraph.graph import StateGraph, START, END
27 | from langgraph.graph.message import add_messages
28 | from langchain_openai import ChatOpenAI
29 |
30 | class State(TypedDict):
31 | # Messages have the type "list". The `add_messages` function
32 | # in the annotation defines how this state key should be updated
33 | # (in this case, it appends messages to the list, rather than overwriting them)
34 | messages: Annotated[list, add_messages]
35 |
36 |
37 | graph_builder = StateGraph(State)
38 |
39 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
40 | llm_with_tools = llm.bind_tools(tools)
41 |
42 | def chatbot(state: State):
43 | return {"messages": [llm_with_tools.invoke(state["messages"])]}
44 |
45 | def stream_graph_updates(user_input: str):
46 | for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
47 | for value in event.values():
48 | print("Assistant:", value["messages"][-1].content)
49 |
50 | # The first argument is the unique node name
51 | # The second argument is the function or object that will be called whenever
52 | # the node is used.
53 | graph_builder.add_node("chatbot", chatbot)
54 |
55 |
56 | import json
57 |
58 | from langchain_core.messages import ToolMessage
59 |
60 |
61 | class BasicToolNode:
62 | """A node that runs the tools requested in the last AIMessage."""
63 |
64 | def __init__(self, tools: list) -> None:
65 | self.tools_by_name = {tool.name: tool for tool in tools}
66 |
67 | def __call__(self, inputs: dict):
68 | if messages := inputs.get("messages", []):
69 | message = messages[-1]
70 | else:
71 | raise ValueError("No message found in input")
72 | outputs = []
73 | for tool_call in message.tool_calls:
74 | tool_result = self.tools_by_name[tool_call["name"]].invoke(
75 | tool_call["args"]
76 | )
77 | outputs.append(
78 | ToolMessage(
79 | content=json.dumps(tool_result),
80 | name=tool_call["name"],
81 | tool_call_id=tool_call["id"],
82 | )
83 | )
84 | return {"messages": outputs}
85 |
86 |
87 | tool_node = BasicToolNode(tools=[tool])
88 | graph_builder.add_node("tools", tool_node)
89 |
90 |
91 | def route_tools(
92 | state: State,
93 | ):
94 | """
95 | Use in the conditional_edge to route to the ToolNode if the last message
96 | has tool calls. Otherwise, route to the end.
97 | """
98 | if isinstance(state, list):
99 | ai_message = state[-1] # type: ignore
100 | elif messages := state.get("messages", []):
101 | ai_message = messages[-1]
102 | else:
103 | raise ValueError(f"No messages found in input state to tool_edge: {state}")
104 | if hasattr(ai_message, "tool_calls") and len(ai_message.tool_calls) > 0: # type: ignore
105 | return "tools"
106 | return END
107 |
108 |
109 | # The `tools_condition` function returns "tools" if the chatbot asks to use a tool, and "END" if
110 | # it is fine directly responding. This conditional routing defines the main agent loop.
111 | graph_builder.add_conditional_edges(
112 | "chatbot",
113 | route_tools,
114 | # The following dictionary lets you tell the graph to interpret the condition's outputs as a specific node
115 | # It defaults to the identity function, but if you
116 | # want to use a node named something else apart from "tools",
117 | # You can update the value of the dictionary to something else
118 | # e.g., "tools": "my_tools"
119 | {"tools": "tools", END: END},
120 | )
121 | # Any time a tool is called, we return to the chatbot to decide the next step
122 | graph_builder.add_edge("tools", "chatbot")
123 | graph_builder.add_edge(START, "chatbot")
124 | graph = graph_builder.compile()
125 | # print(graph.get_graph().draw_mermaid())
126 | # https://mermaid.live/
127 |
128 | while True:
129 | try:
130 | user_input = input("User: ")
131 | if user_input.lower() in ["quit", "exit", "q"]:
132 | print("Goodbye!")
133 | break
134 |
135 | stream_graph_updates(user_input)
136 | except:
137 | # fallback if input() is not available
138 | user_input = "What do you know about LangGraph?"
139 | print("User: " + user_input)
140 | stream_graph_updates(user_input)
141 | break
142 |
--------------------------------------------------------------------------------
/langgraph/chatbot/human_in_the_loop.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated
2 |
3 | from langchain_openai import ChatOpenAI
4 | from langchain_community.tools.tavily_search import TavilySearchResults
5 | from langchain_core.tools import tool
6 | from typing_extensions import TypedDict
7 |
8 | from langgraph.checkpoint.memory import MemorySaver
9 | from langgraph.graph import StateGraph, START, END
10 | from langgraph.graph.message import add_messages
11 | from langgraph.prebuilt import ToolNode, tools_condition
12 |
13 | from langgraph.types import Command, interrupt
14 |
15 | class State(TypedDict):
16 | messages: Annotated[list, add_messages]
17 |
18 |
19 | graph_builder = StateGraph(State)
20 |
21 |
22 | @tool
23 | def human_assistance(query: str) -> str:
24 | """Request assistance from a human."""
25 | human_response = interrupt({"query": query})
26 | return human_response["data"]
27 |
28 |
29 | tool = TavilySearchResults(max_results=2)
30 | tools = [tool, human_assistance]
31 |
32 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
33 | llm_with_tools = llm.bind_tools(tools)
34 |
35 | def chatbot(state: State):
36 | message = llm_with_tools.invoke(state["messages"])
37 | # Because we will be interrupting during tool execution,
38 | # we disable parallel tool calling to avoid repeating any
39 | # tool invocations when we resume.
40 | assert len(message.tool_calls) <= 1 # type: ignore
41 | return {"messages": [message]}
42 |
43 | graph_builder.add_node("chatbot", chatbot)
44 |
45 | tool_node = ToolNode(tools=tools)
46 | graph_builder.add_node("tools", tool_node)
47 |
48 | graph_builder.add_conditional_edges(
49 | "chatbot",
50 | tools_condition,
51 | )
52 | graph_builder.add_edge("tools", "chatbot")
53 | graph_builder.add_edge(START, "chatbot")
54 |
55 | memory = MemorySaver()
56 |
57 | graph = graph_builder.compile(checkpointer=memory)
58 |
59 | user_input = "I need some expert guidance for building an AI agent. Could you request assistance for me?"
60 | config = {"configurable": {"thread_id": "1"}}
61 |
62 | events = graph.stream(
63 | {"messages": [{"role": "user", "content": user_input}]},
64 | config, # type: ignore
65 | stream_mode="values",
66 | )
67 | for event in events:
68 | if "messages" in event:
69 | event["messages"][-1].pretty_print()
70 |
71 | snapshot = graph.get_state(config) # type: ignore
72 | print(snapshot.next)
73 |
74 | # human_response = (
75 | # "We, the experts are here to help! We'd recommend you check out LangGraph to build your agent."
76 | # " It's much more reliable and extensible than simple autonomous agents."
77 | # )
78 |
79 | human_response = input("Please provide your response to the user: ")
80 |
81 | human_command = Command(resume={"data": human_response})
82 |
83 | events = graph.stream(human_command, config, stream_mode="values") # type: ignore
84 | for event in events:
85 | if "messages" in event:
86 | event["messages"][-1].pretty_print()
87 |
--------------------------------------------------------------------------------
/langgraph/chatbot/lat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/langgraph/chatbot/lat.png
--------------------------------------------------------------------------------
/langgraph/chatbot/lat_chart.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/langgraph/chatbot/lat_chart.jpeg
--------------------------------------------------------------------------------
/langgraph/chatbot/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "chatbot"
3 | version = "0.1.0"
4 | description = "Add your description here"
5 | readme = "README.md"
6 | requires-python = ">=3.13"
7 | dependencies = [
8 | "langchain-anthropic>=0.3.10",
9 | "langchain-community>=0.3.21",
10 | "langchain-openai>=0.3.12",
11 | "langgraph>=0.3.25",
12 | "langgraph-checkpoint-sqlite>=2.0.6",
13 | "langsmith>=0.3.24",
14 | "tavily-python>=0.5.4",
15 | ]
16 |
--------------------------------------------------------------------------------
/langgraph/chatbot/reflection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/langgraph/chatbot/reflection.png
--------------------------------------------------------------------------------
/langgraph/chatbot/reflection.py:
--------------------------------------------------------------------------------
1 | from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
2 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
3 | from langchain_openai import ChatOpenAI
4 |
5 | prompt = ChatPromptTemplate.from_messages(
6 | [
7 | (
8 | "system",
9 | "You are an essay assistant tasked with writing excellent 3-paragraph essays."
10 | " Generate the best essay possible for the user's request."
11 | " If the user provides critique, respond with a revised version of your previous attempts.",
12 | ),
13 | MessagesPlaceholder(variable_name="messages"),
14 | ]
15 | )
16 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
17 | generate = prompt | llm
18 |
19 | essay = ""
20 | request = HumanMessage(
21 | content="Write an essay on why the little prince is relevant in modern childhood"
22 | )
23 | for chunk in generate.stream({"messages": [request]}):
24 | print(chunk.content, end="")
25 | essay += chunk.content
26 |
27 | # Start reflecting on the essay
28 | reflection_prompt = ChatPromptTemplate.from_messages(
29 | [
30 | (
31 | "system",
32 | "You are a teacher grading an essay submission. Generate critique and recommendations for the user's submission."
33 | " Provide detailed recommendations, including requests for length, depth, style, etc.",
34 | ),
35 | MessagesPlaceholder(variable_name="messages"),
36 | ]
37 | )
38 | reflect = reflection_prompt | llm
39 | reflection = ""
40 | for chunk in reflect.stream({"messages": [request, HumanMessage(content=essay)]}):
41 | print(chunk.content, end="")
42 | reflection += chunk.content
43 |
44 | # import asyncio
45 | # from typing import Annotated, List, Sequence
46 | # from langgraph.graph import END, StateGraph, START
47 | # from langgraph.graph.message import add_messages
48 | # from langgraph.checkpoint.memory import MemorySaver
49 | # from typing_extensions import TypedDict
50 |
51 |
52 | # class State(TypedDict):
53 | # messages: Annotated[list, add_messages]
54 |
55 |
56 | # async def generation_node(state: State) -> State:
57 | # return {"messages": [await generate.ainvoke(state["messages"])]} # type: ignore
58 |
59 |
60 | # async def reflection_node(state: State) -> State:
61 | # # Other messages we need to adjust
62 | # cls_map = {
63 | # "ai": HumanMessage,
64 | # "human": AIMessage
65 | # }
66 | # # First message is the original user request. We hold it the same for all nodes
67 | # translated = [state["messages"][0]] + [
68 | # cls_map[msg.type](content=msg.content) for msg in state["messages"][1:]
69 | # ]
70 | # res = await reflect.ainvoke(translated)
71 | # # We treat the output of this as human feedback for the generator
72 | # return {"messages": [HumanMessage(content=res.content)]}
73 |
74 |
75 | # builder = StateGraph(State)
76 | # builder.add_node("generate", generation_node)
77 | # builder.add_node("reflect", reflection_node)
78 | # builder.add_edge(START, "generate")
79 |
80 |
81 | # def should_continue(state: State):
82 | # if len(state["messages"]) > 6:
83 | # # End after 3 iterations
84 | # return END
85 | # return "reflect"
86 |
87 |
88 | # builder.add_conditional_edges("generate", should_continue)
89 | # builder.add_edge("reflect", "generate")
90 | # memory = MemorySaver()
91 | # graph = builder.compile(checkpointer=memory)
92 | # # print(graph.get_graph().draw_mermaid())
93 |
94 | # config = {"configurable": {"thread_id": "1"}}
95 |
96 | # async def main():
97 | # async for event in graph.astream(
98 | # {
99 | # "messages": [
100 | # HumanMessage(
101 | # content="Generate an essay on the topicality of The Little Prince and its message in modern life"
102 | # )
103 | # ],
104 | # },
105 | # config,
106 | # ):
107 | # print(event)
108 | # print("---")
109 |
110 | # if __name__ == "__main__":
111 | # asyncio.run(main())
--------------------------------------------------------------------------------
/langgraph/chatbot/reflexion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/langgraph/chatbot/reflexion.png
--------------------------------------------------------------------------------
/langgraph/chatbot/schema.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 | from typing import List
3 | from pydantic import ValidationError
4 | from langchain_core.messages import ToolMessage
5 |
6 | class Reflection(BaseModel):
7 | missing: str = Field(description="Critique of what is missing.")
8 | superfluous: str = Field(description="Critique of what is superfluous")
9 |
10 | class AnswerQuestion(BaseModel):
11 | """Answer the question. Provide an answer, reflection, and then follow up with search queries to improve the answer."""
12 | answer: str = Field(description="~250 word detailed answer to the question.")
13 | search_queries: List[str] = Field(
14 | description="1-3 search queries for researching improvements to address the critique of your current answer."
15 | )
16 | reflection: Reflection = Field(description="Your reflection on the initial answer.")
17 |
18 | class ResponderWithRetries:
19 | def __init__(self, runnable, validator):
20 | self.runnable = runnable
21 | self.validator = validator
22 |
23 | def respond(self, state: dict):
24 | response = []
25 | for attempt in range(3):
26 | response = self.runnable.invoke(
27 | {"messages": state["messages"]}, {"tags": [f"attempt:{attempt}"]}
28 | )
29 | try:
30 | self.validator.invoke(response)
31 | return {"messages": response}
32 | except ValidationError as e:
33 | state = state + [
34 | response,
35 | ToolMessage(
36 | content=f"{repr(e)}\n\nPay close attention to the function schema.\n\n"
37 | + self.validator.schema_json()
38 | + " Respond by fixing all validation errors.",
39 | tool_call_id=response.tool_calls[0]["id"],
40 | ),
41 | ] # type: ignore
42 | return {"messages": response}
43 |
44 | # Extend the initial answer schema to include references.
45 | # Forcing citation in the model encourages grounded responses
46 | class ReviseAnswer(AnswerQuestion):
47 | """Revise your original answer to your question. Provide an answer, reflection,
48 |
49 | cite your reflection with references, and finally
50 | add search queries to improve the answer."""
51 |
52 | references: list[str] = Field(
53 | description="Citations motivating your updated answer."
54 | )
55 |
--------------------------------------------------------------------------------
/langgraph/chatbot/simple_chatbot.py:
--------------------------------------------------------------------------------
1 | from typing import Annotated
2 | from typing_extensions import TypedDict
3 | from langgraph.graph import StateGraph, START, END
4 | from langgraph.graph.message import add_messages
5 | from langchain_openai import ChatOpenAI
6 |
7 | class State(TypedDict):
8 | # Messages have the type "list". The `add_messages` function
9 | # in the annotation defines how this state key should be updated
10 | # (in this case, it appends messages to the list, rather than overwriting them)
11 | messages: Annotated[list, add_messages]
12 |
13 |
14 | graph_builder = StateGraph(State)
15 |
16 | llm = ChatOpenAI(model="gpt-4o") # type: ignore
17 |
18 | def chatbot(state: State):
19 | return {"messages": [llm.invoke(state["messages"])]}
20 |
21 |
22 | # The first argument is the unique node name
23 | # The second argument is the function or object that will be called whenever
24 | # the node is used.
25 | graph_builder.add_node("chatbot", chatbot)
26 |
27 | graph_builder.add_edge(START, "chatbot")
28 | graph_builder.add_edge("chatbot", END)
29 | graph = graph_builder.compile()
30 | # print(graph.get_graph().draw_mermaid())
31 | # https://mermaid.live/
32 |
33 | def stream_graph_updates(user_input: str):
34 | for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):
35 | for value in event.values():
36 | print("Assistant:", value["messages"][-1].content)
37 |
38 |
39 | while True:
40 | try:
41 | user_input = input("User: ")
42 | if user_input.lower() in ["quit", "exit", "q"]:
43 | print("Goodbye!")
44 | break
45 | stream_graph_updates(user_input)
46 | except:
47 | # fallback if input() is not available
48 | user_input = "What do you know about LangGraph?"
49 | print("User: " + user_input)
50 | stream_graph_updates(user_input)
51 | break
52 |
--------------------------------------------------------------------------------
/langserve/client.py:
--------------------------------------------------------------------------------
1 | import json
2 | import requests
3 | """
4 | POST /my_runnable/invoke - invoke the runnable on a single input
5 | POST /my_runnable/batch - invoke the runnable on a batch of inputs
6 | POST /my_runnable/stream - invoke on a single input and stream the output
7 | POST /my_runnable/stream_log - invoke on a single input and stream the output, including output of intermediate steps as it's generated
8 | GET /my_runnable/input_schema - json schema for input to the runnable
9 | GET /my_runnable/output_schema - json schema for output of the runnable
10 | GET /my_runnable/config_schema - json schema for config of the runnable
11 | """
12 | response = requests.post(
13 | "http://localhost:8000/joke/invoke",
14 | json={'input': {'topic': 'cats'}}
15 | )
16 | print(response.json())
17 | """
18 | {
19 | 'output': {
20 | 'content': "Sure, here's a cat-related joke for you:\n\nWhy don't cats play poker in the wild?\n\nToo many cheetahs!",
21 | 'additional_kwargs': {},
22 | 'type': 'ai',
23 | 'example': False
24 | },
25 | 'callback_events': [],
26 | 'metadata': {
27 | 'run_id': '8ed5fa43-6e1f-4743-8310-77dbe52503c0'}}
28 | """
29 |
30 | response = requests.get(
31 | "http://localhost:8000/joke/input_schema",
32 | )
33 | print(response.json())
34 | """
35 | {'title': 'PromptInput', 'type': 'object', 'properties': {'topic': {'title': 'Topic', 'type': 'string'}}}
36 | """
37 |
38 | response = requests.post(
39 | "http://localhost:8000/joke/stream",
40 | json={'input': {'topic': 'cats'}},
41 | stream=True
42 | )
43 |
44 | # Check if the request was successful
45 | if response.status_code == 200:
46 | try:
47 | current_event = None
48 | event_data = []
49 | for line in response.iter_lines():
50 | if line: # filter out keep-alive new lines
51 | # print(line.decode('utf-8'))
52 | line = line.decode('utf-8')
53 | """
54 | event: data
55 | data: {"content":"","additional_kwargs":{},"type":"AIMessageChunk","example":false}
56 | event: data
57 | data: {"content":"Sure","additional_kwargs":{},"type":"AIMessageChunk","example":false}
58 | event: data
59 | ...
60 | """
61 | if line.startswith("event:"):
62 | current_event = line.split(":", 1)[1].strip()
63 | elif line.startswith("data:"):
64 | data = line.split(":", 1)[1].strip()
65 | try:
66 | parsed_data = json.loads(data)
67 | """
68 | {'run_id': '9d77c51b-6e0d-457f-a75e-0961f205cc8f'}
69 | {'content': '', 'additional_kwargs': {}, 'type': 'AIMessageChunk', 'example': False}
70 | {'content': 'Sure', 'additional_kwargs': {}, 'type': 'AIMessageChunk', 'example': False}
71 | {'content': ',', 'additional_kwargs': {}, 'type': 'AIMessageChunk', 'example': False}
72 | ...
73 | """
74 | event_data.append((current_event, parsed_data))
75 |
76 | except json.JSONDecodeError:
77 | print(f"Error decoding JSON: {data}")
78 | except KeyboardInterrupt:
79 | print("Streaming stopped by user.")
80 | else:
81 | print(f"Failed to stream data: {response.status_code}")
82 |
--------------------------------------------------------------------------------
/langserve/sdk_client.py:
--------------------------------------------------------------------------------
1 | from langchain.prompts import ChatPromptTemplate
2 | from langchain.schema.runnable import RunnableMap
3 | from langserve import RemoteRunnable
4 |
5 | openai = RemoteRunnable("http://localhost:8000/openai/")
6 | joke_chain = RemoteRunnable("http://localhost:8000/joke/")
7 |
8 | print(joke_chain.invoke({"topic": "parrots"}))
9 | """
10 | content="Sure, here's a joke for you:\n\nWhy don't scientists trust parrots?\n\nBecause they always give them quack advice!"
11 | """
12 |
13 | prompt = ChatPromptTemplate.from_messages(
14 | [("system", "Tell me a long story about {topic}")]
15 | )
16 |
17 | # Can define custom chains
18 | chain = prompt | RunnableMap({
19 | "openai": openai
20 | })
21 |
22 | print(chain.batch([{ "topic": "parrots" }]))
23 | """
24 | [{'openai': AIMessage(content='Once upon a time, in a lush tropical rainforest, there lived a colorful and vibrant community of parrots. These parrots were renowned for their intelligence, beauty, and lively personalities. They were the guardians of the forest, spreading joy and laughter with their melodious songs and playful behavior.\n\nAt the heart of the parrot community was a wise and respected elder named Ollie. Ollie had a rich plumage of emerald green feathers, with touches of bright red and blue. His eyes twinkled with an ancient wisdom that had been passed down through generations.\n\nOne day, as the parrots gathered around Ollie, he shared a tale from long ago. It was a story about an ancient treasure hidden deep within the forest. This treasure, known as the "Jewel of the Rainforest," was said to possess magical powers that could bring harmony and balance to all living creatures.\n\nThe parrots were intrigued by the tale and decided to embark on a quest to find the Jewel of the Rainforest. They believed that by harnessing its powers, they could protect their home from any harm that might come its way.\n\nLed by Ollie, the parrots set off on their adventure, flying through the dense foliage, and singing songs of courage and determination. Along the way, they encountered various challenges, but their unity and unwavering spirit kept them going.\n\nAs they ventured deeper into the forest, they faced treacherous rivers, towering trees, and hidden predators. However, their sharp minds and agile wings helped them overcome every obstacle. They supported one another, sharing their knowledge and strength.\n\nDuring their journey, the parrots discovered the incredible diversity of the rainforest. They marveled at the exotic flowers, cascading waterfalls, and the symphony of sounds that filled the air. They also encountered other creatures, like mischievous monkeys swinging from the trees and wise old turtles slowly making their way across the forest floor.\n\nOne day, after months of relentless searching, the parrots stumbled upon a hidden cave. Inside, they found an ethereal glow emanating from a magnificent jewel. It was the Jewel of the Rainforest, shimmering with every color imaginable. The parrots knew they had found what they were looking for.\n\nAs they gathered around the jewel, a magical energy enveloped them. They felt a sense of peace and enlightenment wash over them, as if the forest itself had embraced them. From that moment on, the parrots became the true guardians of the rainforest, using the Jewel\'s powers to protect and preserve their home.\n\nWith the Jewel\'s magic, the parrots brought harmony to the ecosystem, ensuring that all creatures lived in balance and peace. They sang their songs of unity, healing the wounds of the forest and spreading happiness throughout.\n\nWord of the parrots\' noble efforts spread far and wide, attracting visitors from across the world who wanted to witness the wonders of the rainforest. People marveled at the parrots\' intelligence, their ability to mimic human speech, and their vibrant colors.\n\nThe parrots became ambassadors of the rainforest, teaching humans the importance of conservation and the need to protect the Earth\'s natural wonders. Their enchanting presence brought joy to all who encountered them, reminding everyone of the beauty and magic that resided within nature.\n\nAnd so, the parrots lived on, their legacy carried through the generations. They continued to guard the rainforest, ensuring its prosperity and safeguarding the Jewel of the Rainforest. Their story became a legend, passed down through time, reminding everyone of the power of unity, wisdom, and the magic that lies within the hearts of parrots.')}]
25 | """
--------------------------------------------------------------------------------
/langserve/server.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from fastapi import FastAPI
3 | from langchain.prompts import ChatPromptTemplate
4 | from langchain_openai import ChatOpenAI
5 | from langserve import add_routes
6 |
7 |
8 | app = FastAPI(
9 | title="LangChain Server",
10 | version="1.0",
11 | description="A simple api server using Langchain's Runnable interfaces",
12 | )
13 |
14 | add_routes(
15 | app,
16 | ChatOpenAI(),
17 | path="/openai",
18 | )
19 |
20 | model = ChatOpenAI()
21 | prompt = ChatPromptTemplate.from_template("tell me a joke about {topic}")
22 | add_routes(
23 | app,
24 | prompt | model,
25 | path="/joke",
26 | )
27 |
28 | if __name__ == "__main__":
29 | import uvicorn
30 |
31 | uvicorn.run(app, host="localhost", port=8000)
32 |
--------------------------------------------------------------------------------
/langsmith/.python-version:
--------------------------------------------------------------------------------
1 | 3.13
2 |
--------------------------------------------------------------------------------
/langsmith/README.md:
--------------------------------------------------------------------------------
1 | # LangSmith
2 |
3 | LangSmith is a tool designed to simplify and enhance the development of applications using the LangChain framework. It provides utilities for debugging, monitoring, and optimizing workflows built with LangChain.
4 |
5 | ## Features
6 |
7 | - **Debugging Tools**: Easily identify and resolve issues in your LangChain workflows.
8 | - **Monitoring**: Track the performance and behavior of your applications in real-time.
9 | - **Optimization**: Analyze and improve the efficiency of your LangChain-based applications.
10 |
11 |
--------------------------------------------------------------------------------
/langsmith/create_prompt.py:
--------------------------------------------------------------------------------
1 | from langsmith import Client
2 | from langchain_core.prompts import ChatPromptTemplate
3 |
4 | # Connect to the LangSmith client
5 |
6 | client = Client()
7 |
8 | # Define the prompt
9 |
10 | prompt = ChatPromptTemplate([
11 | ("system", "You are a helpful chatbot. Answer the question as best as you can. provide the answer within 1 line"),
12 | ("user", "{question}"),
13 | ])
14 |
15 | # Push the prompt
16 | client.push_prompt("my-fistprompt", object=prompt)
17 |
--------------------------------------------------------------------------------
/langsmith/evaluation.py:
--------------------------------------------------------------------------------
1 | from langsmith import wrappers, Client
2 | from pydantic import BaseModel, Field
3 | from openai import OpenAI
4 |
5 | client = Client()
6 | openai_client = wrappers.wrap_openai(OpenAI())
7 |
8 | # For other dataset creation methods, see: https://docs.smith.langchain.com/evaluation/how_to_guides/manage_datasets_programmatically https://docs.smith.langchain.com/evaluation/how_to_guides/manage_datasets_in_application
9 |
10 | # Create inputs and reference outputs
11 | examples = [
12 | (
13 | "Which country is Mount Kilimanjaro located in?",
14 | "Mount Kilimanjaro is located in Tanzania.",
15 | ),
16 | (
17 | "What is Earth's lowest point?",
18 | "Earth's lowest point is The Dead Sea.",
19 | ),
20 | ]
21 |
22 | inputs = [{"question": input_prompt} for input_prompt, _ in examples]
23 | outputs = [{"answer": output_answer} for _, output_answer in examples]
24 |
25 | # Programmatically create a dataset in LangSmith
26 | dataset = client.create_dataset(
27 | dataset_name = "Sample dataset",
28 | description = "A sample dataset in LangSmith."
29 | )
30 |
31 | # Add examples to the dataset
32 | client.create_examples(inputs=inputs, outputs=outputs, dataset_id=dataset.id)
33 |
34 | # Define the application logic you want to evaluate inside a target function
35 | # The SDK will automatically send the inputs from the dataset to your target function
36 | def target(inputs: dict) -> dict:
37 | response = openai_client.chat.completions.create(
38 | model="gpt-4o-mini",
39 | messages=[
40 | { "role": "system", "content": "Answer the following question accurately" },
41 | { "role": "user", "content": inputs["question"] },
42 | ]
43 | )
44 | return { "response": response.choices[0].message.content.strip() } # type: ignore
45 |
46 | # Define instructions for the LLM judge evaluator
47 | instructions = """Evaluate Student Answer against Ground Truth for conceptual similarity and classify true or false:
48 | - False: No conceptual match and similarity
49 | - True: Most or full conceptual match and similarity
50 | - Key criteria: Concept should match, not exact wording.
51 | """
52 |
53 | # Define output schema for the LLM judge
54 | class Grade(BaseModel):
55 | score: bool = Field(description="Boolean that indicates whether the response is accurate relative to the reference answer")
56 |
57 | # Define LLM judge that grades the accuracy of the response relative to reference output
58 | def accuracy(outputs: dict, reference_outputs: dict) -> bool:
59 | response = openai_client.beta.chat.completions.parse(
60 | model="gpt-4o-mini",
61 | messages=[
62 | { "role": "system", "content": instructions },
63 | { "role": "user", "content": f"""Ground Truth answer: {reference_outputs["answer"]};
64 | Student's Answer: {outputs["response"]}"""
65 | }],
66 | response_format=Grade
67 | )
68 | return response.choices[0].message.parsed.score # type: ignore
69 |
70 |
71 | # After running the evaluation, a link will be provided to view the results in langsmith
72 | experiment_results = client.evaluate(
73 | target,
74 | data = "Sample dataset",
75 | evaluators = [
76 | accuracy, # type: ignore
77 | # can add multiple evaluators here
78 | ],
79 | experiment_prefix = "first-eval-in-langsmith",
80 | max_concurrency = 2,
81 | ) # type: ignore
82 |
83 | print(experiment_results)
84 |
--------------------------------------------------------------------------------
/langsmith/main.py:
--------------------------------------------------------------------------------
1 | from langchain_openai import ChatOpenAI
2 |
3 | llm = ChatOpenAI()
4 | llm.invoke("What is the population of South Korean?") # type: ignore
5 |
6 |
--------------------------------------------------------------------------------
/langsmith/pull_prompt.py:
--------------------------------------------------------------------------------
1 | from langsmith import Client
2 | from openai import OpenAI
3 | from langchain_core.messages import convert_to_openai_messages
4 |
5 | # Connect to LangSmith and OpenAI
6 |
7 | client = Client()
8 | oai_client = OpenAI()
9 |
10 | # Pull the prompt to use
11 |
12 | # You can also specify a specific commit by passing the commit hash "my-prompt:"
13 |
14 | prompt = client.pull_prompt("my-fistprompt")
15 |
16 | # Since our prompt
17 | # only has one variable we could also pass in the value directly
18 |
19 | # The code below is equivalent to formatted_prompt = prompt.invoke("What is the color of the sky?")
20 |
21 | formatted_prompt = prompt.invoke({"question": "What is the color of the sky?"})
22 |
23 | # Test the prompt
24 |
25 | response = oai_client.chat.completions.create(
26 | model="gpt-4o",
27 | messages=convert_to_openai_messages(formatted_prompt.messages), # type: ignore
28 | )
29 | print(response)
30 |
--------------------------------------------------------------------------------
/langsmith/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "learn-langsmith"
3 | version = "0.1.0"
4 | description = "Add your description here"
5 | readme = "README.md"
6 | requires-python = ">=3.13"
7 | dependencies = [
8 | "langchain>=0.3.23",
9 | "langchain-openai>=0.3.12",
10 | "pydantic>=2.11.2",
11 | ]
12 |
--------------------------------------------------------------------------------
/lcel/Chinook.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/lcel/Chinook.db
--------------------------------------------------------------------------------
/lcel/code_writing.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain.prompts import (
6 | ChatPromptTemplate,
7 | )
8 | from langchain.schema import StrOutputParser
9 | from langchain_community.utilities import PythonREPL
10 |
11 | # Introduce PythonREPL
12 | python_repl = PythonREPL()
13 | print(python_repl.run("print(1+1)"))
14 | """
15 | Python REPL can execute arbitrary code. Use with caution.
16 | 2
17 | """
18 |
19 | template = """Write some python code to solve the user's problem.
20 |
21 | Return only python code in Markdown format, e.g.:
22 |
23 | ```python
24 | ....
25 | ```"""
26 | prompt = ChatPromptTemplate.from_messages([("system", template), ("human", "{input}")])
27 |
28 | model = ChatOpenAI()
29 |
30 | def _sanitize_output(text: str):
31 | _, after = text.split("```python")
32 | return after.split("```")[0]
33 |
34 | chain = prompt | model | StrOutputParser()
35 |
36 | print(chain.invoke({"input": "Write the function to sort the list. Then call the function by pasing [1,4,2]"}))
37 | """
38 | ```python
39 | def sort_list(lst):
40 | return sorted(lst)
41 |
42 | my_list = [1, 4, 2]
43 | sorted_list = sort_list(my_list)
44 | print(sorted_list)
45 | ```
46 | """
47 | repl_chain = chain | _sanitize_output | PythonREPL().run
48 |
49 | print(repl_chain.invoke({"input": "Write the function to sort the list. Then call the function by pasing [1,4,2]"}))
50 | """
51 | Python REPL can execute arbitrary code. Use with caution.
52 | [1, 2, 4]
53 | """
54 |
--------------------------------------------------------------------------------
/lcel/faiss_index/index.faiss:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/lcel/faiss_index/index.faiss
--------------------------------------------------------------------------------
/lcel/faiss_index/index.pkl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/lcel/faiss_index/index.pkl
--------------------------------------------------------------------------------
/lcel/multiple_chains.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from operator import itemgetter
5 | from langchain_openai import ChatOpenAI
6 | from langchain.prompts import ChatPromptTemplate
7 | from langchain.schema import StrOutputParser
8 |
9 | # Example1
10 | prompt1 = ChatPromptTemplate.from_template("what is the city {person} is from?")
11 | prompt2 = ChatPromptTemplate.from_template(
12 | "what country is the city {city} in? respond in {language}"
13 | )
14 |
15 | model = ChatOpenAI()
16 |
17 | chain1 = prompt1 | model | StrOutputParser()
18 |
19 | chain2 = (
20 | {"city": chain1, "language": itemgetter("language")}
21 | | prompt2
22 | | model
23 | | StrOutputParser()
24 | )
25 |
26 | print(chain2.invoke({"person": "obama", "language": "english"}))
27 | """
28 | Barack Obama, the 44th President of the United States, was born in Honolulu, Hawaii, which is located in the United States of America.
29 | """
30 |
31 | # Example2
32 | from langchain.schema.runnable import RunnablePassthrough
33 |
34 | # Generates a prompt asking for a color based on a given attribute.
35 | prompt1 = ChatPromptTemplate.from_template(
36 | "generate a {attribute} color. Return the name of the color and nothing else:"
37 | )
38 |
39 | # Asks for a fruit of a specified color.
40 | prompt2 = ChatPromptTemplate.from_template(
41 | "what is a fruit of color: {color}. Return the name of the fruit and nothing else:"
42 | )
43 |
44 | # Requests the name of a country with a flag containing a certain color.
45 | prompt3 = ChatPromptTemplate.from_template(
46 | "what is a country with a flag that has the color: {color}. Return the name of the country and nothing else:"
47 | )
48 |
49 | # Forms a prompt asking for the color of a specific fruit and the flag of a specific country
50 | prompt4 = ChatPromptTemplate.from_template(
51 | "What is the color of {fruit} and the flag of {country}?"
52 | )
53 |
54 | # Extract model message
55 | model_parser = model | StrOutputParser()
56 |
57 | # Generating Color
58 | color_generator = (
59 | {"attribute": RunnablePassthrough()} | prompt1 | {"color": model_parser}
60 | )
61 |
62 | # Takes a color and uses prompt2 to ask for a corresponding fruit
63 | color_to_fruit = prompt2 | model_parser
64 |
65 | # uses prompt3 to find a country with a flag containing that color
66 | color_to_country = prompt3 | model_parser
67 |
68 |
69 | question_generator = (
70 | color_generator | {"fruit": color_to_fruit, "country": color_to_country} | prompt4
71 | )
72 |
73 | prompt = question_generator.invoke("warm")
74 | print(prompt)
75 | """
76 | messages=[HumanMessage(content='What is the color of Coral. and the flag of Comoros?')]
77 | """
78 |
79 | print(model.invoke(prompt))
80 | """
81 | content='The color of a pomegranate is typically a deep red or maroon. The flag of Armenia consists of three horizontal bands of equal width - the top band is red, the middle band is blue, and the bottom band is orange.'
82 | """
83 |
84 |
85 | # Example3
86 | # Branching and Merging
87 | """
88 | Input
89 | / \
90 | / \
91 | Branch1 Branch2
92 | \ /
93 | \ /
94 | Combine
95 | """
96 | planner = (
97 | ChatPromptTemplate.from_template("Generate an argument about: {input}")
98 | | ChatOpenAI()
99 | | StrOutputParser()
100 | | {"base_response": RunnablePassthrough()}
101 | )
102 |
103 | arguments_for = (
104 | ChatPromptTemplate.from_template(
105 | "List the pros or positive aspects of {base_response}"
106 | )
107 | | ChatOpenAI()
108 | | StrOutputParser()
109 | )
110 | arguments_against = (
111 | ChatPromptTemplate.from_template(
112 | "List the cons or negative aspects of {base_response}"
113 | )
114 | | ChatOpenAI()
115 | | StrOutputParser()
116 | )
117 |
118 | final_responder = (
119 | ChatPromptTemplate.from_messages(
120 | [
121 | ("ai", "{original_response}"),
122 | ("human", "Pros:\n{results_1}\n\nCons:\n{results_2}"),
123 | ("system", "Generate a final response given the critique"),
124 | ]
125 | )
126 | | ChatOpenAI()
127 | | StrOutputParser()
128 | )
129 |
130 | chain = (
131 | planner
132 | | {
133 | "results_1": arguments_for,
134 | "results_2": arguments_against,
135 | "original_response": itemgetter("base_response"),
136 | }
137 | | final_responder
138 | )
139 |
140 | print(chain.invoke({"input": "scrum"}))
141 | """
142 | While Scrum has its pros and cons, it is important to recognize that no project management framework is a one-size-fits-all solution. The cons mentioned should be considered in the context of the specific project and organization.
143 |
144 | For example, while Scrum may have a lack of predictability, this can be mitigated by implementing effective estimation techniques and regularly reassessing and adjusting plans. Additionally, while Scrum relies on team communication, organizations can invest in improving communication practices and tools to address any gaps or issues.
145 |
146 | Similarly, while Scrum may have limitations for large projects, organizations can adapt Scrum by implementing scaled agile frameworks like SAFe or LeSS to address complexities and dependencies.
147 |
148 | Furthermore, while Scrum may prioritize working software over comprehensive documentation, it does not mean that documentation is disregarded entirely. Organizations can establish guidelines and processes to ensure that essential documentation is maintained alongside the iterative development.
149 |
150 | Regarding role clarity, organizations can establish clear role definitions and ensure that team members understand their responsibilities and accountabilities. This can be achieved through effective communication and regular feedback.
151 |
152 | Lastly, while Scrum relies on experienced Scrum Masters, organizations can invest in training and development programs to enhance the skills and knowledge of Scrum Masters, ensuring effective facilitation of the Scrum process.
153 |
154 | In conclusion, while Scrum has its limitations, many of these can be addressed and mitigated through proper implementation, adaptation, and organizational support. It is important to carefully consider the specific project and organizational context to determine if Scrum is the right fit and to make necessary adjustments to maximize its benefits and overcome any potential drawbacks.
155 | """
156 |
--------------------------------------------------------------------------------
/lcel/prompt_llm_function_call.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain.prompts import ChatPromptTemplate
6 | from langchain.output_parsers.openai_functions import (
7 | JsonOutputFunctionsParser,
8 | JsonKeyOutputFunctionsParser)
9 | from langchain.schema.runnable import RunnableParallel, RunnablePassthrough
10 |
11 |
12 | prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
13 | model = ChatOpenAI()
14 |
15 | # function call
16 | functions = [
17 | {
18 | "name": "joke",
19 | "description": "A joke",
20 | "parameters": {
21 | "type": "object",
22 | "properties": {
23 | "setup": {"type": "string", "description": "The setup for the joke"},
24 | "punchline": {
25 | "type": "string",
26 | "description": "The punchline for the joke",
27 | },
28 | },
29 | "required": ["setup", "punchline"],
30 | },
31 | }
32 | ]
33 | chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions)
34 | # print(chain.invoke({"topic": "ice cream"}, config={}))
35 | """
36 | content='' additional_kwargs={'function_call': {'arguments': '{\n "setup": "Why did the ice cream go to therapy?",\n "punchline": "Because it was feeling a little melty!"\n}', 'name': 'joke'}}
37 | """
38 |
39 | # chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions) | JsonOutputFunctionsParser()
40 | # print(chain.invoke({"topic": "ice cream"}))
41 | """
42 | {'setup': 'Why did the ice cream go to therapy?', 'punchline': 'Because it had too many sprinkles of anxiety!'}
43 | """
44 |
45 | # chain = prompt | model.bind(function_call={"name": "joke"}, functions=functions) | JsonKeyOutputFunctionsParser(key_name="setup")
46 | # print(chain.invoke({"topic": "ice cream"}))
47 | """
48 | Why did the ice cream go to therapy?
49 | """
50 |
51 | map_ = RunnableParallel(topic=RunnablePassthrough())
52 | chain = (
53 | map_
54 | | prompt
55 | | model.bind(function_call={"name": "joke"}, functions=functions)
56 | | JsonKeyOutputFunctionsParser(key_name="setup")
57 | )
58 | print(chain.invoke("ice cream"))
59 | """
60 | Why did the ice cream go to therapy?
61 | """
62 |
63 | chain = (
64 | {"topic": RunnablePassthrough()}
65 | | prompt
66 | | model.bind(function_call={"name": "joke"}, functions=functions)
67 | | JsonKeyOutputFunctionsParser(key_name="setup")
68 | )
69 | print(chain.invoke("ice cream"))
70 | """
71 | Why did the ice cream break up with the cone?
72 | """
--------------------------------------------------------------------------------
/lcel/prompt_llm_output_parser.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain.prompts import ChatPromptTemplate
6 | from langchain.schema.output_parser import StrOutputParser
7 |
8 | prompt = ChatPromptTemplate.from_template("tell me a short joke about {topic}")
9 | prompt_value = prompt.invoke({"topic": "ice cream"})
10 | """
11 | messages=[HumanMessage(content='tell me a short joke about ice cream')]
12 | """
13 | print(prompt_value.to_string())
14 | """
15 | Human: tell me a short joke about ice cream
16 | """
17 |
18 | model = ChatOpenAI()
19 | message = model.invoke(prompt_value)
20 | """
21 | content='Why did the ice cream go to therapy? \n\nBecause it had too many scoops of emotions!'
22 | """
23 |
24 | # from langchain.llms import OpenAI
25 | # llm = OpenAI(model="gpt-3.5-turbo-instruct")
26 | # llm_message = llm.invoke(prompt_value)
27 | """
28 | Why did the ice cream go to therapy?
29 |
30 | Because it was having a meltdown!
31 | """
32 |
33 | output_parser = StrOutputParser()
34 | print(output_parser.invoke(message))
35 | """
36 | Why did the ice cream go to therapy?
37 |
38 | Because it had a meltdown!
39 | """
40 |
41 | # similar to unix pipe operator
42 | chain = prompt | model | output_parser
43 |
44 | result = chain.invoke({"topic": "ice cream"})
45 | print(result)
46 | """
47 | Why did the ice cream go to therapy?
48 |
49 | Because it had too many sprinkles of anxiety!
50 | # """
51 |
--------------------------------------------------------------------------------
/lcel/querying_sql_db.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain.prompts import ChatPromptTemplate
5 | from langchain_community.utilities.sql_database import SQLDatabase
6 |
7 |
8 | template = """Based on the table schema below, write a SQL query that would answer the user's question:
9 | {schema}
10 |
11 | Question: {question}
12 | SQL Query:"""
13 | prompt = ChatPromptTemplate.from_template(template)
14 |
15 | # sqlite3 Chinook.db
16 | # .read Chinook_Sqlite.sql
17 | # download the sql file from the link below
18 | # https://raw.githubusercontent.com/lerocha/chinook-database/master/ChinookDatabase/DataSources/Chinook_Sqlite.sql
19 |
20 | db = SQLDatabase.from_uri("sqlite:///./Chinook.db")
21 |
22 | def get_schema(_):
23 | return db.get_table_info()
24 |
25 | def run_query(query):
26 | return db.run(query)
27 |
28 | from langchain_openai import ChatOpenAI
29 | from langchain.schema import StrOutputParser
30 | from langchain.schema.runnable import RunnablePassthrough
31 |
32 | model = ChatOpenAI()
33 |
34 | sql_response = (
35 | RunnablePassthrough.assign(schema=get_schema)
36 | | prompt
37 | | model.bind(stop=["\nSQLResult:"])
38 | | StrOutputParser()
39 | )
40 |
41 | print(sql_response.invoke({"question": "How many employees are there?"}))
42 | """
43 | SELECT COUNT(*) FROM Employee
44 | """
45 |
46 | template = """Based on the table schema below, question, sql query, and sql response, write a natural language response:
47 | {schema}
48 |
49 | Question: {question}
50 | SQL Query: {query}
51 | SQL Response: {response}"""
52 | prompt_response = ChatPromptTemplate.from_template(template)
53 |
54 | full_chain = (
55 | RunnablePassthrough.assign(query=sql_response)
56 | | RunnablePassthrough.assign(
57 | schema=get_schema,
58 | response=lambda x: run_query(x["query"]),
59 | )
60 | | prompt_response
61 | | model
62 | )
63 |
64 | print(full_chain.invoke({"question": "How many employees are there?"}))
65 | """
66 | content='There are 8 employees.'
67 | """
68 |
--------------------------------------------------------------------------------
/lcel/rag.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from operator import itemgetter
5 | from langchain_openai import ChatOpenAI
6 | from langchain_openai import OpenAIEmbeddings
7 | from langchain.prompts import ChatPromptTemplate
8 | from langchain.schema.output_parser import StrOutputParser
9 | from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
10 | from langchain_community.vectorstores.faiss import FAISS
11 |
12 | # It requires `pip install langchain openai faiss-cpu tiktoken`
13 | embedding_model = OpenAIEmbeddings()
14 | vectorstore = FAISS.from_texts(
15 | ["harrison worked at kensho"], embedding=embedding_model
16 | )
17 | # save
18 | vectorstore.save_local("faiss_index")
19 |
20 | vectorstore_new = FAISS.load_local("faiss_index", embedding_model)
21 |
22 | retriever = vectorstore_new.as_retriever()
23 |
24 | template = """Answer the question based only on the following context:
25 | {context}
26 |
27 | Question: {question}
28 | """
29 | prompt = ChatPromptTemplate.from_template(template)
30 |
31 | model = ChatOpenAI()
32 |
33 | chain = (
34 | {"context": retriever, "question": RunnablePassthrough()}
35 | | prompt
36 | | model
37 | | StrOutputParser()
38 | )
39 |
40 | print(chain.invoke("where did harrison work?"))
41 | """
42 | Harrison worked at Kensho.
43 | """
44 |
45 | template = """Answer the question based only on the following context:
46 | {context}
47 |
48 | Question: {question}
49 |
50 | Answer in the following language: {language}
51 | """
52 | prompt = ChatPromptTemplate.from_template(template)
53 |
54 | chain = (
55 | {
56 | "context": itemgetter("question") | retriever,
57 | "question": itemgetter("question"),
58 | "language": itemgetter("language"),
59 | }
60 | | prompt
61 | | model
62 | | StrOutputParser()
63 | )
64 |
65 | print(chain.invoke({"question": "where did harrison work", "language": "italian"}))
66 | """
67 | Harrison ha lavorato a Kensho.
68 | """
69 |
70 | # # itemgetter example
71 | # from operator import itemgetter
72 | # # Suppose we have a dictionary
73 | # person = {'name': 'Alice', 'age': 30, 'job': 'Engineer'}
74 | # # We can use itemgetter to create a function that fetches the 'name' from a dictionary
75 | # get_name = itemgetter('name')
76 | # # Now, when we use this function with our dictionary
77 | # name = get_name(person)
78 | # print(name) # Output: Alice
79 |
--------------------------------------------------------------------------------
/lcel/runnable_branch.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain.prompts import PromptTemplate
6 | from langchain.schema.output_parser import StrOutputParser
7 |
8 | chain = (
9 | PromptTemplate.from_template(
10 | """Given the user question below, classify it as either being about `Strawberry`, `Banana`, or `Other`.
11 |
12 | Do not respond with more than one word.
13 |
14 |
15 | {question}
16 |
17 |
18 | Classification:"""
19 | )
20 | | ChatOpenAI()
21 | | StrOutputParser()
22 | )
23 |
24 | print(chain.invoke({"question": "What is the fruit that has red color?"}))
25 | """
26 | Strawberry
27 | """
28 |
29 | strawberry_chain = (
30 | PromptTemplate.from_template(
31 | """You are an expert about strawberry. \
32 | Always answer questions starting with "As a Strawberry expert ... ". \
33 | Respond to the following question:
34 |
35 | # Question: {question}
36 | # Answer:"""
37 | )
38 | | ChatOpenAI()
39 | )
40 |
41 | banana_chain = (
42 | PromptTemplate.from_template(
43 | """You are an expert about banana. \
44 | Always answer questions starting with "As a Banana expert ... ". \
45 | Respond to the following question:
46 |
47 | # Question: {question}
48 | # Answer:"""
49 | )
50 | | ChatOpenAI()
51 | )
52 |
53 | general_chain = (
54 | PromptTemplate.from_template(
55 | """Respond to the following question:
56 |
57 | Question: {question}
58 | Answer:"""
59 | )
60 | | ChatOpenAI()
61 | )
62 |
63 |
64 | from langchain.schema.runnable import RunnableBranch
65 |
66 | # the first element is a condition (a lambda function) and
67 | # the second element is the chain to execute if the condition is true
68 | branch = RunnableBranch(
69 | (lambda x: "strawberry" in x["topic"].lower(), strawberry_chain), # type: ignore
70 | (lambda x: "banana" in x["topic"].lower(), banana_chain), # type: ignore
71 | general_chain,
72 | )
73 |
74 | # chain is invoked to classify the question, and its output is stored under the key topic.
75 | # The original question is passed through unchanged under the key question.
76 | full_chain = {"topic": chain, "question": lambda x: x["question"]} | branch
77 |
78 | print(full_chain.invoke({"question": "What is the fruit that has red color?"}))
79 | print(full_chain.invoke({"question": "What is the fruit that has yellow color?"}))
80 | print(full_chain.invoke({"question": "What is the fruit that has green color?"}))
81 | """
82 | content='As a Strawberry expert, I can tell you that strawberries are the fruit that has a vibrant red color.'
83 | content='As a Banana expert, the fruit that has a yellow color is the banana.'
84 | content='The fruit that has a green color is typically an apple or a lime.'
85 | """
--------------------------------------------------------------------------------
/lcel/runnable_lambda.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from operator import itemgetter
5 | from langchain_openai import ChatOpenAI
6 | from langchain.prompts import ChatPromptTemplate
7 | from langchain.schema.runnable import RunnableLambda
8 |
9 | def length_function(text):
10 | return len(text)
11 |
12 | def _multiple_length_function(text1, text2):
13 | return len(text1) * len(text2)
14 |
15 | def multiple_length_function(_dict):
16 | return _multiple_length_function(_dict["text1"], _dict["text2"])
17 |
18 | prompt = ChatPromptTemplate.from_template("what is {a} + {b}")
19 | model = ChatOpenAI()
20 | chain = (
21 | {
22 | "a": itemgetter("foo") | RunnableLambda(length_function),
23 | "b": {"text1": itemgetter("foo"), "text2": itemgetter("bar")}
24 | | RunnableLambda(multiple_length_function),
25 | }
26 | | prompt
27 | | model
28 | )
29 | print(chain.invoke({"foo": "bar", "bar": "gah"}))
30 | """
31 | content='3 + 9 = 12'
32 | """
--------------------------------------------------------------------------------
/lcel/runnable_parallel.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from operator import itemgetter
5 | from langchain.schema.runnable import RunnableParallel, RunnablePassthrough
6 |
7 | runnable = RunnableParallel(
8 | passed=RunnablePassthrough()
9 | )
10 |
11 | print(runnable.invoke({"num": 1}))
12 | """
13 | {'passed': {'num': 1}}
14 | """
15 |
16 | runnable = RunnableParallel(
17 | passed=RunnablePassthrough(),
18 | extra=RunnablePassthrough.assign(mult=lambda x: x["num"] * 3),
19 | modified=lambda x: x["num"] + 1,
20 | )
21 |
22 | print(runnable.invoke({"num": 1}))
23 | """
24 | {'passed': {'num': 1}, 'extra': {'num': 1, 'mult': 3}, 'modified': 2}
25 | """
26 |
27 | from langchain_openai import ChatOpenAI
28 | from langchain.prompts import ChatPromptTemplate
29 | from langchain.schema.runnable import RunnableParallel
30 |
31 | model = ChatOpenAI()
32 |
33 | joke_chain = ChatPromptTemplate.from_template("tell me a joke about {topic}") | model
34 | poem_chain = (
35 | ChatPromptTemplate.from_template("write a 2-line poem about {topic}") | model
36 | )
37 |
38 | # easy to execute multiple Runnables in parallel
39 | map_chain = RunnableParallel(joke=joke_chain, poem=poem_chain)
40 |
41 | print(map_chain.invoke({"topic": "bear"}))
42 | """
43 | {
44 | 'joke': AIMessage(content="Why did the bear break up with his girlfriend? \n\nBecause he couldn't bear the relationship any longer!"),
45 | 'poem': AIMessage(content='In the dark woods, a bear roams free,\nA majestic creature, wild and full of mystery.')
46 | }
47 | """
48 |
--------------------------------------------------------------------------------
/llm_chatmodels.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import OpenAI, ChatOpenAI
5 |
6 | # Configure OpenAI API key
7 | # export OPENAI_API_KEY=""
8 |
9 | llm = OpenAI()
10 | chat_model = ChatOpenAI()
11 |
12 | from langchain_core.messages import HumanMessage, SystemMessage
13 |
14 | text = "What would be a good company name for a company that makes colorful socks?"
15 | messages = [SystemMessage(content="You are the teenager"),
16 | HumanMessage(content=text)]
17 |
18 | # Takes in a string, returns a string.
19 | print(llm.invoke(text))
20 |
21 | # Takes in a list of BaseMessage, returns a BaseMessage.
22 | print(chat_model.invoke(messages))
23 |
--------------------------------------------------------------------------------
/mcp/README.md:
--------------------------------------------------------------------------------
1 | # MCP
2 | - Reference: https://github.com/langchain-ai/langchain-mcp-adapters
3 |
4 | # installation
5 | ```bash
6 | virtualenv --python= venv
7 | source venv/bin/activate
8 | pip install -r requirements.txt
9 | ```
--------------------------------------------------------------------------------
/mcp/client.py:
--------------------------------------------------------------------------------
1 | # Imports Python's built-in asyncio module, which is used to run asynchronous code using async/await.
2 | import asyncio
3 |
4 | # ClientSession: manages a session with an MCP-compliant tool or service.
5 | # StdioServerParameters: used to specify how to start the tool (like a subprocess).
6 | from mcp import ClientSession, StdioServerParameters
7 |
8 | # connects to a tool over standard input/output.
9 | from mcp.client.stdio import stdio_client
10 |
11 | # Imports a helper function that loads tools that support the MCP protocol, making them compatible with LangChain.
12 | from langchain_mcp_adapters.tools import load_mcp_tools
13 |
14 | # Imports a function to create an agent that follows the ReAct pattern (Reasoning + Acting) from LangGraph.
15 | # ReAct agents can use tools and think step-by-step.
16 | from langgraph.prebuilt import create_react_agent
17 |
18 | # Imports the OpenAI chat model interface from LangChain.
19 | from langchain_openai import ChatOpenAI
20 | model = ChatOpenAI(model="gpt-4o")
21 |
22 | # Prepares the parameters to launch a tool server via math_server.py using Python.
23 | server_params = StdioServerParameters(
24 | command="python",
25 | # Make sure to update to the full absolute path to your math_server.py file
26 | args=["/Users/seungjoonlee/git/learn-langchain/mcp/math_server.py"],
27 | )
28 |
29 | # Defines an asynchronous main function.
30 | async def main():
31 | # Starts the math_server.py subprocess and establishes a connection using stdin and stdout.
32 | # Returns read and write streams for communication.
33 | async with stdio_client(server_params) as (read, write):
34 | # Wraps the read/write streams in a ClientSession to interact with the tool more easily.
35 | async with ClientSession(read, write) as session:
36 | # Initialize the connection
37 | await session.initialize()
38 |
39 | # Loads the tools exposed by the running math_server.py.
40 | # These tools are now in a format that the LangChain agent can use.
41 | tools = await load_mcp_tools(session)
42 |
43 | # Creates an agent that can reason and call the MCP tools using the GPT-4o model.
44 | agent = create_react_agent(model, tools)
45 |
46 | # Invokes the agent asynchronously and gives it a user message.
47 | # The agent will process the question, possibly call the math tool, and return a response.
48 | agent_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
49 | print(agent_response)
50 |
51 | # Run the async main function
52 | if __name__ == "__main__":
53 | asyncio.run(main())
54 |
--------------------------------------------------------------------------------
/mcp/math_server.py:
--------------------------------------------------------------------------------
1 | # Imports FastMCP, a lightweight framework for exposing Python functions as MCP-compatible tools.
2 | # This lets other programs (like agents) call your Python functions over a standard interface (like stdio or HTTP).
3 | from mcp.server.fastmcp import FastMCP
4 |
5 | # Creates an instance of FastMCP and names the tool "Math".
6 | # This name is optional, but it's helpful for debugging or when managing multiple tools.
7 | mcp = FastMCP("Math")
8 |
9 | # The @mcp.tool() decorator exposes this function as a callable tool via MCP.
10 | @mcp.tool()
11 | def add(a: int, b: int) -> int:
12 | """Add two numbers"""
13 | return a + b
14 |
15 | @mcp.tool()
16 | def multiply(a: int, b: int) -> int:
17 | """Multiply two numbers"""
18 | return a * b
19 |
20 | if __name__ == "__main__":
21 | # If this script is run directly, it starts the MCP server using stdio (standard input/output).
22 | # This allows the agent (in your first script) to connect to this tool by launching it as a subprocess
23 | mcp.run(transport="stdio")
24 |
--------------------------------------------------------------------------------
/mcp/mcp_doc_messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "messages": [
3 | {
4 | "type": "HumanMessage",
5 | "content": "how does langchain chatbot works? check the latest documenation. but make it short as 5 lines",
6 | "additional_kwargs": {},
7 | "response_metadata": {},
8 | "id": "f5f461cc-05a7-402e-9b81-3d6919930627"
9 | },
10 | {
11 | "type": "AIMessage",
12 | "content": "",
13 | "additional_kwargs": {
14 | "tool_calls": [
15 | {
16 | "id": "call_Yy1lavSk3GyKWka30ETksAkw",
17 | "function": {
18 | "arguments": "{}",
19 | "name": "list_doc_sources"
20 | },
21 | "type": "function"
22 | }
23 | ],
24 | "refusal": null
25 | },
26 | "response_metadata": {
27 | "token_usage": {
28 | "completion_tokens": 12,
29 | "prompt_tokens": 232,
30 | "total_tokens": 244
31 | },
32 | "model_name": "gpt-4o-mini-2024-07-18",
33 | "finish_reason": "tool_calls"
34 | },
35 | "id": "run-cb28ae21-5ae4-4c71-9fa1-cc08f9b2dbdd-0"
36 | },
37 | {
38 | "type": "ToolMessage",
39 | "content": "LangChain\nURL: https://python.langchain.com/llms.txt\n\n",
40 | "name": "list_doc_sources",
41 | "id": "7405d543-3795-4ed7-b774-318b555ddf38",
42 | "tool_call_id": "call_Yy1lavSk3GyKWka30ETksAkw"
43 | },
44 | {
45 | "type": "AIMessage",
46 | "content": "",
47 | "additional_kwargs": {
48 | "tool_calls": [
49 | {
50 | "id": "call_csnsmJMuK3KyMs61ZUiikbTH",
51 | "function": {
52 | "arguments": "{\"url\":\"https://python.langchain.com/llms.txt\"}",
53 | "name": "fetch_docs"
54 | },
55 | "type": "function"
56 | }
57 | ],
58 | "refusal": null
59 | },
60 | "response_metadata": {
61 | "token_usage": {
62 | "completion_tokens": 24,
63 | "prompt_tokens": 268,
64 | "total_tokens": 292
65 | },
66 | "model_name": "gpt-4o-mini-2024-07-18",
67 | "finish_reason": "tool_calls"
68 | },
69 | "id": "run-97326a71-27b6-44f3-8173-8bb8b8fd903a-0"
70 | },
71 | {
72 | "type": "ToolMessage",
73 | "content": "# LangChain\n## High level\n[Why LangChain?](https://python.langchain.com/docs/concepts/why_langchain/): considering using LangChain, when building complex AI applications, and when needing to evaluate AI applications This page discusses the main reasons to use LangChain: standardized component interfaces, orchestration capabilities, and observability/evaluation through L...tool calling, and structured outputs. The architecture supports multimodal data, allowing text, images, and other formats in interactions. Additionally, the framework includes memory management for maintaining conversation context. By leveraging these components, developers can create dynamic and interactive chatbot applications effectively.",
74 | "additional_kwargs": {
75 | "refusal": null
76 | },
77 | "response_metadata": {
78 | "token_usage": {
79 | "completion_tokens": 83,
80 | "prompt_tokens": 26007,
81 | "total_tokens": 26090
82 | },
83 | "model_name": "gpt-4o-mini-2024-07-18",
84 | "finish_reason": "stop"
85 | },
86 | "id": "run-3801de5d-bf5c-42c6-9152-4aec779badda-0"
87 | },
88 | {
89 | "type": "AIMessage",
90 | "content": "LangChain chatbot operates by utilizing chat models that facilitate conversation through structured messaging. It integrates various components such as tools for functionality and memory for context management. The framework supports advanced techniques like tool calling for external functions, structured outputs for formatted responses, and multimodal inputs compatible with text and media. Additionally, it effectively manages chat history to retain context for better interaction. By connecting these elements, LangChain enables the creation of responsive and context-aware conversational agents.",
91 | "additional_kwargs": {
92 | "refusal": null
93 | },
94 | "response_metadata": {
95 | "token_usage": {
96 | "completion_tokens": 92,
97 | "prompt_tokens": 26007,
98 | "total_tokens": 26099,
99 | "completion_tokens_details": {
100 | "accepted_prediction_tokens": 0,
101 | "audio_tokens": 0,
102 | "reasoning_tokens": 0,
103 | "rejected_prediction_tokens": 0
104 | },
105 | "prompt_tokens_details": {
106 | "audio_tokens": 0,
107 | "cached_tokens": 0
108 | }
109 | },
110 | "model_name": "gpt-4o-mini-2024-07-18",
111 | "system_fingerprint": "fp_b376dfbbd5",
112 | "id": "chatcmpl-BIUYRlwT3cKoOREZxe2d6IIk1YWp5",
113 | "finish_reason": "stop",
114 | "logprobs": null
115 | },
116 | "id": "run-9f71886f-18a7-4f13-ac5c-18dfdbc920fd-0",
117 | "usage_metadata": {
118 | "input_tokens": 26007,
119 | "output_tokens": 92,
120 | "total_tokens": 26099,
121 | "input_token_details": {
122 | "audio": 0,
123 | "cache_read": 0
124 | },
125 | "output_token_details": {
126 | "audio": 0,
127 | "reasoning": 0
128 | }
129 | }
130 | }
131 | ]
132 | }
133 |
--------------------------------------------------------------------------------
/mcp/mcpdoc_server.py:
--------------------------------------------------------------------------------
1 | # Imports Python's built-in asyncio module, which is used to run asynchronous code using async/await.
2 | import asyncio
3 |
4 | # Import MultiServerMCPClient to connect to multiple servers at once.
5 | from langchain_mcp_adapters.client import MultiServerMCPClient
6 |
7 | # Imports a function to create an agent that follows the ReAct pattern (Reasoning + Acting) from LangGraph.
8 | # ReAct agents can use tools and think step-by-step.
9 | from langgraph.prebuilt import create_react_agent
10 |
11 | # Imports the OpenAI chat model interface from LangChain.
12 | from langchain_openai import ChatOpenAI
13 | model = ChatOpenAI(model="gpt-4o-mini")
14 |
15 | # Defines an asynchronous main function.
16 | async def main():
17 | async with MultiServerMCPClient(
18 | {
19 | "langgraph-docs-mcp": {
20 | "url": "http://localhost:8082/sse",
21 | "transport": "sse",
22 | } # type: ignore
23 | }
24 | ) as client:
25 | agent = create_react_agent(model, client.get_tools())
26 | langgraph_response = await agent.ainvoke({"messages": "how does langchain chatbot works? check the latest documenation. but make it short as 5 lines"})
27 | print(langgraph_response)
28 |
29 | # Run the async main function
30 | if __name__ == "__main__":
31 | asyncio.run(main())
32 |
--------------------------------------------------------------------------------
/mcp/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "messages": [
3 | {
4 | "type": "HumanMessage",
5 | "content": "what's (3 + 5) x 12?",
6 | "additional_kwargs": {},
7 | "response_metadata": {},
8 | "id": "ee77cf94-5720-4090-ac63-29c10202b275"
9 | },
10 | {
11 | "type": "AIMessage",
12 | "content": "",
13 | "additional_kwargs": {
14 | "tool_calls": [
15 | {
16 | "id": "call_ANj2x44sYmCiLDikYBRzfwnf",
17 | "function": {
18 | "arguments": "{\"a\": 3, \"b\": 5}",
19 | "name": "add"
20 | },
21 | "type": "function"
22 | },
23 | {
24 | "id": "call_QbDXKPgWbIFMaDNl3H11uxGM",
25 | "function": {
26 | "arguments": "{\"a\": 8, \"b\": 12}",
27 | "name": "multiply"
28 | },
29 | "type": "function"
30 | }
31 | ],
32 | "refusal": null
33 | },
34 | "response_metadata": {
35 | "token_usage": {
36 | "completion_tokens": 51,
37 | "prompt_tokens": 77,
38 | "total_tokens": 128,
39 | "completion_tokens_details": {
40 | "accepted_prediction_tokens": 0,
41 | "audio_tokens": 0,
42 | "reasoning_tokens": 0,
43 | "rejected_prediction_tokens": 0
44 | },
45 | "prompt_tokens_details": {
46 | "audio_tokens": 0,
47 | "cached_tokens": 0
48 | }
49 | },
50 | "model_name": "gpt-4o-2024-08-06",
51 | "system_fingerprint": "fp_6dd05565ef",
52 | "id": "chatcmpl-BGI6hIzVveFo1yl3bUbCxZOcTS0ly",
53 | "finish_reason": "tool_calls",
54 | "logprobs": null
55 | },
56 | "id": "run-4981eb3e-dc9d-48cf-8555-220b8d24f829-0",
57 | "tool_calls": [
58 | {
59 | "name": "add",
60 | "args": {
61 | "a": 3,
62 | "b": 5
63 | },
64 | "id": "call_ANj2x44sYmCiLDikYBRzfwnf",
65 | "type": "tool_call"
66 | },
67 | {
68 | "name": "multiply",
69 | "args": {
70 | "a": 8,
71 | "b": 12
72 | },
73 | "id": "call_QbDXKPgWbIFMaDNl3H11uxGM",
74 | "type": "tool_call"
75 | }
76 | ],
77 | "usage_metadata": {
78 | "input_tokens": 77,
79 | "output_tokens": 51,
80 | "total_tokens": 128,
81 | "input_token_details": {
82 | "audio": 0,
83 | "cache_read": 0
84 | },
85 | "output_token_details": {
86 | "audio": 0,
87 | "reasoning": 0
88 | }
89 | }
90 | },
91 | {
92 | "type": "ToolMessage",
93 | "content": "8",
94 | "name": "add",
95 | "id": "3fed1876-1c6a-47ef-95ea-651e33e47f39",
96 | "tool_call_id": "call_ANj2x44sYmCiLDikYBRzfwnf"
97 | },
98 | {
99 | "type": "ToolMessage",
100 | "content": "96",
101 | "name": "multiply",
102 | "id": "21102f77-fddd-4a2c-a885-de9b9ec8269a",
103 | "tool_call_id": "call_QbDXKPgWbIFMaDNl3H11uxGM"
104 | },
105 | {
106 | "type": "AIMessage",
107 | "content": "The result of \\((3 + 5) \\times 12\\) is 96.",
108 | "additional_kwargs": {
109 | "refusal": null
110 | },
111 | "response_metadata": {
112 | "token_usage": {
113 | "completion_tokens": 22,
114 | "prompt_tokens": 143,
115 | "total_tokens": 165,
116 | "completion_tokens_details": {
117 | "accepted_prediction_tokens": 0,
118 | "audio_tokens": 0,
119 | "reasoning_tokens": 0,
120 | "rejected_prediction_tokens": 0
121 | },
122 | "prompt_tokens_details": {
123 | "audio_tokens": 0,
124 | "cached_tokens": 0
125 | }
126 | },
127 | "model_name": "gpt-4o-2024-08-06",
128 | "system_fingerprint": "fp_6dd05565ef",
129 | "id": "chatcmpl-BGI6hmjJs0RLcha8AO4sUT1bEZgo4",
130 | "finish_reason": "stop",
131 | "logprobs": null
132 | },
133 | "id": "run-4d093615-ecd4-4918-bbe6-533ec590ccca-0",
134 | "usage_metadata": {
135 | "input_tokens": 143,
136 | "output_tokens": 22,
137 | "total_tokens": 165,
138 | "input_token_details": {
139 | "audio": 0,
140 | "cache_read": 0
141 | },
142 | "output_token_details": {
143 | "audio": 0,
144 | "reasoning": 0
145 | }
146 | }
147 | }
148 | ]
149 | }
--------------------------------------------------------------------------------
/mcp/multi_server_client.py:
--------------------------------------------------------------------------------
1 | # Imports Python's built-in asyncio module, which is used to run asynchronous code using async/await.
2 | import asyncio
3 |
4 | # Import MultiServerMCPClient to connect to multiple servers at once.
5 | from langchain_mcp_adapters.client import MultiServerMCPClient
6 |
7 | # Imports a function to create an agent that follows the ReAct pattern (Reasoning + Acting) from LangGraph.
8 | # ReAct agents can use tools and think step-by-step.
9 | from langgraph.prebuilt import create_react_agent
10 |
11 | # Imports the OpenAI chat model interface from LangChain.
12 | from langchain_openai import ChatOpenAI
13 | model = ChatOpenAI(model="gpt-4o-mini")
14 |
15 | # Defines an asynchronous main function.
16 | async def main():
17 | async with MultiServerMCPClient(
18 | {
19 | # "math": {
20 | # "command": "python",
21 | # # Make sure to update to the full absolute path to your math_server.py file
22 | # "args": ["/Users/seungjoonlee/git/learn-langchain/mcp/math_server.py"],
23 | # "transport": "stdio",
24 | # },
25 | # "weather": {
26 | # # make sure you start your weather server on port 8000
27 | # "url": "http://localhost:8000/sse",
28 | # "transport": "sse",
29 | # },
30 | "langgraph-docs-mcp": {
31 | "url": "http://localhost:8082/sse",
32 | "transport": "sse",
33 | }
34 | } # type: ignore
35 | ) as client:
36 | agent = create_react_agent(model, client.get_tools())
37 | # math_response = await agent.ainvoke({"messages": "what's (3 + 5) x 12?"})
38 | # print(math_response)
39 | # weather_response = await agent.ainvoke({"messages": "what is the weather in nyc?"})
40 | # print(weather_response)
41 | langgraph_response = await agent.ainvoke({"messages": "how does langchain chatbot works? check the latest documenation. but make it short as 5 lines"})
42 | print(langgraph_response)
43 |
44 | # Run the async main function
45 | if __name__ == "__main__":
46 | asyncio.run(main())
47 |
--------------------------------------------------------------------------------
/mcp/requirements.txt:
--------------------------------------------------------------------------------
1 | mcp
2 | httpx
3 | langchain
4 | langchain-core
5 | langchain-community
6 | langchain-groq
7 | langchain-ollama
8 | langchain_mcp_adapters
9 | langchain_openai
10 | langgraph
11 |
--------------------------------------------------------------------------------
/mcp/weather_messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "messages": [
3 | {
4 | "type": "HumanMessage",
5 | "content": "what is the weather in nyc?",
6 | "additional_kwargs": {},
7 | "response_metadata": {},
8 | "id": "8b715c11-b901-43f8-b898-a7472dd8334c"
9 | },
10 | {
11 | "type": "AIMessage",
12 | "content": "",
13 | "additional_kwargs": {
14 | "tool_calls": [
15 | {
16 | "id": "call_LzlW2VG0SwTep5Qfyj4lxSk0",
17 | "function": {
18 | "arguments": "{\"location\":\"New York City\"}",
19 | "name": "get_weather"
20 | },
21 | "type": "function"
22 | }
23 | ],
24 | "refusal": null
25 | },
26 | "response_metadata": {
27 | "token_usage": {
28 | "completion_tokens": 17,
29 | "prompt_tokens": 92,
30 | "total_tokens": 109,
31 | "completion_tokens_details": {
32 | "accepted_prediction_tokens": 0,
33 | "audio_tokens": 0,
34 | "reasoning_tokens": 0,
35 | "rejected_prediction_tokens": 0
36 | },
37 | "prompt_tokens_details": {
38 | "audio_tokens": 0,
39 | "cached_tokens": 0
40 | }
41 | },
42 | "model_name": "gpt-4o-2024-08-06",
43 | "system_fingerprint": "fp_6dd05565ef",
44 | "id": "chatcmpl-BGUADKUBkqShPoK0BQg17qwxjNFAQ",
45 | "finish_reason": "tool_calls",
46 | "logprobs": null
47 | },
48 | "id": "run-5183e6d7-4820-4c6e-9f25-d9e174cf6fd5-0",
49 | "tool_calls": [
50 | {
51 | "name": "get_weather",
52 | "args": {
53 | "location": "New York City"
54 | },
55 | "id": "call_LzlW2VG0SwTep5Qfyj4lxSk0",
56 | "type": "tool_call"
57 | }
58 | ],
59 | "usage_metadata": {
60 | "input_tokens": 92,
61 | "output_tokens": 17,
62 | "total_tokens": 109,
63 | "input_token_details": {
64 | "audio": 0,
65 | "cache_read": 0
66 | },
67 | "output_token_details": {
68 | "audio": 0,
69 | "reasoning": 0
70 | }
71 | }
72 | },
73 | {
74 | "type": "ToolMessage",
75 | "content": "It's always sunny in New York",
76 | "name": "get_weather",
77 | "id": "53302019-e212-4f0b-b3e0-e8e623949e17",
78 | "tool_call_id": "call_LzlW2VG0SwTep5Qfyj4lxSk0"
79 | },
80 | {
81 | "type": "AIMessage",
82 | "content": "The weather in New York City is currently sunny.",
83 | "additional_kwargs": {
84 | "refusal": null
85 | },
86 | "response_metadata": {
87 | "token_usage": {
88 | "completion_tokens": 12,
89 | "prompt_tokens": 122,
90 | "total_tokens": 134,
91 | "completion_tokens_details": {
92 | "accepted_prediction_tokens": 0,
93 | "audio_tokens": 0,
94 | "reasoning_tokens": 0,
95 | "rejected_prediction_tokens": 0
96 | },
97 | "prompt_tokens_details": {
98 | "audio_tokens": 0,
99 | "cached_tokens": 0
100 | }
101 | },
102 | "model_name": "gpt-4o-2024-08-06",
103 | "system_fingerprint": "fp_6dd05565ef",
104 | "id": "chatcmpl-BGUAERtv9wg4bgjUEEpfRt8gjBGUR",
105 | "finish_reason": "stop",
106 | "logprobs": null
107 | },
108 | "id": "run-d0eae9b6-d941-44e9-bb41-89ddd69d5371-0",
109 | "usage_metadata": {
110 | "input_tokens": 122,
111 | "output_tokens": 12,
112 | "total_tokens": 134,
113 | "input_token_details": {
114 | "audio": 0,
115 | "cache_read": 0
116 | },
117 | "output_token_details": {
118 | "audio": 0,
119 | "reasoning": 0
120 | }
121 | }
122 | }
123 | ]
124 | }
--------------------------------------------------------------------------------
/mcp/weather_server.py:
--------------------------------------------------------------------------------
1 | # weather_server.py
2 | from typing import List
3 | from mcp.server.fastmcp import FastMCP
4 |
5 | mcp = FastMCP("Weather")
6 |
7 | @mcp.tool()
8 | async def get_weather(location: str) -> str:
9 | """Get weather for location."""
10 | return "It's always sunny in New York"
11 |
12 | if __name__ == "__main__":
13 | mcp.run(transport="sse")
14 |
--------------------------------------------------------------------------------
/memory/adding_memory.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from operator import itemgetter
5 | from langchain_openai import ChatOpenAI
6 | from langchain.memory import ConversationBufferMemory
7 | from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
8 | from langchain.schema.runnable import RunnableLambda, RunnablePassthrough
9 |
10 | model = ChatOpenAI()
11 | prompt = ChatPromptTemplate.from_messages(
12 | [
13 | ("system", "You are a helpful chatbot"),
14 | MessagesPlaceholder(variable_name="history"),
15 | ("human", "{input}"),
16 | ]
17 | )
18 |
19 | memory = ConversationBufferMemory(return_messages=True)
20 |
21 | chain = (
22 | RunnablePassthrough.assign(
23 | history=RunnableLambda(memory.load_memory_variables) | itemgetter("history")
24 | )
25 | | prompt
26 | | model
27 | )
28 |
29 | inputs = {"input": "Hello, My name is Joon"}
30 | response = chain.invoke(inputs)
31 | print(response)
32 | """
33 | content="Hello Joon! It's nice to meet you. How can I assist you today?"
34 | """
35 | memory.save_context(inputs, {"output": response.content}) # type: ignore
36 |
37 | print(memory.load_memory_variables({}))
38 | """
39 | {'history': [HumanMessage(content='Hello, My name is Joon'), AIMessage(content='Hello Joon! How can I assist you today?')]}
40 | """
41 |
42 | inputs = {"input": "whats my name"}
43 | response = chain.invoke(inputs)
44 | print(response)
45 | """
46 | content='Your name is Joon. How can I assist you further, Joon?
47 | """
48 |
--------------------------------------------------------------------------------
/memory/conversation_buffer_window_memory.py:
--------------------------------------------------------------------------------
1 | from langchain.memory import ConversationBufferWindowMemory
2 |
3 | memory = ConversationBufferWindowMemory(k=1)
4 | memory.save_context({"input": "hi"}, {"output": "whats up"})
5 | memory.save_context({"input": "not much you"}, {"output": "not much"})
6 |
7 | print(memory.load_memory_variables({}))
8 | """
9 | {'history': 'Human: not much you\nAI: not much'}
10 | """
11 |
12 | memory = ConversationBufferWindowMemory(k=1, return_messages=True)
13 | memory.save_context({"input": "hi"}, {"output": "whats up"})
14 | memory.save_context({"input": "not much you"}, {"output": "not much"})
15 |
16 | print(memory.load_memory_variables({}))
17 | """
18 | {'history': [HumanMessage(content='not much you'), AIMessage(content='not much')]}
19 | """
20 |
21 |
--------------------------------------------------------------------------------
/memory/conversation_summary_buffer_memory.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import OpenAI
5 | from langchain.memory import ConversationSummaryBufferMemory
6 |
7 | llm = OpenAI()
8 |
9 | memory = ConversationSummaryBufferMemory(llm=llm, max_token_limit=10)
10 | memory.save_context({"input": "hi"}, {"output": "whats up"})
11 | memory.save_context({"input": "not much you"}, {"output": "not much"})
12 |
13 | print(memory.load_memory_variables({}))
14 | """
15 | {'history': "System: \nThe human greets the AI and the AI responds asking what's up.\nHuman: not much you\nAI: not much"}
16 | """
17 |
18 | memory = ConversationSummaryBufferMemory(
19 | llm=llm, max_token_limit=10, return_messages=True
20 | )
21 | memory.save_context({"input": "hi"}, {"output": "whats up"})
22 | memory.save_context({"input": "not much you"}, {"output": "not much"})
23 |
24 | print(memory.load_memory_variables({}))
25 | """
26 | {'history': [
27 | SystemMessage(content="\nThe human greets the AI. The AI responds by asking what's up."),
28 | HumanMessage(content='not much you'),
29 | AIMessage(content='not much')]}
30 | """
31 |
32 | messages = memory.chat_memory.messages
33 | previous_summary = ""
34 | print(memory.predict_new_summary(messages, previous_summary))
35 | """
36 | The human and AI exchange pleasantries and express that there is not much going on.
37 | """
38 |
--------------------------------------------------------------------------------
/memory/conversation_summary_memory.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain.memory import ConversationSummaryMemory, ChatMessageHistory
5 | from langchain_openai import OpenAI
6 |
7 | memory = ConversationSummaryMemory(llm=OpenAI(temperature=0))
8 | memory.save_context({"input": "hi"}, {"output": "whats up"})
9 |
10 | print(memory.load_memory_variables({}))
11 | """
12 | {'history': '\nThe human greets the AI, to which the AI responds.'}
13 | """
14 |
15 | memory = ConversationSummaryMemory(llm=OpenAI(temperature=0), return_messages=True)
16 | memory.save_context({"input": "hi"}, {"output": "whats up"})
17 |
18 | # print(memory.load_memory_variables({}))
19 | """
20 | {'history': [SystemMessage(content='\nThe human greets the AI, to which the AI responds.')]}
21 | """
22 |
23 | # Directly use the memory
24 | messages = memory.chat_memory.messages
25 | """
26 | [HumanMessage(content='hi'), AIMessage(content='whats up')]
27 | """
28 | previous_summary = ""
29 | print(memory.predict_new_summary(messages, previous_summary))
30 | """
31 | The human greets the AI, to which the AI responds.
32 | """
33 |
34 | # Initializing with messages/existing summary
35 | history = ChatMessageHistory()
36 | history.add_user_message("hi")
37 | history.add_ai_message("hi there!")
38 |
39 | memory = ConversationSummaryMemory.from_messages(
40 | llm=OpenAI(temperature=0),
41 | chat_memory=history,
42 | return_messages=True
43 | )
44 | print(memory.buffer)
45 | """
46 | The human greets the AI, to which the AI responds with a friendly greeting.
47 | """
48 |
49 | # summary initialization
50 | memory = ConversationSummaryMemory(
51 | llm=OpenAI(temperature=0),
52 | buffer="The human asks what the AI thinks of artificial intelligence. The AI thinks artificial intelligence is a force for good because it will help humans reach their full potential.",
53 | chat_memory=history,
54 | return_messages=True
55 | )
56 | print(memory.buffer)
57 | """
58 | The human asks what the AI thinks of artificial intelligence. The AI thinks artificial intelligence is a force for good because it will help humans reach their full potential.
59 | """
--------------------------------------------------------------------------------
/memory/entity.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import OpenAI
5 | from langchain.memory import ConversationEntityMemory
6 |
7 | llm = OpenAI(temperature=0)
8 | memory = ConversationEntityMemory(llm=llm)
9 | _input = {"input": "Deven & Sam are working on a hackathon project"}
10 | memory.load_memory_variables(_input)
11 | memory.save_context(
12 | _input,
13 | {"output": " That sounds like a great project! What kind of project are they working on?"}
14 | )
15 |
16 | print(memory.load_memory_variables({"input": 'who is Sam'}))
17 | """
18 | {'history': 'Human: Deven & Sam are working on a hackathon project\n
19 | AI: That sounds like a great project! What kind of project are they working on?',
20 | 'entities': {'Sam': 'Sam is working on a hackathon project with Deven.'}}
21 | """
22 |
23 | print(memory.load_memory_variables({"input": 'who is Deven'}))
24 | """
25 | {'history': 'Human: Deven & Sam are working on a hackathon project\n
26 | AI: That sounds like a great project! What kind of project are they working on?',
27 | 'entities': {
28 | 'Deven': 'Deven is working on a hackathon project with Sam.',
29 | 'Sam': 'Sam is working on a hackathon project with Deven.'}}
30 | """
--------------------------------------------------------------------------------
/memory/memory_example.py:
--------------------------------------------------------------------------------
1 | from langchain.memory import ConversationBufferMemory
2 |
3 | memory = ConversationBufferMemory()
4 | memory.chat_memory.add_user_message("hi!")
5 | memory.chat_memory.add_ai_message("what's up?")
6 |
7 | print(memory.load_memory_variables({}))
8 | """
9 | {'history': "Human: hi!\nAI: what's up?"}
10 | """
11 |
12 | # memory key change
13 | memory = ConversationBufferMemory(memory_key="chat_history")
14 | memory.chat_memory.add_user_message("hi!")
15 | memory.chat_memory.add_ai_message("what's up?")
16 |
17 | print(memory.load_memory_variables({}))
18 | """
19 | {'chat_history': "Human: hi!\nAI: what's up?"}
20 | """
21 |
22 | # return in str type or list type
23 | memory = ConversationBufferMemory(return_messages=True)
24 | memory.chat_memory.add_user_message("hi!")
25 | memory.chat_memory.add_ai_message("what's up?")
26 |
27 | print(memory.load_memory_variables({}))
28 | """
29 | {'history': [HumanMessage(content='hi!'), AIMessage(content="what's up?")]}
30 | """
--------------------------------------------------------------------------------
/output_parser.py:
--------------------------------------------------------------------------------
1 | from langchain.schema import BaseOutputParser
2 |
3 | class CommaSeparatedListOutputParser(BaseOutputParser):
4 | """Parse the output of an LLM call to a comma-separated list."""
5 |
6 |
7 | def parse(self, text: str):
8 | """Parse the output of an LLM call."""
9 | return text.strip().split(", ")
10 |
11 | # When LLM returns the response in text format
12 | print(CommaSeparatedListOutputParser().parse("hi, bye"))
13 | # >> ['hi', 'bye']
--------------------------------------------------------------------------------
/output_parsers/auto_fixing_parser.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import ChatOpenAI
5 | from langchain.output_parsers import PydanticOutputParser
6 | from langchain.pydantic_v1 import BaseModel, Field
7 | from typing import List
8 |
9 | class Actor(BaseModel):
10 | name: str = Field(description="name of an actor")
11 | film_names: List[str] = Field(description="list of names of films they starred in")
12 |
13 | actor_query = "Generate the filmography for a random actor."
14 |
15 | parser = PydanticOutputParser(pydantic_object=Actor)
16 |
17 | # assuming we got the misformmated response i.e single quote instead of double quote
18 | misformatted = "{'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}"
19 | try:
20 | parser.parse(misformatted)
21 | """
22 | Traceback (most recent call last):
23 | File "/Users/seungjoonlee/git/learn-langchain/venv/lib/python3.10/site-packages/langchain/output_parsers/pydantic.py", line 27, in parse
24 | json_object = json.loads(json_str, strict=False)
25 | File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/__init__.py", line 359, in loads
26 | return cls(**kw).decode(s)
27 | File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py", line 337, in decode
28 | obj, end = self.raw_decode(s, idx=_w(s, 0).end())
29 | File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/json/decoder.py", line 353, in raw_decode
30 | obj, end = self.scan_once(s, idx)
31 | json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
32 |
33 | During handling of the above exception, another exception occurred:
34 |
35 | Traceback (most recent call last):
36 | File "/Users/seungjoonlee/git/learn-langchain/output_parsers/auto_fixing_parser.py", line 15, in
37 | print(parser.parse(misformatted))
38 | File "/Users/seungjoonlee/git/learn-langchain/venv/lib/python3.10/site-packages/langchain/output_parsers/pydantic.py", line 33, in parse
39 | raise OutputParserException(msg, llm_output=text)
40 | langchain.schema.output_parser.OutputParserException: Failed to parse Actor from completion {'name': 'Tom Hanks', 'film_names': ['Forrest Gump']}. Got: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
41 | """
42 | except Exception as e:
43 | print("Got an error!!!!! trying with OutputFixingParser...")
44 | from langchain.output_parsers import OutputFixingParser
45 |
46 | new_parser = OutputFixingParser.from_llm(parser=parser, llm=ChatOpenAI())
47 | print(new_parser.parse(misformatted))
48 | """
49 | name='Tom Hanks' film_names=['Forrest Gump']
50 | """
51 |
--------------------------------------------------------------------------------
/output_parsers/datetime_parser.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain.chains import LLMChain
5 | from langchain_openai import OpenAI
6 | from langchain.output_parsers import DatetimeOutputParser
7 | from langchain.prompts import PromptTemplate
8 |
9 | output_parser = DatetimeOutputParser()
10 | # print(output_parser.get_format_instructions())
11 | """
12 | Write a datetime string that matches the following pattern: '%Y-%m-%dT%H:%M:%S.%fZ'.
13 |
14 | Examples: 0845-05-01T23:51:26.179657Z, 0953-10-03T20:38:54.550930Z, 0188-02-08T08:37:30.449473Z
15 |
16 | Return ONLY this string, no other words!
17 | """
18 | template = """Answer the users question:
19 |
20 | {question}
21 |
22 | {format_instructions}"""
23 | prompt = PromptTemplate.from_template(
24 | template,
25 | partial_variables={"format_instructions": output_parser.get_format_instructions()},
26 | )
27 | chain = LLMChain(prompt=prompt, llm=OpenAI())
28 | output_dict = chain.invoke("around when was bitcoin founded?")
29 | print(output_parser.parse(output_dict['text']))
30 | """
31 | 2009-01-03 18:15:05
32 | """
--------------------------------------------------------------------------------
/output_parsers/enum_parser.py:
--------------------------------------------------------------------------------
1 | from langchain.output_parsers.enum import EnumOutputParser
2 | from enum import Enum
3 |
4 | class Colors(Enum):
5 | RED = "red"
6 | GREEN = "green"
7 | BLUE = "blue"
8 |
9 | parser = EnumOutputParser(enum=Colors)
10 | # # Colors.RED
11 | # parser.parse("red")
12 |
13 | # # Can handle spaces
14 | # parser.parse(" green")
15 |
16 | # # And new lines
17 | # parser.parse("blue\n")
18 |
19 | # # And raises errors when appropriate
20 | # parser.parse("yellow")
21 |
22 | # """
23 | # Traceback (most recent call last):
24 | # File "/Users/seungjoonlee/git/learn-langchain/venv/lib/python3.10/site-packages/langchain/output_parsers/enum.py", line 27, in parse
25 | # return self.enum(response.strip())
26 | # File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/enum.py", line 385, in __call__
27 | # return cls.__new__(cls, value)
28 | # File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/enum.py", line 710, in __new__
29 | # raise ve_exc
30 | # ValueError: 'yellow' is not a valid Colors
31 |
32 | # During handling of the above exception, another exception occurred:
33 |
34 | # Traceback (most recent call last):
35 | # File "/Users/seungjoonlee/git/learn-langchain/output_parsers/enum_parser.py", line 20, in
36 | # parser.parse("yellow")
37 | # File "/Users/seungjoonlee/git/learn-langchain/venv/lib/python3.10/site-packages/langchain/output_parsers/enum.py", line 29, in parse
38 | # raise OutputParserException(
39 | # langchain.schema.output_parser.OutputParserException: Response 'yellow' is not one of the expected values: ['red', 'green', 'blue']
40 | # """
--------------------------------------------------------------------------------
/output_parsers/list_parser.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain.output_parsers import CommaSeparatedListOutputParser
5 | from langchain.prompts import PromptTemplate
6 | from langchain_openai import OpenAI
7 |
8 | output_parser = CommaSeparatedListOutputParser()
9 |
10 | format_instructions = output_parser.get_format_instructions()
11 | """
12 | Your response should be a list of comma separated values, eg: `foo, bar, baz`
13 | """
14 | # check what to expect to LLM
15 | prompt = PromptTemplate(
16 | template="List five {subject}.\n{format_instructions}",
17 | input_variables=["subject"],
18 | partial_variables={"format_instructions": format_instructions}
19 | )
20 |
21 | model = OpenAI(temperature=0)
22 |
23 | _input = prompt.format(subject="ice cream flavors")
24 | output = model.invoke(_input)
25 |
26 | print(output_parser.parse(output))
27 | # 모델 버전이 바뀐 후로는
28 | # ['1. Chocolate\n2. Vanilla\n3. Strawberry\n4. Mint chocolate chip\n5. Cookies and cream']
29 | # 으로 아웃풋이 됩니다.
30 |
--------------------------------------------------------------------------------
/output_parsers/pydantic_parser_actor.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from typing import List
5 | from langchain_openai import OpenAI
6 | from langchain.output_parsers import PydanticOutputParser
7 | from langchain.prompts import PromptTemplate
8 | from langchain.pydantic_v1 import BaseModel, Field
9 |
10 | model_name = "gpt-3.5-turbo-instruct"
11 | temperature = 0.0
12 | model = OpenAI(model_name=model_name, temperature=temperature)
13 |
14 | # Here's another example, but with a compound typed field.
15 | class Actor(BaseModel):
16 | name: str = Field(description="name of an actor")
17 | film_names: List[str] = Field(description="list of names of films they starred in")
18 |
19 |
20 | actor_query = "Generate the filmography for a random actor."
21 |
22 | parser = PydanticOutputParser(pydantic_object=Actor)
23 |
24 | print(parser.get_format_instructions())
25 | """
26 | The output should be formatted as a JSON instance that conforms to the JSON schema below.
27 |
28 | As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
29 | the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.
30 |
31 | Here is the output schema:
32 | ```
33 | {"properties": {"name": {"title": "Name", "description": "name of an actor", "type": "string"}, "film_names": {"title": "Film Names", "description": "list of names of films they starred in", "type": "array", "items": {"type": "string"}}}, "required": ["name", "film_names"]}
34 | ```
35 | """
36 | prompt = PromptTemplate(
37 | template="Answer the user query.\n{format_instructions}\n{query}\n",
38 | input_variables=["query"],
39 | partial_variables={"format_instructions": parser.get_format_instructions()},
40 | )
41 |
42 | _input = prompt.format_prompt(query=actor_query)
43 |
44 | output = model.invoke(_input.to_string())
45 | """
46 | Output:
47 | {"name": "Tom Hanks", "film_names": ["Forrest Gump", "Saving Private Ryan", "Cast Away", "The Green Mile", "Apollo 13", "Toy Story", "Toy Story 2", "Toy Story 3", "The Da Vinci Code", "Catch Me If You Can"]}
48 | name='Tom Hanks' film_names=['Forrest Gump', 'Saving Private Ryan', 'Cast Away', 'The Green Mile', 'Apollo 13', 'Toy Story', 'Toy Story 2', 'Toy Story 3', 'The Da Vinci Code', 'Catch Me If You Can']
49 | """
50 | m = parser.parse(output)
51 | print(m)
52 | """
53 | name='Tom Hanks' film_names=['Forrest Gump', 'Saving Private Ryan', 'The Green Mile', 'Cast Away', 'Toy Story']
54 | """
55 | print(m.name)
--------------------------------------------------------------------------------
/output_parsers/pydantic_parser_joke.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from typing import List
5 | from langchain_openai import OpenAI
6 | from langchain.output_parsers import PydanticOutputParser
7 | from langchain.prompts import PromptTemplate
8 | from langchain.pydantic_v1 import BaseModel, Field, validator
9 |
10 | model_name = "gpt-3.5-turbo-instruct"
11 | temperature = 0.0
12 | model = OpenAI(model_name=model_name, temperature=temperature)
13 |
14 | # Define your desired data structure.
15 | class Joke(BaseModel):
16 | setup: str = Field(description="question to set up a joke")
17 | punchline: str = Field(description="answer to resolve the joke")
18 |
19 | # You can add custom validation logic easily with Pydantic.
20 | @validator("setup")
21 | def question_ends_with_question_mark(cls, field):
22 | if field[-1] != "?":
23 | raise ValueError("Badly formed question!")
24 | return field
25 |
26 |
27 | # And a query intented to prompt a language model to populate the data structure.
28 | joke_query = "Tell me a joke."
29 |
30 | # Set up a parser + inject instructions into the prompt template.
31 | parser = PydanticOutputParser(pydantic_object=Joke)
32 |
33 | # print(parser.get_format_instructions())
34 | """
35 | The output should be formatted as a JSON instance that conforms to the JSON schema below.
36 |
37 | As an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}
38 | the object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.
39 |
40 | Here is the output schema:
41 | ```
42 | {"properties": {"setup": {"title": "Setup", "description": "question to set up a joke", "type": "string"}, "punchline": {"title": "Punchline", "description": "answer to resolve the joke", "type": "string"}}, "required": ["setup", "punchline"]}
43 | ```
44 | """
45 |
46 | prompt = PromptTemplate(
47 | template="Answer the user query.\n{format_instructions}\n{query}\n",
48 | input_variables=["query"],
49 | partial_variables={"format_instructions": parser.get_format_instructions()},
50 | )
51 |
52 | _input = prompt.format_prompt(query=joke_query)
53 |
54 | output = model.invoke(_input.to_string())
55 | print(output)
56 | output = '{"setup": "Why did the chicken cross the road?", "punchline": "To get to the other side!"}'
57 | """
58 | {"setup": "Why did the chicken cross the road?", "punchline": "To get to the other side!"}
59 | """
60 | m = parser.parse(output)
61 | print(m)
62 | """
63 | setup='Why did the chicken cross the road?' punchline='To get to the other side!
64 | """
65 | print(m.setup)
66 | """
67 | Why did the chicken cross the road?
68 | """
69 |
--------------------------------------------------------------------------------
/output_parsers/structured_output_parser.py:
--------------------------------------------------------------------------------
1 | from langchain.output_parsers import StructuredOutputParser, ResponseSchema
2 | from langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
3 | from langchain.llms import OpenAI
4 | from langchain.chat_models import ChatOpenAI
5 |
6 | response_schemas = [
7 | ResponseSchema(name="answer", description="answer to the user's question"),
8 | ResponseSchema(name="source", description="source used to answer the user's question, should be a website.")
9 | ]
10 | output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
11 |
12 | format_instructions = output_parser.get_format_instructions()
13 | # The output should be a markdown code snippet formatted in the following schema, including the leading and trailing "```json" and "```":
14 | """
15 | ```json
16 | {
17 | "answer": string // answer to the user's question
18 | "source": string // source used to answer the user's question, should be a website.
19 | }
20 | ```
21 | """
22 |
23 | prompt = PromptTemplate(
24 | template="answer the users question as best as possible.\n{format_instructions}\n{question}",
25 | input_variables=["question"],
26 | partial_variables={"format_instructions": format_instructions}
27 | )
28 |
29 | model = OpenAI(temperature=0)
30 |
31 | _input = prompt.format_prompt(question="what's the capital of france?")
32 | output = model(_input.to_string())
33 | """
34 | ```json
35 | {
36 | "answer": "Paris",
37 | "source": "https://www.worldatlas.com/articles/what-is-the-capital-of-france.html"
38 | }
39 | ```
40 | """
41 |
42 | chat_model = ChatOpenAI(temperature=0)
43 |
44 | prompt = ChatPromptTemplate(
45 | messages=[
46 | HumanMessagePromptTemplate.from_template("answer the users question as best as possible.\n{format_instructions}\n{question}")
47 | ],
48 | input_variables=["question"],
49 | partial_variables={"format_instructions": format_instructions}
50 | )
51 |
52 | _input = prompt.format_prompt(question="what's the capital of france?")
53 | output = chat_model(_input.to_messages())
54 | output_parser.parse(output.content)
55 | # {'answer': 'The capital of France is Paris.', 'source': 'https://en.wikipedia.org/wiki/Paris'}
56 |
--------------------------------------------------------------------------------
/prompt_template.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain.prompts import PromptTemplate
5 |
6 | prompt = PromptTemplate.from_template("What is a good name for a company that makes {product}?")
7 | prompt_output = prompt.format(product="colorful socks")
8 | print(prompt_output)
9 | # What is a good name for a company that makes colorful socks?
10 |
11 | from langchain.prompts.chat import ChatPromptTemplate
12 |
13 | template = "You are a helpful assistant that translates {input_language} to {output_language}."
14 | human_template = "{text}"
15 |
16 | chat_prompt = ChatPromptTemplate.from_messages([
17 | ("system", template), # role
18 | ("human", human_template), # content
19 | ])
20 |
21 | chat_prompt_output = chat_prompt.format_messages(
22 | input_language="English",
23 | output_language="French",
24 | text="I love programming.")
25 | print(chat_prompt_output)
26 | # [SystemMessage(content='You are a helpful assistant that translates English to French.'),
27 | # HumanMessage(content='I love programming.')]
28 |
29 |
30 | from langchain_openai import ChatOpenAI
31 |
32 | chat_model = ChatOpenAI()
33 | print(chat_model.invoke(chat_prompt_output))
34 |
--------------------------------------------------------------------------------
/pydantic_example/quickstart.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | from typing import Tuple
3 | from pydantic import BaseModel
4 |
5 |
6 | class Delivery(BaseModel):
7 | timestamp: datetime
8 | dimensions: Tuple[int, int]
9 |
10 |
11 | m = Delivery(timestamp='2020-01-02T03:04:05Z', dimensions=['10', '20']) # type: ignore
12 | print(repr(m.timestamp))
13 | #> datetime.datetime(2020, 1, 2, 3, 4, 5, tzinfo=TzInfo(UTC))
14 | print(m.dimensions)
15 | #> (10, 20)
16 |
--------------------------------------------------------------------------------
/pydantic_example/validation_fail.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | from pydantic import BaseModel, PositiveInt
3 | from pydantic import ValidationError
4 |
5 |
6 | class User(BaseModel):
7 | id: int
8 | name: str = 'John Doe'
9 | signup_ts: datetime | None
10 | tastes: dict[str, PositiveInt]
11 |
12 | external_data = {'id': 'not an int', 'tastes': {}}
13 |
14 | try:
15 | User(**external_data)
16 | except ValidationError as e:
17 | print(e.errors())
18 | """
19 | [
20 | {
21 | 'type': 'int_parsing',
22 | 'loc': ('id',),
23 | 'msg': 'Input should be a valid integer, unable to parse string as an integer',
24 | 'input': 'not an int',
25 | 'url': 'https://errors.pydantic.dev/2/v/int_parsing',
26 | },
27 | {
28 | 'type': 'missing',
29 | 'loc': ('signup_ts',),
30 | 'msg': 'Field required',
31 | 'input': {'id': 'not an int', 'tastes': {}},
32 | 'url': 'https://errors.pydantic.dev/2/v/missing',
33 | },
34 | ]
35 | """
36 |
--------------------------------------------------------------------------------
/pydantic_example/validation_successful.py:
--------------------------------------------------------------------------------
1 | from datetime import datetime
2 | from pydantic import BaseModel, PositiveInt
3 |
4 | class User(BaseModel):
5 | id: int
6 | name: str = 'John Doe'
7 | signup_ts: datetime | None
8 | tastes: dict[str, PositiveInt]
9 |
10 | external_data = {
11 | 'id': 123,
12 | 'signup_ts': '2019-06-01 12:22',
13 | 'tastes': {
14 | 'wine': 9,
15 | b'cheese': 7,
16 | 'cabbage': '1',
17 | },
18 | }
19 |
20 | user = User(**external_data)
21 |
22 | print(user.id)
23 | #> 123
24 | print(user.model_dump())
25 | """
26 | {
27 | 'id': 123,
28 | 'name': 'John Doe',
29 | 'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
30 | 'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1},
31 | }
32 | """
33 |
--------------------------------------------------------------------------------
/quickstart.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from typing import List
5 | from langchain_openai import ChatOpenAI
6 | from langchain.prompts import ChatPromptTemplate
7 | from langchain.schema import BaseOutputParser
8 |
9 | class CommaSeparatedListOutputParser(BaseOutputParser[List[str]]):
10 | """Parse the output of an LLM call to a comma-separated list."""
11 | def parse(self, text: str) -> List[str]:
12 | """Parse the output of an LLM call."""
13 | return text.strip().split(", ")
14 |
15 | template = """You are a helpful assistant who generates comma separated lists.
16 | A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
17 | ONLY return a comma separated list, and nothing more."""
18 | human_template = "{text}"
19 |
20 | chat_prompt = ChatPromptTemplate.from_messages([
21 | ("system", template),
22 | ("human", human_template),
23 | ])
24 |
25 | # LangChain Expression Language(LCEL)
26 | chain = chat_prompt | ChatOpenAI() | CommaSeparatedListOutputParser()
27 | print(chain.invoke({"text": "colors"}))
28 | # ['red', 'blue', 'green', 'yellow', 'purple']
29 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | langchain==0.1.9
2 | langchain-community==0.0.24
3 | langchain-core==0.1.27
4 | langchain-openai==0.0.8
5 |
--------------------------------------------------------------------------------
/retriever/context_compression.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_community.document_loaders import TextLoader
5 | from langchain_openai import OpenAI
6 | from langchain.retrievers import ContextualCompressionRetriever
7 | from langchain_openai import OpenAIEmbeddings
8 | from langchain.text_splitter import CharacterTextSplitter
9 | from langchain.retrievers.document_compressors import LLMChainExtractor
10 | from langchain_community.vectorstores.chroma import Chroma
11 |
12 | data = TextLoader('./state_of_the_union.txt').load()
13 |
14 | # Split
15 | text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
16 | splits = text_splitter.split_documents(data)
17 |
18 | # VectorDB
19 | embedding = OpenAIEmbeddings()
20 | vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
21 |
22 | # Helper function for printing docs
23 | def pretty_print_docs(docs):
24 | print(f"\n{'-' * 100}\n".join([f"Document {i+1}:\n\n" + d.page_content for i, d in enumerate(docs)]))
25 |
26 | retriever = vectordb.as_retriever()
27 | docs = retriever.get_relevant_documents("What did the president say about Ketanji Brown Jackson")
28 | # pretty_print_docs(docs)
29 | """
30 | Document 1:
31 |
32 | Tonight. I call on the Senate to: Pass the Freedom to Vote Act. Pass the John Lewis Voting Rights Act. And while you’re at it, pass the Disclose Act so Americans can know who is funding our elections.
33 |
34 | Tonight, I’d like to honor someone who has dedicated his life to serve this country: Justice Stephen Breyer—an Army veteran, Constitutional scholar, and retiring Justice of the United States Supreme Court. Justice Breyer, thank you for your service.
35 |
36 | One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court.
37 |
38 | And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence.
39 | ...
40 | """
41 |
42 | llm = OpenAI(temperature=0)
43 | compressor = LLMChainExtractor.from_llm(llm)
44 | compression_retriever = ContextualCompressionRetriever(
45 | base_compressor=compressor,
46 | base_retriever=retriever)
47 |
48 | compressed_docs = compression_retriever.get_relevant_documents(
49 | "What did the president say about Ketanji Brown Jackson")
50 | pretty_print_docs(compressed_docs)
51 | """
52 | Document 1:
53 |
54 | "One of the most serious constitutional responsibilities a President has is nominating someone to serve on the United States Supreme Court.
55 |
56 | And I did that 4 days ago, when I nominated Circuit Court of Appeals Judge Ketanji Brown Jackson. One of our nation’s top legal minds, who will continue Justice Breyer’s legacy of excellence."
57 | """
58 |
--------------------------------------------------------------------------------
/retriever/multi_query_retriever.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 |
5 | # Build a sample vectorDB
6 | from langchain_community.document_loaders import WebBaseLoader
7 | from langchain_openai import OpenAIEmbeddings
8 | from langchain.text_splitter import RecursiveCharacterTextSplitter
9 | from langchain_community.vectorstores.chroma import Chroma
10 |
11 | # Load blog post
12 | loader = WebBaseLoader("https://lilianweng.github.io/posts/2023-06-23-agent/")
13 | data = loader.load()
14 |
15 | # Split
16 | text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0)
17 | splits = text_splitter.split_documents(data)
18 |
19 | # VectorDB
20 | embedding = OpenAIEmbeddings()
21 | vectordb = Chroma.from_documents(documents=splits, embedding=embedding)
22 |
23 | from langchain_openai import ChatOpenAI
24 | from langchain.retrievers.multi_query import MultiQueryRetriever
25 |
26 | question = "What are the approaches to Task Decomposition?"
27 | llm = ChatOpenAI(temperature=0)
28 | retriever_from_llm = MultiQueryRetriever.from_llm(
29 | retriever=vectordb.as_retriever(), llm=llm)
30 |
31 | # Set logging for the queries
32 | import logging
33 |
34 | logging.basicConfig()
35 | logging.getLogger("langchain.retrievers.multi_query").setLevel(logging.INFO)
36 |
37 | unique_docs = retriever_from_llm.get_relevant_documents(query=question)
38 | """
39 | INFO:langchain.retrievers.multi_query:Generated queries: [
40 | '1. How can Task Decomposition be achieved through different methods?',
41 | '2. What strategies are commonly used for breaking down tasks in Task Decomposition?',
42 | '3. What are the various techniques employed in Task Decomposition to simplify complex tasks?']
43 | """
44 | print(len(unique_docs))
45 | """
46 | 6
47 | """
--------------------------------------------------------------------------------
/serialization/example_json.py:
--------------------------------------------------------------------------------
1 | # All prompts are loaded through the `load_prompt` function.
2 | from langchain.prompts import load_prompt, PromptTemplate
3 |
4 |
5 | template = "Tell me a {adjective} joke about {content}."
6 | prompt = PromptTemplate(template=template, input_variables=["adjective", "content"])
7 | # input_variables=['adjective', 'content'] template='Tell me a {adjective} joke about {content}.'
8 |
9 | # save the prompt in JSON
10 | prompt.save("simple_prompt.json")
11 |
12 | # load the prompt from JSON file
13 | prompt = load_prompt("simple_prompt.json")
14 | print(prompt.format(adjective="funny", content="chickens"))
--------------------------------------------------------------------------------
/serialization/example_yaml.py:
--------------------------------------------------------------------------------
1 | # All prompts are loaded through the `load_prompt` function.
2 | from langchain.prompts import load_prompt, PromptTemplate
3 |
4 |
5 | template = "Tell me a {adjective} joke about {content}."
6 | prompt = PromptTemplate(template=template, input_variables=["adjective", "content"])
7 | # input_variables=['adjective', 'content'] template='Tell me a {adjective} joke about {content}.'
8 |
9 | # save the prompt in YAML
10 | prompt.save("simple_prompt.yaml")
11 |
12 | # load the prompt from YAML file
13 | prompt = load_prompt("simple_prompt.yaml")
14 | print(prompt.format(adjective="funny", content="chickens"))
15 |
--------------------------------------------------------------------------------
/serialization/simple_prompt.json:
--------------------------------------------------------------------------------
1 | {
2 | "input_variables": [
3 | "adjective",
4 | "content"
5 | ],
6 | "input_types": {},
7 | "output_parser": null,
8 | "partial_variables": {},
9 | "template": "Tell me a {adjective} joke about {content}.",
10 | "template_format": "f-string",
11 | "validate_template": false,
12 | "_type": "prompt"
13 | }
--------------------------------------------------------------------------------
/serialization/simple_prompt.yaml:
--------------------------------------------------------------------------------
1 | _type: prompt
2 | input_types: {}
3 | input_variables:
4 | - adjective
5 | - content
6 | output_parser: null
7 | partial_variables: {}
8 | template: Tell me a {adjective} joke about {content}.
9 | template_format: f-string
10 | validate_template: false
11 |
--------------------------------------------------------------------------------
/serve.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from typing import List
3 |
4 | from fastapi import FastAPI
5 | from langchain.prompts import ChatPromptTemplate
6 | from langchain.chat_models import ChatOpenAI
7 | from langchain.schema import BaseOutputParser
8 | from langserve import add_routes
9 |
10 | # 1. Chain definition
11 |
12 | class CommaSeparatedListOutputParser(BaseOutputParser[List[str]]):
13 | """Parse the output of an LLM call to a comma-separated list."""
14 |
15 |
16 | def parse(self, text: str) -> List[str]:
17 | """Parse the output of an LLM call."""
18 | return text.strip().split(", ")
19 |
20 | template = """You are a helpful assistant who generates comma separated lists.
21 | A user will pass in a category, and you should generate 5 objects in that category in a comma separated list.
22 | ONLY return a comma separated list, and nothing more."""
23 | human_template = "{text}"
24 |
25 | chat_prompt = ChatPromptTemplate.from_messages([
26 | ("system", template),
27 | ("human", human_template),
28 | ])
29 | category_chain = chat_prompt | ChatOpenAI() | CommaSeparatedListOutputParser()
30 |
31 | # 2. App definition
32 | app = FastAPI(
33 | title="LangChain Server",
34 | version="1.0",
35 | description="A simple api server using Langchain's Runnable interfaces",
36 | )
37 |
38 | # 3. Adding chain route
39 | add_routes(
40 | app,
41 | category_chain,
42 | path="/category_chain",
43 | )
44 |
45 | if __name__ == "__main__":
46 | import uvicorn
47 |
48 | uvicorn.run(app, host="localhost", port=8000)
--------------------------------------------------------------------------------
/simple_prompt.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": null,
3 | "input_variables": [
4 | "adjective",
5 | "content"
6 | ],
7 | "input_types": {},
8 | "output_parser": null,
9 | "partial_variables": {},
10 | "metadata": null,
11 | "tags": null,
12 | "template": "Tell me a {adjective} joke about {content}.",
13 | "template_format": "f-string",
14 | "validate_template": false,
15 | "_type": "prompt"
16 | }
--------------------------------------------------------------------------------
/simple_prompt.yaml:
--------------------------------------------------------------------------------
1 | _type: prompt
2 | input_types: {}
3 | input_variables:
4 | - adjective
5 | - content
6 | metadata: null
7 | name: null
8 | output_parser: null
9 | partial_variables: {}
10 | tags: null
11 | template: Tell me a {adjective} joke about {content}.
12 | template_format: f-string
13 | validate_template: false
14 |
--------------------------------------------------------------------------------
/text_embedding/csv_sample.csv:
--------------------------------------------------------------------------------
1 | name,age,country
2 | Neville Hardy,56,Niue
3 | Dacia Cohen,74,Falkland Islands (Malvinas)
4 | Kathey Daniel,10,Slovenia
5 | Mallie Welch,12,Equatorial Guinea
6 | Katia Bryant,14,Ghana
7 | Laurice Robertson,53,Saudi Arabia
8 | Minh Barrett,27,French Southern Territories
9 | Latashia Perez,52,Finland
10 | Elvina Ross,68,New Zealand
--------------------------------------------------------------------------------
/text_embedding/text_embedding.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_openai import OpenAIEmbeddings
5 |
6 | # requires `pip install openai`
7 | embeddings_model = OpenAIEmbeddings()
8 |
9 | # Embed list of texts
10 | embeddings = embeddings_model.embed_documents(
11 | [
12 | "Hi there!",
13 | "Oh, hello!",
14 | "What's your name?",
15 | "My friends call me World",
16 | "Hello World!"
17 | ]
18 | )
19 | print(len(embeddings))
20 | """
21 | 5
22 | """
23 |
24 | # length of 1536
25 | print(len(embeddings[0]))
26 | print(len(embeddings[1]))
27 | """
28 | [... 0.022085255981691917, 0.025720015991018582, 0.008734743689027272, -0.006709843137048811, -0.022764415491192392, -0.00257671800269355, 0.010677894145694868, 0.0001446357869742665, -0.02568228625240111, -0.010438930752548039, -0.002831402818756228, -0.012992066737283132, 0.0015925658455746433, -0.021569597594135712, 0.011853846242120273, 0.015771589535625893, 0.006238204640524732, 0.02429881221167677, 0.014086268272736402, -0.024575506274763608, -0.021129402409104603, 0.007653119664435697, 0.006021250727232698, -0.02475158583889211, -0.012853719705739713, 0.018048030525951612, -0.0018441062839218978, -0.008445472115078739, -0.006885921304193508, 0.00240850043059146, 0.00827568270336489, -0.008030431020448483, -0.004181860777053302, 0.0010344603379206113, 0.007552503768493557, 0.01879007479579295, 0.008451761336170855, -0.014249769394680672, -0.03264995904888929, 0.004728961544779937, -0.0020343339179553677, -0.024927663540375542, -0.006565207350074544, -0.014765427782236877 ...]
29 | """
30 |
31 | # Use Document Loader
32 | from langchain_community.document_loaders import CSVLoader
33 | loader = CSVLoader(file_path='./csv_sample.csv')
34 | data = loader.load()
35 | print(data)
36 | embeddings = embeddings_model.embed_documents(
37 | [
38 | text.page_content for text in data
39 | ]
40 | )
41 | print(len(embeddings))
42 | """
43 | 9
44 | """
45 |
46 | # Embed single query
47 | # Embed a single piece of text for the purpose of comparing to other embedded pieces of texts.
48 | embedded_query = embeddings_model.embed_query("What was the name mentioned in the conversation?")
49 | print(embedded_query[:5])
50 | """
51 | [0.005354681365594307, -0.0005715346531097274, 0.03887590993433691, -0.0029596003572924623, -0.00896628532870428]
52 | """
--------------------------------------------------------------------------------
/vector_stores/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/.DS_Store
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/data_level0.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/data_level0.bin
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/header.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/header.bin
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/index_metadata.pickle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/index_metadata.pickle
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/length.bin:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/link_lists.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/fortune_500_db/3ac7dac4-a1b8-4432-9306-3bec6614ef1c/link_lists.bin
--------------------------------------------------------------------------------
/vector_stores/fortune_500_db/chroma.sqlite3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimz119/learn-langchain/f0c2604aab7cab7f2c4d44d7bb484fd0dc2463bc/vector_stores/fortune_500_db/chroma.sqlite3
--------------------------------------------------------------------------------
/vector_stores/quickstart.py:
--------------------------------------------------------------------------------
1 | # Note as of 02/27/2024
2 | # before you start you need to install the following
3 | # pip install langchain==0.1.9 langchain-openai==0.0.8
4 | from langchain_community.document_loaders import CSVLoader
5 | from langchain_openai import OpenAIEmbeddings
6 | from langchain.text_splitter import CharacterTextSplitter
7 | from langchain_community.vectorstores.chroma import Chroma
8 |
9 | # requires `pip install chromadb`
10 | loader = CSVLoader(file_path='./fortune_500_2020.csv')
11 | raw_documents = loader.load()
12 |
13 | text_splitter = CharacterTextSplitter(chunk_size=200, chunk_overlap=0)
14 | documents = text_splitter.split_documents(raw_documents)
15 | openai_embedding = OpenAIEmbeddings()
16 | db = Chroma.from_documents(documents, openai_embedding, persist_directory="./fortune_500_db")
17 |
18 | # save to disk
19 | db.persist()
20 |
21 | db_conn = Chroma(persist_directory="./fortune_500_db", embedding_function=openai_embedding)
22 | query = "What is JPMorgan Revenue?"
23 | docs = db_conn.similarity_search(query)
24 | print(docs)
25 | print(docs[0].page_content)
26 |
27 | # # retriever
28 | # db_conn = Chroma(persist_directory="./fortune_500_db", embedding_function=openai_embedding)
29 | # retriever = db_conn.as_retriever()
30 | # result = retriever.get_relevant_documents('walmart')
31 | # print(result[0].page_content)
32 | # """
33 | # rank: 1
34 | # company: Walmart
35 | # no_of_employees: 2,200,000.00
36 | # rank_change: None
37 | # revenues: 523,964.00
38 | # revenue_change: 0.02
39 | # profits: 14,881.00
40 | # profit_change: 1.23
41 | # assets: 236,495.00
42 | # market_value: 321,803.30
43 | # """
--------------------------------------------------------------------------------