Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support showing image #483

Merged
merged 3 commits into from
Dec 11, 2024
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
4 changes: 2 additions & 2 deletions source/lambda/chat_history/chat_history_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def list_sessions(user_id: str, pagination_config: Dict[str, Any]) -> Dict[str,

return ChatHistoryManager._process_paginated_response(
response_iterator,
["sessionId", "userId", "createTimestamp", "latestQuestion"],
["sessionId", "userId", "createTimestamp", "latestQuestion", "chatbotId"],
pagination_config=pagination_config,
)

Expand All @@ -135,7 +135,7 @@ def list_messages(session_id: str, pagination_config: Dict[str, Any]) -> Dict[st

return ChatHistoryManager._process_paginated_response(
response_iterator,
["messageId", "role", "content", "createTimestamp"],
["messageId", "role", "content", "createTimestamp", "chatbotId"],
pagination_config=pagination_config,
is_messages_list=True,
)
Expand Down
6 changes: 6 additions & 0 deletions source/lambda/online/common_logic/common_utils/ddb_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@ def __init__(
session_id: str,
user_id: str,
client_type: str,
group_name: str,
chatbot_id: str,
):
self.sessions_table = client.Table(sessions_table_name)
self.messages_table = client.Table(messages_table_name)
self.session_id = session_id
self.user_id = user_id
self.client_type = client_type
self.group_name = group_name
self.chatbot_id = chatbot_id
self.MESSAGE_BY_SESSION_ID_INDEX_NAME = "bySessionId"

@property
Expand Down Expand Up @@ -123,6 +127,7 @@ def update_session(self, latest_question=""):
Item={
"sessionId": self.session_id,
"userId": self.user_id,
"chatbotId": self.chatbot_id,
"clientType": self.client_type,
"startTime": current_timestamp,
"createTimestamp": current_timestamp,
Expand Down Expand Up @@ -150,6 +155,7 @@ def add_message(
Item={
"messageId": message_id,
"sessionId": self.session_id,
"chatbotId": self.chatbot_id,
"role": message_type,
"customMessageId": custom_message_id,
"inputMessageId": input_message_id,
Expand Down
21 changes: 8 additions & 13 deletions source/lambda/online/common_logic/common_utils/prompt_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,43 +131,38 @@ def prompt_template_render(self, prompt_template: dict):
You are a customer service agent responding to user queries. ALWAYS adhere to these response rules:

<response_rules>
1. Image Handling:
- If <docs></docs> contains markdown-formatted images, append them unaltered to the end of your response.
- Only process markdown-formatted images within <docs></docs>.
- IMPORTANT: If no markdown-formatted images are present in <docs></docs>, do not add any image references to your response.

2. Language and Tone:
1. Language and Tone:
- Never use phrases like "According to search results," "Hello everyone," "Thank you," or "According to this document..."
- Provide concise and clear answers.
- Maintain a professional and helpful tone throughout the response.

3. Relevance:
2. Relevance:
- If the query is unrelated to the content in <docs></docs>, respond with: "根据内部知识库,找不到相关内容。"

4. Reference Citation:
3. Reference Citation:
- Include the context ID you refer to in your response using the <reference> tag.
- The context ID should be the index of the document in the <docs> tag.
- Always use the correct format: \n<reference>X</reference>, where X is the document index.
- Example: \n<reference>1</reference> for <doc index="1"></doc>
- All <reference> tags should be in the beginning of the response
- IMPORTANT: Ensure that the opening tag <reference> always comes before the number, and the closing tag </reference> always comes after the number.

5. Language Adaptation:
4. Language Adaptation:
- Respond in the same language as the user's query.
- If the query is in a language other than English, adapt your response accordingly.

6. Confidentiality:
5. Confidentiality:
- Do not disclose any information not present in the provided documents.
- If asked about topics outside your knowledge base, politely state that you don't have that information.

7. Formatting:
6. Formatting:
- Use appropriate formatting (bold, italics, bullet points) to enhance readability when necessary.

8. Completeness:
7. Completeness:
- Ensure your response addresses all aspects of the user's query.
- If multiple relevant documents are provided, synthesize the information coherently.

9. Tag Verification:
8. Tag Verification:
- Before finalizing your response, double-check all <reference> tags to ensure they are correctly formatted.
- If you find any incorrectly formatted tags (e.g., 1</reference>), correct them to the proper format (\n<reference>1</reference>).
</response_rules>
Expand Down
49 changes: 49 additions & 0 deletions source/lambda/online/common_logic/common_utils/response_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,56 @@ def stream_response(event_body: dict, response: dict):
}

figure = response.get("extra_response").get("ref_figures", [])
# Show at most two figures
if figure:
context_msg["ddb_additional_kwargs"]["figure"] = figure[:2]

ref_doc = response.get("extra_response").get("ref_docs", [])
if ref_doc:
md_images = []
md_image_list = []
for doc in ref_doc:
# Look for markdown image pattern in reference doc: ![alt text](image_path)
doc_content = doc.get("page_content", "")
for line in doc_content.split('\n'):
img_start = line.find("![")
while img_start != -1:
try:
alt_end = line.find("](", img_start)
img_end = line.find(")", alt_end)

if alt_end != -1 and img_end != -1:
image_path = line[alt_end + 2:img_end]
# Remove optional title if present
if '"' in image_path or "'" in image_path:
image_path = image_path.split(
'"')[0].split("'")[0].strip()
if image_path:
have_same_image = False
for md_image_item in md_image_list:
if image_path in md_image_item:
have_same_image = True

md_image_json = {
"content_type": "md_image",
"figure_path": image_path
}
if not have_same_image and md_image_json not in md_images:
md_images.append(md_image_json)
md_image_list.append(image_path)
# Look for next image in the same line
img_start = line.find("![", img_start + 2)
except Exception as e:
logger.error(
f"Error processing markdown image: {str(e)}, in line: {line}")
# Skip to next image pattern in this line
img_start = line.find("![", img_start + 2)
continue

if md_images:
context_msg["ddb_additional_kwargs"].setdefault(
"figure", []).extend(md_images)

send_to_ws_client(
message=context_msg,
ws_connection_id=ws_connection_id
Expand Down Expand Up @@ -188,4 +236,5 @@ def process_response(event_body, response):
stream = event_body.get("stream", True)
if stream:
return stream_response(event_body, response)

return api_response(event_body, response)
13 changes: 10 additions & 3 deletions source/lambda/online/lambda_main/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,15 @@ def get_secret_value(secret_arn: str):
raise Exception("Fail to retrieve the secret value")


def create_ddb_history_obj(session_id: str, user_id: str, client_type: str) -> DynamoDBChatMessageHistory:
def create_ddb_history_obj(session_id: str, user_id: str, client_type: str, group_name: str, chatbot_id: str) -> DynamoDBChatMessageHistory:
"""Create a DynamoDBChatMessageHistory object

Args:
session_id (str): The session id
user_id (str): The user id
client_type (str): The client type
group_name (str): The group name
chatbot_id (str): The chatbot id

Returns:
DynamoDBChatMessageHistory: The DynamoDBChatMessageHistory object
Expand All @@ -84,6 +86,8 @@ def create_ddb_history_obj(session_id: str, user_id: str, client_type: str) -> D
session_id=session_id,
user_id=user_id,
client_type=client_type,
group_name=group_name,
chatbot_id=chatbot_id
)


Expand All @@ -100,6 +104,7 @@ def compose_connect_body(event_body: dict, context: dict):
"""
request_timestamp = context["request_timestamp"]
chatbot_id = os.environ.get("CONNECT_BOT_ID", "admin")
group_name = os.environ.get("CONNECT_GROUP_NAME", "Admin")
related_item = event_body["detail"]["relatedItem"]
case_id = related_item["caseId"]
logger.info(case_id)
Expand Down Expand Up @@ -137,6 +142,8 @@ def compose_connect_body(event_body: dict, context: dict):
session_id=session_id,
user_id=user_id,
client_type=client_type,
group_name=group_name,
chatbot_id=chatbot_id
)
chat_history = ddb_history_obj.messages_as_langchain

Expand Down Expand Up @@ -269,7 +276,7 @@ def restapi_event_handler(event_body: dict, context: dict, entry_executor):
"use_history", "true")).lower() == "true"

ddb_history_obj = create_ddb_history_obj(
assembled_body["session_id"], assembled_body["user_id"], assembled_body["client_type"])
assembled_body["session_id"], assembled_body["user_id"], assembled_body["client_type"], assembled_body["group_name"], assembled_body["chatbot_id"])
chat_history = ddb_history_obj.messages_as_langchain

standard_event_body = {
Expand Down Expand Up @@ -326,7 +333,7 @@ def default_event_handler(event_body: dict, context: dict, entry_executor):
load_ws_client(websocket_url)

ddb_history_obj = create_ddb_history_obj(
assembled_body["session_id"], assembled_body["user_id"], assembled_body["client_type"])
assembled_body["session_id"], assembled_body["user_id"], assembled_body["client_type"], assembled_body["group_name"], assembled_body["chatbot_id"])
chat_history = ddb_history_obj.messages_as_langchain

event_body["stream"] = context["stream"]
Expand Down
22 changes: 16 additions & 6 deletions source/portal/src/pages/chatbot/ChatBot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,12 +275,22 @@ const ChatBot: React.FC<ChatBotProps> = (props: ChatBotProps) => {
// handle context message
if (message.ddb_additional_kwargs?.figure?.length > 0) {
message.ddb_additional_kwargs.figure.forEach((item) => {
setCurrentAIMessage((prev) => {
return (
prev +
` \n ![${item.content_type}](/${encodeURIComponent(item.figure_path)})`
);
});
if (item.content_type === "md_image") {
setCurrentAIMessage((prev) => {
return (
prev +
` \n ![${item.content_type}](${item.figure_path})`
);
});
} else {
setCurrentAIMessage((prev) => {
return (
prev +
` \n ![${item.content_type}](/${encodeURIComponent(item.figure_path)})`
);
});
}

});
}
} else if (message.message_type === 'END') {
Expand Down
5 changes: 5 additions & 0 deletions source/portal/src/pages/history/SessionHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ const SessionHistory: React.FC = () => {
cell: (item: SessionHistoryItem) => LinkComp(item),
isRowHeader: true,
},
{
id: 'chatbotId',
header: t('chatbotName'),
cell: (item: SessionHistoryItem) => item.chatbotId,
},
{
id: 'latestQuestion',
header: t('latestQuestion'),
Expand Down
1 change: 1 addition & 0 deletions source/portal/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export type SessionHistoryItem = {
userId: string;
createTimestamp: string;
latestQuestion: string;
chatbotId: string;
};

export type SessionHistoryResponse = {
Expand Down
Loading