Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ COSMOSDB_DATABASE_NAME="template_langgraph"
COSMOSDB_CONTAINER_NAME="kabuto"
COSMOSDB_PARTITION_KEY="/id"

# SQL Database Settings
SQL_DATABASE_URI="sqlite:///template_langgraph.db"

# ---------
# Utilities
# ---------
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,4 @@ requirements.txt
assets/
.langgraph_api
generated/
*.db
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@

from template_langgraph.agents.chat_with_tools_agent.agent import AgentState, graph

if "chat_history" not in st.session_state:
st.session_state["chat_history"] = []

for msg in st.session_state["chat_history"]:
if isinstance(msg, dict):
st.chat_message(msg["role"]).write(msg["content"])
else:
st.chat_message("assistant").write(msg.content)
Comment on lines +12 to +15
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mixed message format handling (dict vs object with .content attribute) suggests inconsistent data structures. Consider standardizing the message format or adding type hints to clarify the expected structure.

Suggested change
if isinstance(msg, dict):
st.chat_message(msg["role"]).write(msg["content"])
else:
st.chat_message("assistant").write(msg.content)
st.chat_message(msg["role"]).write(msg["content"])

Copilot uses AI. Check for mistakes.


if prompt := st.chat_input():
st.session_state["chat_history"].append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)
with st.chat_message("assistant"):
response: AgentState = graph.invoke(
{
"messages": [
{
"role": "user",
"content": prompt,
},
]
},
{"messages": st.session_state["chat_history"]},
{
"callbacks": [
StreamlitCallbackHandler(st.container()),
]
},
)
st.session_state["chat_history"].append(response["messages"][-1])
st.write(response["messages"][-1].content)
6 changes: 5 additions & 1 deletion template_langgraph/tools/common.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
from template_langgraph.llms.azure_openais import AzureOpenAiWrapper
from template_langgraph.tools.cosmosdb_tool import search_cosmosdb
from template_langgraph.tools.dify_tool import run_dify_workflow
from template_langgraph.tools.elasticsearch_tool import search_elasticsearch
from template_langgraph.tools.qdrant_tool import search_qdrant
from template_langgraph.tools.sql_database_tool import SqlDatabaseClientWrapper

DEFAULT_TOOLS = [
search_cosmosdb,
run_dify_workflow,
search_qdrant,
search_elasticsearch,
]
] + SqlDatabaseClientWrapper().get_tools(
llm=AzureOpenAiWrapper().chat_model,
)
Comment on lines 8 to +15
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Creating SqlDatabaseClientWrapper and AzureOpenAiWrapper instances at module import time can cause initialization delays and potential connection issues. Consider lazy initialization or moving this to a function that's called when needed.

Copilot uses AI. Check for mistakes.

45 changes: 45 additions & 0 deletions template_langgraph/tools/sql_database_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from functools import lru_cache

from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_core.language_models import BaseLanguageModel
from langchain_core.tools.base import BaseTool
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
sql_database_uri: str = "sqlite:///template_langgraph.db"

model_config = SettingsConfigDict(
env_file=".env",
env_ignore_empty=True,
extra="ignore",
)


@lru_cache
def get_sql_database_settings() -> Settings:
"""Get SQL Database settings."""
return Settings()


class SqlDatabaseClientWrapper:
def __init__(
self,
settings: Settings = None,
Copy link
Preview

Copilot AI Aug 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using mutable default arguments with None and then reassigning is a common pattern, but using 'settings: Settings | None = None' would be more explicit about the type annotation in modern Python.

Suggested change
settings: Settings = None,
settings: Settings | None = None,

Copilot uses AI. Check for mistakes.

):
if settings is None:
settings = get_sql_database_settings()
self.db = SQLDatabase.from_uri(
database_uri=settings.sql_database_uri,
)

def get_tools(
self,
llm: BaseLanguageModel,
) -> list[BaseTool]:
"""Get SQL Database tools."""
return SQLDatabaseToolkit(
db=self.db,
llm=llm,
).get_tools()