在本教程中,您将向状态添加其他字段,以定义复杂的行为,而无需依赖消息列表。聊天机器人将使用其搜索工具查找特定信息并将其转发给人工审核。

本教程以添加人机交互控制为基础。

1. 向状态添加键

通过向状态添加name和键来更新聊天机器人以研究实体的生日:birthday

(API 参考:add_messages)

1
2
3
4
5
6
7
8
9
10
11
from typing import Annotated

from typing_extensions import TypedDict

from langgraph.graph.message import add_messages


class State(TypedDict):
messages: Annotated[list, add_messages]
name: str
birthday: str

将此信息添加到状态中,使得其他图形节点(如存储或处理信息的下游节点)以及图形的持久层可以轻松访问它。

2. 更新工具内部的状态

现在,在human_assistance工具中填充状态键。这允许人类在信息存储到状态之前对其进行审查。使用命令从工具内部发出状态更新。

API 参考:ToolMessage | InjectedToolCallId |工具|命令|中断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from langchain_core.messages import ToolMessage
from langchain_core.tools import InjectedToolCallId, tool

from langgraph.types import Command, interrupt

@tool
# Note that because we are generating a ToolMessage for a state update, we
# generally require the ID of the corresponding tool call. We can use
# LangChain's InjectedToolCallId to signal that this argument should not
# be revealed to the model in the tool's schema.
def human_assistance(
name: str, birthday: str, tool_call_id: Annotated[str, InjectedToolCallId]
) -> str:
"""Request assistance from a human."""
human_response = interrupt(
{
"question": "Is this correct?",
"name": name,
"birthday": birthday,
},
)
# If the information is correct, update the state as-is.
if human_response.get("correct", "").lower().startswith("y"):
verified_name = name
verified_birthday = birthday
response = "Correct"
# Otherwise, receive information from the human reviewer.
else:
verified_name = human_response.get("name", name)
verified_birthday = human_response.get("birthday", birthday)
response = f"Made a correction: {human_response}"

# This time we explicitly update the state with a ToolMessage inside
# the tool.
state_update = {
"name": verified_name,
"birthday": verified_birthday,
"messages": [ToolMessage(response, tool_call_id=tool_call_id)],
}
# We return a Command object in the tool to update our state.
return Command(update=state_update)

图表的其余部分保持不变。

3. 提示聊天机器人

human_assistance 提示聊天机器人查找 LangGraph 库的生日,并在获得所需信息后指示聊天机器人联系该工具。您可以强制聊天机器人为这些字段生成提案, 通过在该工具的参数中设置namebirthday

1
2
3
4
5
6
7
8
9
10
11
12
13
14
user_input = (
"Can you look up when LangGraph was released? "
"When you have the answer, use the human_assistance tool for review."
)
config = {"configurable": {"thread_id": "1"}}

events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config,
stream_mode="values",
)
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()

对话记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
================================ Human Message =================================

Can you look up when LangGraph was released? When you have the answer, use the human_assistance tool for review.
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_nlrjvtin)
Call ID: call_nlrjvtin
Args:
query: LangGraph release date
================================= Tool Message =================================
Name: tavily_search

