Skip to content

Commit 2ddb48c

Browse files
authored
Merge pull request #167 from oracle-samples/164-endpoint-for-new-conversation
Implement API call to clear history
2 parents 39e3a21 + a69a593 commit 2ddb48c

File tree

4 files changed

+55
-16
lines changed

4 files changed

+55
-16
lines changed

src/client/utils/st_common.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import os
88
from io import BytesIO
99
from typing import Union
10-
from uuid import uuid4
1110
import pandas as pd
1211

1312
import streamlit as st
@@ -19,20 +18,14 @@
1918

2019
import common.help_text as help_text
2120
import common.logging_config as logging_config
22-
from common.schema import ClientIdType, PromptPromptType, PromptNameType
21+
from common.schema import PromptPromptType, PromptNameType
2322

2423
logger = logging_config.logging.getLogger("client.utils.st_common")
2524

2625

2726
#############################################################################
2827
# Common Helpers
2928
#############################################################################
30-
def client_gen_id() -> ClientIdType:
31-
"""Generate a new client ID; can be used to clear history"""
32-
logger.info("Creating new client identifier")
33-
return str(uuid4())
34-
35-
3629
def local_file_payload(uploaded_files: Union[BytesIO, list[BytesIO]]) -> list:
3730
"""Upload Single file from Streamlit to the Server"""
3831
# If it's a single file, convert it to a list for consistent processing
@@ -122,8 +115,11 @@ def history_sidebar() -> None:
122115
on_change=update_user_settings("ll_model"),
123116
)
124117
if button_col.button("Clear", disabled=not chat_history_enable, use_container_width=True):
125-
# Establish a new thread
126-
state.user_settings["client"] = client_gen_id()
118+
# Clean out history
119+
try:
120+
api_call.patch(endpoint="v1/chat/history")
121+
except api_call.ApiError as ex:
122+
logger.error("Clearing Chat History for %s failed: %s", state.user_settings["client"], ex)
127123
clear_state_key("user_client")
128124

129125

src/launch_client.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
# spell-checker:ignore streamlit, scriptrunner
99

1010
import os
11+
from uuid import uuid4
1112

1213
import streamlit as st
1314
from streamlit import session_state as state
1415

1516
from client.utils import api_call
16-
from client.utils.st_common import set_server_state, client_gen_id
17+
from client.utils.st_common import set_server_state
1718

1819
import common.logging_config as logging_config
1920

@@ -62,7 +63,7 @@ def main() -> None:
6263
if "user_settings" not in state:
6364
try:
6465
state.user_settings = api_call.post(
65-
endpoint="v1/settings", params={"client": client_gen_id()}, retries=10, backoff_factor=1.5
66+
endpoint="v1/settings", params={"client": str(uuid4())}, retries=10, backoff_factor=1.5
6667
)
6768
except api_call.ApiError:
6869
logger.error("Unable to contact API Server; setting as Down!")

src/server/endpoints.py

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@
1818
from pydantic import HttpUrl
1919

2020
from langgraph.graph.state import CompiledStateGraph
21-
from langchain_core.messages import HumanMessage, AnyMessage, convert_to_openai_messages, ChatMessage
21+
from langgraph.graph.message import REMOVE_ALL_MESSAGES
22+
from langchain_core.messages import (
23+
HumanMessage,
24+
AnyMessage,
25+
convert_to_openai_messages,
26+
ChatMessage,
27+
RemoveMessage,
28+
)
2229
from langchain_core.runnables import RunnableConfig
2330
from giskard.rag import evaluate, QATestset
2431
from giskard.rag.metrics import correctness_metric
@@ -729,12 +736,32 @@ async def chat_stream(request: schema.ChatRequest, client: schema.ClientIdType =
729736
media_type="application/octet-stream",
730737
)
731738

739+
@auth.patch(
740+
"/v1/chat/history",
741+
description="Delete Chat History",
742+
response_model=list[schema.ChatMessage],
743+
)
744+
async def chat_history_clean(client: schema.ClientIdType = Header(...)) -> list[ChatMessage]:
745+
agent: CompiledStateGraph = chatbot.chatbot_graph
746+
try:
747+
_ = agent.update_state(
748+
config=RunnableConfig(
749+
configurable={
750+
"thread_id": client,
751+
}
752+
),
753+
values={"messages": RemoveMessage(id=REMOVE_ALL_MESSAGES)},
754+
)
755+
return [ChatMessage(content="As requested, I've forgotten our conversation.", role="system")]
756+
except KeyError:
757+
return [ChatMessage(content="I'm sorry, I have no history of this conversation.", role="system")]
758+
732759
@auth.get(
733760
"/v1/chat/history",
734761
description="Get Chat History",
735762
response_model=list[schema.ChatMessage],
736763
)
737-
async def chat_history(client: schema.ClientIdType = Header(...)) -> list[ChatMessage]:
764+
async def chat_history_return(client: schema.ClientIdType = Header(...)) -> list[ChatMessage]:
738765
"""Return Chat History"""
739766
agent: CompiledStateGraph = chatbot.chatbot_graph
740767
try:
@@ -749,7 +776,7 @@ async def chat_history(client: schema.ClientIdType = Header(...)) -> list[ChatMe
749776
chat_messages = convert_to_openai_messages(messages)
750777
return chat_messages
751778
except KeyError:
752-
return [ChatMessage(content="I'm sorry, I have no history of this conversation", role="system")]
779+
return [ChatMessage(content="I'm sorry, I have no history of this conversation.", role="system")]
753780

754781
#################################################
755782
# testbed Endpoints

tests/server/test_endpoints_chat.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,13 @@ class TestNoAuthEndpoints:
2929
{"endpoint": "/v1/chat/streams", "method": "post"},
3030
id="chat_stream",
3131
),
32+
pytest.param(
33+
{"endpoint": "/v1/chat/history", "method": "patch"},
34+
id="chat_history_clean",
35+
),
3236
pytest.param(
3337
{"endpoint": "/v1/chat/history", "method": "get"},
34-
id="chat_history",
38+
id="chat_history_return",
3539
),
3640
]
3741

@@ -173,6 +177,17 @@ def test_chat_history_valid(self, client: TestClient):
173177
assert history[0]["role"] == "user"
174178
assert history[0]["content"] == "Hello"
175179

180+
def test_chat_history_clean(self, client: TestClient):
181+
"""Test chat history with no history"""
182+
with patch("server.agents.chatbot.chatbot_graph") as mock_graph:
183+
mock_graph.get_state.side_effect = KeyError()
184+
response = client.patch("/v1/chat/history", headers=TEST_HEADERS)
185+
assert response.status_code == 200
186+
history = response.json()
187+
assert len(history) == 1
188+
assert history[0]["role"] == "system"
189+
assert "forgotten" in history[0]["content"].lower()
190+
176191
def test_chat_history_empty(self, client: TestClient):
177192
"""Test chat history with no history"""
178193
with patch("server.agents.chatbot.chatbot_graph") as mock_graph:

0 commit comments

Comments
 (0)