diff --git a/src/interface/web/chat.html b/src/interface/web/chat.html
new file mode 100644
index 00000000..07253b06
--- /dev/null
+++ b/src/interface/web/chat.html
@@ -0,0 +1,261 @@
+
+
+
+
+ Khoj
+
+
+
+
+
+
+
+
+ Khoj
+
+
+
+
+
+
+
+
+
+
diff --git a/src/processor/conversation/gpt.py b/src/processor/conversation/gpt.py
index 5f312b78..c67739d1 100644
--- a/src/processor/conversation/gpt.py
+++ b/src/processor/conversation/gpt.py
@@ -31,7 +31,7 @@ Summarize the below notes about {user_query}:
{text}
-Summarize the notes in second person perspective and use past tense:'''
+Summarize the notes in second person perspective:'''
# Get Response from GPT
response = openai.Completion.create(
@@ -210,20 +210,31 @@ def message_to_prompt(user_message, conversation_history="", gpt_message=None, s
return f"{conversation_history}{restart_sequence} {user_message}{start_sequence}{gpt_message}"
-def message_to_log(user_message, user_message_metadata, gpt_message, conversation_log=[]):
+def message_to_log(user_message, gpt_message, user_message_metadata={}, conversation_log=[]):
"""Create json logs from messages, metadata for conversation log"""
+ default_user_message_metadata = {
+ "intent": {
+ "type": "remember",
+ "memory-type": "notes",
+ "query": user_message
+ },
+ "trigger-emotion": "calm"
+ }
+ current_dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+
# Create json log from Human's message
- human_log = user_message_metadata
+ human_log = user_message_metadata or default_user_message_metadata
human_log["message"] = user_message
- human_log["by"] = "Human"
- human_log["created"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ human_log["by"] = "you"
+ human_log["created"] = current_dt
# Create json log from GPT's response
- ai_log = {"message": gpt_message, "by": "AI", "created": datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
+ khoj_log = {"message": gpt_message, "by": "khoj", "created": current_dt}
- conversation_log.extend([human_log, ai_log])
+ conversation_log.extend([human_log, khoj_log])
return conversation_log
+
def extract_summaries(metadata):
"""Extract summaries from metadata"""
return ''.join(
diff --git a/src/routers/api_beta.py b/src/routers/api_beta.py
index a92443db..021e7e9a 100644
--- a/src/routers/api_beta.py
+++ b/src/routers/api_beta.py
@@ -4,13 +4,14 @@ import logging
from typing import Optional
# External Packages
+import schedule
from fastapi import APIRouter
# Internal Packages
from src.routers.api import search
from src.processor.conversation.gpt import converse, extract_search_type, message_to_log, message_to_prompt, understand, summarize
from src.utils.config import SearchType
-from src.utils.helpers import get_absolute_path, get_from_dict
+from src.utils.helpers import get_from_dict, resolve_absolute_path
from src.utils import state
@@ -46,6 +47,10 @@ def summarize_beta(q: str):
model = state.processor_config.conversation.model
api_key = state.processor_config.conversation.openai_api_key
+ # Load Conversation History
+ chat_session = state.processor_config.conversation.chat_session
+ meta_log = state.processor_config.conversation.meta_log
+
# Converse with OpenAI GPT
result_list = search(q, n=1, t=SearchType.Org, r=True)
collated_result = "\n".join([item.entry for item in result_list])
@@ -57,11 +62,15 @@ def summarize_beta(q: str):
gpt_response = str(e)
status = 'error'
+ # Update Conversation History
+ state.processor_config.conversation.chat_session = message_to_prompt(q, chat_session, gpt_message=gpt_response)
+ state.processor_config.conversation.meta_log['chat'] = message_to_log(q, gpt_response, conversation_log=meta_log.get('chat', []))
+
return {'status': status, 'response': gpt_response}
@api_beta.get('/chat')
-def chat(q: str):
+def chat(q: Optional[str]=None):
# Initialize Variables
model = state.processor_config.conversation.model
api_key = state.processor_config.conversation.openai_api_key
@@ -70,6 +79,10 @@ def chat(q: str):
chat_session = state.processor_config.conversation.chat_session
meta_log = state.processor_config.conversation.meta_log
+ # If user query is empty, return chat history
+ if not q:
+ return {'status': 'ok', 'response': meta_log["chat"]}
+
# Converse with OpenAI GPT
metadata = understand(q, model=model, api_key=api_key, verbose=state.verbose)
logger.debug(f'Understood: {get_from_dict(metadata, "intent")}')
@@ -95,17 +108,16 @@ def chat(q: str):
# Update Conversation History
state.processor_config.conversation.chat_session = message_to_prompt(q, chat_session, gpt_message=gpt_response)
- state.processor_config.conversation.meta_log['chat'] = message_to_log(q, metadata, gpt_response, meta_log.get('chat', []))
+ state.processor_config.conversation.meta_log['chat'] = message_to_log(q, gpt_response, metadata, meta_log.get('chat', []))
return {'status': status, 'response': gpt_response}
-@api_beta.on_event('shutdown')
-def shutdown_event():
+@schedule.repeat(schedule.every(5).minutes)
+def save_chat_session():
# No need to create empty log file
- if not (state.processor_config and state.processor_config.conversation and state.processor_config.conversation.meta_log):
+ if not (state.processor_config and state.processor_config.conversation and state.processor_config.conversation.meta_log and state.processor_config.conversation.chat_session):
return
- logger.debug('INFO:\tSaving conversation logs to disk...')
# Summarize Conversation Logs for this Session
chat_session = state.processor_config.conversation.chat_session
@@ -121,10 +133,13 @@ def shutdown_event():
conversation_log['session'].append(session)
else:
conversation_log['session'] = [session]
+ logger.info('Added new chat session to conversation logs')
# Save Conversation Metadata Logs to Disk
- conversation_logfile = get_absolute_path(state.processor_config.conversation.conversation_logfile)
+ conversation_logfile = resolve_absolute_path(state.processor_config.conversation.conversation_logfile)
+ conversation_logfile.parent.mkdir(parents=True, exist_ok=True) # create conversation directory if doesn't exist
with open(conversation_logfile, "w+", encoding='utf-8') as logfile:
json.dump(conversation_log, logfile)
- logger.info('INFO:\tConversation logs saved to disk.')
+ state.processor_config.conversation.chat_session = None
+ logger.info('Saved updated conversation logs to disk.')
diff --git a/src/routers/web_client.py b/src/routers/web_client.py
index 0c2b8628..4a22e7f7 100644
--- a/src/routers/web_client.py
+++ b/src/routers/web_client.py
@@ -21,3 +21,7 @@ def index():
@web_client.get('/config', response_class=HTMLResponse)
def config_page(request: Request):
return templates.TemplateResponse("config.html", context={'request': request})
+
+@web_client.get("/chat", response_class=FileResponse)
+def chat_page():
+ return FileResponse(constants.web_directory / "chat.html")
\ No newline at end of file