{"query": "LangGraph release date", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://langchain-ai.github.io/langgraph/tutorials/get-started/5-customize-state/", "title": "5. Customize state - GitHub Pages", "content": "Prompt the chatbot to look up the \"birthday\" of the LangGraph library and direct the chatbot to reach out to the `human_assistance` tool once it has the required information. Then, I'll use the human_assistance tool for review.\", 'type': 'text'}, {'id': 'toolu_01JoXQPgTVJXiuma8xMVwqAi', 'input': {'query': 'LangGraph release date'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}] \\n\\nGiven this information, I'll use the human_assistance tool to review and potentially provide more accurate information about LangGraph's initial release date.\", 'type': 'text'}, {'id': 'toolu_01JDQAV7nPqMkHHhNs3j3XoN', 'input': {'name': 'Assistant', 'birthday': '2023-01-01'}, 'name': 'human_assistance', 'type': 'tool_use'}] \\n\\nGiven this information, I'll use the human_assistance tool to review and potentially provide more accurate information about LangGraph's initial release date.\", 'type': 'text'}, {'id': 'toolu_01JDQAV7nPqMkHHhNs3j3XoN', 'input': {'name': 'Assistant', 'birthday': '2023-01-01'}, 'name': 'human_assistance', 'type': 'tool_use'}]", "score": 0.8127637, "raw_content": null}, {"url": "https://github.com/langchain-ai/langgraph-studio/releases", "title": "Releases · langchain-ai/langgraph-studio - GitHub", "content": "* [Code](https://github.com/langchain-ai/langgraph-studio) * [Issues 47](https://github.com/langchain-ai/langgraph-studio/issues) * [Pull requests 0](https://github.com/langchain-ai/langgraph-studio/pulls) * [Discussions](https://github.com/langchain-ai/langgraph-studio/discussions) * [Actions](https://github.com/langchain-ai/langgraph-studio/actions) [There was an error while loading.](https://github.com/langchain-ai/langgraph-studio/security)Please reload this page. * [Insights](https://github.com/langchain-ai/langgraph-studio/pulse) * [Code](https://github.com/langchain-ai/langgraph-studio) * [Issues](https://github.com/langchain-ai/langgraph-studio/issues) * [Discussions](https://github.com/langchain-ai/langgraph-studio/discussions) * [Actions](https://github.com/langchain-ai/langgraph-studio/actions) * [Security](https://github.com/langchain-ai/langgraph-studio/security) * [Insights](https://github.com/langchain-ai/langgraph-studio/pulse) [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [Latest](https://github.com/langchain-ai/langgraph-studio/releases/latest) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.37.zip) 2025-01-02T13:24:41Z [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.36](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.36) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.36.zip) 2025-01-02T13:24:41Z [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.35](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.35) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.35.zip) 2025-01-02T13:24:41Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.34](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.34) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.34.zip) 2024-12-18T22:14:18Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.33](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.33) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.33.zip) 2024-12-04T23:51:34Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.32](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.32) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.32.zip) 2024-12-04T23:51:34Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.31](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.31) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.31.zip) 2024-11-06T02:20:16Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.30](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.30) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.30.zip) 2024-09-19T13:46:48Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.29](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.29) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.29.zip) 2024-09-19T13:46:48Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.28](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.28) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.28.zip) 2024-09-19T13:46:48Z Previous[Next](https://github.com/langchain-ai/langgraph-studio/releases?page=2)", "score": 0.72231215, "raw_content": null}], "response_time": 1.14, "request_id": "9b83a79e-a410-452e-9abf-a4dcd452c85f"}
================================== Ai Message ==================================

Based on the information retrieved from GitHub, it seems that LangGraph has had several releases. The latest release tag available is `v0.0.37`, but this does not necessarily indicate when LangGraph was first released. To get a more accurate answer about its initial release date, I will use the human_assistance tool for review.
Tool Calls:
human_assistance (call_m9u0u7os)
Call ID: call_m9u0u7os
Args:
birthday: 2023-01-01
name: LangGraph

我们再次遇见了人工帮助中断

4. 增加人工帮助

聊天机器人无法识别正确的日期,因此请向其提供以下信息:

1
2
3
4
5
6
7
8
9
10
11
human_command = Command(
resume={
"name": "LangGraph",
"birthday": "Jan 17, 2024",
},
)

events = graph.stream(human_command, config, stream_mode="values")
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()

对话记录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
================================ Human Message =================================

Can you look up when LangGraph was released? When you have the answer, use the human_assistance tool for review.
================================== Ai Message ==================================
Tool Calls:
tavily_search (call_rql1noyw)
Call ID: call_rql1noyw
Args:
query: LangGraph release date
================================= Tool Message =================================
Name: tavily_search

{"query": "LangGraph release date", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://langchain-ai.github.io/langgraph/tutorials/get-started/5-customize-state/", "title": "5. Customize state - GitHub Pages", "content": "Prompt the chatbot to look up the \"birthday\" of the LangGraph library and direct the chatbot to reach out to the `human_assistance` tool once it has the required information. Then, I'll use the human_assistance tool for review.\", 'type': 'text'}, {'id': 'toolu_01JoXQPgTVJXiuma8xMVwqAi', 'input': {'query': 'LangGraph release date'}, 'name': 'tavily_search_results_json', 'type': 'tool_use'}] \\n\\nGiven this information, I'll use the human_assistance tool to review and potentially provide more accurate information about LangGraph's initial release date.\", 'type': 'text'}, {'id': 'toolu_01JDQAV7nPqMkHHhNs3j3XoN', 'input': {'name': 'Assistant', 'birthday': '2023-01-01'}, 'name': 'human_assistance', 'type': 'tool_use'}] \\n\\nGiven this information, I'll use the human_assistance tool to review and potentially provide more accurate information about LangGraph's initial release date.\", 'type': 'text'}, {'id': 'toolu_01JDQAV7nPqMkHHhNs3j3XoN', 'input': {'name': 'Assistant', 'birthday': '2023-01-01'}, 'name': 'human_assistance', 'type': 'tool_use'}]", "score": 0.8127637, "raw_content": null}, {"url": "https://github.com/langchain-ai/langgraph-studio/releases", "title": "Releases · langchain-ai/langgraph-studio - GitHub", "content": "* [Code](https://github.com/langchain-ai/langgraph-studio) * [Issues 47](https://github.com/langchain-ai/langgraph-studio/issues) * [Pull requests 0](https://github.com/langchain-ai/langgraph-studio/pulls) * [Discussions](https://github.com/langchain-ai/langgraph-studio/discussions) * [Actions](https://github.com/langchain-ai/langgraph-studio/actions) [There was an error while loading.](https://github.com/langchain-ai/langgraph-studio/security)Please reload this page. * [Insights](https://github.com/langchain-ai/langgraph-studio/pulse) * [Code](https://github.com/langchain-ai/langgraph-studio) * [Issues](https://github.com/langchain-ai/langgraph-studio/issues) * [Discussions](https://github.com/langchain-ai/langgraph-studio/discussions) * [Actions](https://github.com/langchain-ai/langgraph-studio/actions) * [Security](https://github.com/langchain-ai/langgraph-studio/security) * [Insights](https://github.com/langchain-ai/langgraph-studio/pulse) [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [Latest](https://github.com/langchain-ai/langgraph-studio/releases/latest) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.37.zip) 2025-01-02T13:24:41Z [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.36](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.36) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.36.zip) 2025-01-02T13:24:41Z [`5874680`](https://github.com/langchain-ai/langgraph-studio/commit/5874680cdf4319d036c1021f18c119f069d3f115) [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.35](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.35) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.35.zip) 2025-01-02T13:24:41Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.34](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.34) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.34.zip) 2024-12-18T22:14:18Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.33](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.33) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.33.zip) 2024-12-04T23:51:34Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.32](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.32) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.32.zip) 2024-12-04T23:51:34Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.31](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.31) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.31.zip) 2024-11-06T02:20:16Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.30](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.30) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.30.zip) 2024-09-19T13:46:48Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.29](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.29) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.29.zip) 2024-09-19T13:46:48Z [View all tags](https://github.com/langchain-ai/langgraph-studio/tags) [0.0.28](https://github.com/langchain-ai/langgraph-studio/releases/tag/v0.0.28) * [Source code(zip)](https://github.com/langchain-ai/langgraph-studio/archive/refs/tags/v0.0.28.zip) 2024-09-19T13:46:48Z Previous[Next](https://github.com/langchain-ai/langgraph-studio/releases?page=2)", "score": 0.72231215, "raw_content": null}], "response_time": 1.12, "request_id": "3c3f849a-d88a-4ed2-a51e-c86332fd960d"}
================================== Ai Message ==================================

Based on the information retrieved from GitHub, it seems that LangGraph has had several releases. The latest release tag available is `v0.0.37`, but this does not necessarily indicate when LangGraph was first released. To get a more accurate answer about its initial release date, I will use the human_assistance tool for review.
Tool Calls:
human_assistance (call_y4r0npr9)
Call ID: call_y4r0npr9
Args:
birthday: 2023-01-01
name: LangGraph
================================== Ai Message ==================================

Based on the information retrieved from GitHub, it seems that LangGraph has had several releases. The latest release tag available is `v0.0.37`, but this does not necessarily indicate when LangGraph was first released. To get a more accurate answer about its initial release date, I will use the human_assistance tool for review.
Tool Calls:
human_assistance (call_y4r0npr9)
Call ID: call_y4r0npr9
Args:
birthday: 2023-01-01
name: LangGraph
================================= Tool Message =================================
Name: human_assistance

Made a correction: {'name': 'LangGraph', 'birthday': 'Jan 17, 2024'}
================================== Ai Message ==================================

According to the information reviewed by the human expert, LangGraph was released on January 17, 2024.

If you have any other questions or need further assistance, feel free to ask!

请注意,这些字段现在反映在状态中:

1
2
3
snapshot = graph.get_state(config)

print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})
1
{'name': 'LangGraph', 'birthday': 'Jan 17, 2024'}

