Skip to content

Commit e7e6fb1

Browse files
committed
added langgraph sample
1 parent bc93ddc commit e7e6fb1

File tree

9 files changed

+100
-143
lines changed

9 files changed

+100
-143
lines changed

chainlit/app-chainlit-tools.py

Lines changed: 0 additions & 70 deletions
This file was deleted.

chainlit/app-langgraph.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import os
2+
from dotenv import load_dotenv
3+
4+
from typing import Annotated, Literal, TypedDict
5+
6+
from langchain_openai import AzureChatOpenAI
7+
8+
from langchain.schema.runnable.config import RunnableConfig
9+
from langchain_core.messages import SystemMessage, HumanMessage
10+
11+
from langchain_core.messages import HumanMessage
12+
from langchain_core.tools import tool
13+
from langgraph.checkpoint.memory import MemorySaver
14+
from langgraph.graph import END, START, StateGraph, MessagesState
15+
from langgraph.prebuilt import ToolNode
16+
17+
from utilities import get_similar_sessions
18+
19+
import chainlit as cl
20+
21+
load_dotenv()
22+
23+
tools = [get_similar_sessions]
24+
model = AzureChatOpenAI(openai_api_version=os.environ["AZURE_OPENAI_API_VERSION"], azure_deployment=os.environ["AZURE_OPENAI_CHAT_DEPLOYMENT_NAME"])
25+
model = model.bind_tools(tools)
26+
27+
def should_continue(state: MessagesState) -> Literal["tools", END]:
28+
messages = state["messages"]
29+
last_message = messages[-1]
30+
# If the LLM makes a tool call, then we route to the "tools" node
31+
if last_message.tool_calls:
32+
return "tools"
33+
# Otherwise, we stop (reply to the user)
34+
return END
35+
36+
def call_model(state: MessagesState):
37+
messages = state["messages"]
38+
response = model.invoke(messages)
39+
# We return a list, because this will get added to the existing list
40+
return {"messages": [response]}
41+
42+
tool_node = ToolNode(tools=tools)
43+
44+
workflow = StateGraph(MessagesState)
45+
46+
workflow.add_node("agent", call_model)
47+
workflow.add_node("tools", tool_node)
48+
49+
workflow.add_edge(START, "agent")
50+
51+
workflow.add_conditional_edges("agent", should_continue)
52+
53+
workflow.add_edge("tools", "agent")
54+
55+
checkpointer = MemorySaver()
56+
57+
graph = workflow.compile(checkpointer=checkpointer)
58+
59+
@cl.on_message
60+
async def on_message(msg: cl.Message):
61+
config = {"configurable": {"thread_id": cl.context.session.id}}
62+
final_answer = cl.Message(content="")
63+
64+
for msg, metadata in await cl.make_async(graph.stream)(
65+
{"messages": [HumanMessage(content=msg.content)]},
66+
stream_mode="messages",
67+
config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()], **config)
68+
):
69+
if metadata["langgraph_node"] == "agent":
70+
await final_answer.stream_token(msg.content)
71+
72+
await final_answer.send()
73+

chainlit/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ async def on_chat_start():
5656
async def on_message(message: cl.Message):
5757
runnable = cl.user_session.get("runnable") # type: Runnable
5858

59-
msg = cl.Message(content="")
59+
response_message = cl.Message(content="")
6060

6161
for chunk in await cl.make_async(runnable.stream)(
6262
input=message.content,
6363
config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()]),
6464
):
65-
await msg.stream_token(chunk)
65+
await response_message.stream_token(chunk)
6666

67-
await msg.send()
67+
await response_message.send()

chainlit/requirements.txt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
1-
chainlit
2-
langchain
3-
langchain_openai
41
python-dotenv
2+
53
pyodbc
6-
azure-identity
4+
azure-identity
5+
6+
langchain
7+
langchain-openai
8+
langchain-community
9+
langchain-sqlserver
10+
langgraph
11+
12+
chainlit
13+
14+

chainlit/run-langgraph.bat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@chainlit run app-langgraph.py -w
File renamed without changes.

chainlit/run2.bat

Lines changed: 0 additions & 1 deletion
This file was deleted.

chainlit/test-langchain.py

Lines changed: 0 additions & 61 deletions
This file was deleted.

chainlit/utilities.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,33 @@ def get_mssql_connection(source_variable_name: str) -> pyodbc.Connection:
2525

2626
return conn
2727

28-
def get_similar_sessions(search_text:str) -> str:
28+
def get_similar_sessions(topic:str) -> str:
29+
"""
30+
Use this function to get a list of sessions that are potentially relevant for the specified topic.
31+
The sessions are provided in the format of `id|title|abstract|speakers|start-time|end-time`.
32+
33+
"""
2934
conn = get_mssql_connection("AZURE_SQL_CONNECTION_STRING")
3035
logging.info("Querying MSSQL...")
31-
logging.info(f"Message content: '{search_text}'")
36+
logging.info(f"Topic: '{topic}'")
3237
try:
3338
cursor = conn.cursor()
34-
results = cursor.execute("SET NOCOUNT ON; EXEC web.find_sessions @text=?", (search_text)).fetchall()
39+
results = cursor.execute("SET NOCOUNT ON; EXEC web.find_sessions @text=?", (topic)).fetchall()
3540

3641
logging.info(f"Found {len(results)} similar sessions.")
3742

3843
payload = ""
3944
for row in results:
4045
description = str(row[2]).replace("\n", " ")
4146
speakers = ", ".join(json.loads(row[7]))
42-
payload += f'{row[1]}|{description}|{speakers}|{row[4]}|{row[5]}'
47+
payload += f'{row[0]}|{row[1]}|{description}|{speakers}|{row[4]}|{row[5]}'
4348
payload += "\n"
4449

4550
return payload
4651
finally:
4752
cursor.close()
4853

4954
if __name__ == "__main__":
55+
from dotenv import load_dotenv
56+
load_dotenv()
5057
print(get_similar_sessions("SQL and AI"))

0 commit comments

Comments
 (0)