这使得下游节点(例如,进一步处理或存储信息的节点)可以轻松访问它们。

5. 手动更新状态

LangGraph 对应用程序状态提供了高度的控制。例如,在任何时候(包括中断时),你都可以使用以下命令手动覆盖某个键graph.update_state

1
graph.update_state(config, {"name": "LangGraph (library)"})

6. 查看新值

如果您调用graph.get_state,您可以看到反映的新值:

1
2
3
snapshot = graph.get_state(config)

print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})
1
{'name': 'LangGraph (library)', 'birthday': 'Jan 17, 2024'}

7. 最终代码

API 参考:TavilySearch | ToolMessage | InjectedToolCallId | tool | InMemorySaver | StateGraph | START | END | add_messages | ToolNode | tools_condition | Command | interrupt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import os
from typing import Annotated

from typing_extensions import TypedDict

from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
from langchain_tavily import TavilySearch
from langgraph.prebuilt import ToolNode, tools_condition
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command, interrupt
from langchain_core.tools import InjectedToolCallId, tool

import json

from langchain_core.messages import ToolMessage

load_dotenv()

memory = InMemorySaver()

class State(TypedDict):
messages: Annotated[list, add_messages]
name: str
birthday: str

graph_builder = StateGraph(State)


llm = ChatOpenAI(
model=os.getenv("LLM_MODEL_NAME"),
api_key=os.getenv("LLM_API_KEY"),
base_url=os.getenv("LLM_BASE_URL"),
temperature=os.getenv("LLM_TEMPERATURE"),
max_tokens=os.getenv("LLM_MAX_TOKENS")
)

@tool
#请注意,由于我们正在为状态更新生成ToolMessage,我们通常需要相应工具调用的ID。
# 我们可以使用LangChain的 InjectedToolCallId 表示此参数不应在工具的模式中向模型显示。
def human_assistance(
name: str, birthday: str, tool_call_id: Annotated[str, InjectedToolCallId]
) -> str:
"""Request assistance from a human."""
human_response = interrupt(
{
"question": "Is this correct?",
"name": name,
"birthday": birthday,
},
)
# If the information is correct, update the state as-is.
if human_response.get("correct", "").lower().startswith("y"):
verified_name = name
verified_birthday = birthday
response = "Correct"
# Otherwise, receive information from the human reviewer.
else:
verified_name = human_response.get("name", name)
verified_birthday = human_response.get("birthday", birthday)
response = f"Made a correction: {human_response}"

# This time we explicitly update the state with a ToolMessage inside
# the tool.
state_update = {
"name": verified_name,
"birthday": verified_birthday,
"messages": [ToolMessage(response, tool_call_id=tool_call_id)],
}
# We return a Command object in the tool to update our state.
return Command(update=state_update)

tool = TavilySearch(max_results=2)
tools = [tool, human_assistance]
llm_with_tools = llm.bind_tools(tools)

def chatbot(state: State):
message = llm_with_tools.invoke(state["messages"])
# Because we will be interrupting during tool execution,
# we disable parallel tool calling to avoid repeating any
# tool invocations when we resume.
assert len(message.tool_calls) <= 1
return {"messages": [message]}

graph_builder.add_node("chatbot", chatbot)


tool_node = ToolNode(tools=tools)
graph_builder.add_node("tools", tool_node)


graph_builder.add_conditional_edges(
"chatbot",
tools_condition,
)

# Any time a tool is called, we return to the chatbot to decide the next step
graph_builder.add_edge("tools", "chatbot")
graph_builder.add_edge(START, "chatbot")
graph = graph_builder.compile(checkpointer=memory)


# 画图
png_bytes = graph.get_graph().draw_mermaid_png()

with open("graph.png", "wb") as f:
f.write(png_bytes)

# import os
# os.system("open graph.png")

user_input = (
"Can you look up when LangGraph was released? "
"When you have the answer, use the human_assistance tool for review."
)
config = {"configurable": {"thread_id": "1"}}

events = graph.stream(
{"messages": [{"role": "user", "content": user_input}]},
config,
stream_mode="values",
)
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()


human_command = Command(
resume={
"name": "LangGraph",
"birthday": "Jan 17, 2024",
},
)

events = graph.stream(human_command, config, stream_mode="values")
for event in events:
if "messages" in event:
event["messages"][-1].pretty_print()

snapshot = graph.get_state(config)
print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})

graph.update_state(config, {"name": "LangGraph (library)"})

snapshot = graph.get_state(config)
print({k: v for k, v in snapshot.values.items() if k in ("name", "birthday")})