mirror of
https://github.com/khoj-ai/khoj.git
synced 2025-02-17 08:04:21 +00:00
Revert to using GPT to extract search queries from users message
- Reasons: - GPT can extract date aware search queries with date filters better than ChatGPT given the same prompt. - Need quality more than cost savings for now. - Need to figure ways to improve prompt for ChatGPT before using it
This commit is contained in:
parent
e28526bbc9
commit
601ff2541b
2 changed files with 58 additions and 73 deletions
|
@ -9,11 +9,7 @@ import openai
|
||||||
|
|
||||||
# Internal Packages
|
# Internal Packages
|
||||||
from khoj.utils.constants import empty_escape_sequences
|
from khoj.utils.constants import empty_escape_sequences
|
||||||
from khoj.processor.conversation.utils import (
|
from khoj.processor.conversation.utils import message_to_prompt, generate_chatml_messages_with_context
|
||||||
message_to_prompt,
|
|
||||||
message_to_chatml,
|
|
||||||
generate_chatml_messages_with_context,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -82,104 +78,92 @@ Summarize the notes in second person perspective:"""
|
||||||
return str(story).replace("\n\n", "")
|
return str(story).replace("\n\n", "")
|
||||||
|
|
||||||
|
|
||||||
def extract_questions(message, model="gpt-3.5-turbo", conversation_log={}, api_key=None, temperature=0):
|
def extract_questions(text, model="text-davinci-003", conversation_log={}, api_key=None, temperature=0, max_tokens=100):
|
||||||
"""
|
"""
|
||||||
Infer search queries to retrieve relevant notes to respond to user's message
|
Infer search queries to retrieve relevant notes to answer user query
|
||||||
"""
|
"""
|
||||||
# Initialize Variables
|
# Initialize Variables
|
||||||
openai.api_key = api_key or os.getenv("OPENAI_API_KEY")
|
openai.api_key = api_key or os.getenv("OPENAI_API_KEY")
|
||||||
|
|
||||||
|
# Extract Past User Message and Inferred Questions from Conversation Log
|
||||||
|
chat_history = "".join(
|
||||||
|
[
|
||||||
|
f'Q: {chat["intent"]["query"]}\n\n{chat["intent"].get("inferred-queries") or list([chat["intent"]["query"]])}\n\n{chat["message"]}\n\n'
|
||||||
|
for chat in conversation_log.get("chat", [])[-4:]
|
||||||
|
if chat["by"] == "khoj"
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
# Get dates relative to today for prompt creation
|
# Get dates relative to today for prompt creation
|
||||||
today = datetime.today()
|
today = datetime.today()
|
||||||
current_new_year = today.replace(month=1, day=1)
|
current_new_year = today.replace(month=1, day=1)
|
||||||
last_new_year = current_new_year.replace(year=today.year - 1)
|
last_new_year = current_new_year.replace(year=today.year - 1)
|
||||||
|
|
||||||
personality_primer = f"""
|
prompt = f"""
|
||||||
You are Khoj, an extremely smart and helpful search assistant with the ability to retrieve information from the users notes.
|
You are Khoj, an extremely smart and helpful search assistant with the ability to retrieve information from the users notes.
|
||||||
The user will provide their questions and answers to you for context.
|
- The user will provide their questions and answers to you for context.
|
||||||
You can:
|
|
||||||
- Add as much context from the previous questions and answers as required into your search queries.
|
- Add as much context from the previous questions and answers as required into your search queries.
|
||||||
- Break messages into multiple search queries when required to retrieve the relevant information.
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
||||||
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
||||||
|
|
||||||
What searches, if any, will you need to perform to answer the users question?
|
What searches, if any, will you need to perform to answer the users question?
|
||||||
Provide search queries as a JSON list of strings
|
Provide search queries as a JSON list of strings
|
||||||
Current Date: {today.strftime("%H:%M %A %Y-%m-%d")}"""
|
Current Date: {today.strftime("%A, %Y-%m-%d")}
|
||||||
|
|
||||||
# Extract Past User Message and Inferred Questions from Conversation Log
|
Q: How was my trip to Cambodia?
|
||||||
# fmt: off
|
|
||||||
messages = [
|
|
||||||
# Add system message to prime GPT for the task
|
|
||||||
message_to_chatml(personality_primer, role="system"),
|
|
||||||
|
|
||||||
# Add example user message, inferred question and answer triplets to explain the task
|
["How was my trip to Cambodia?"]
|
||||||
message_to_chatml("Q: How was my trip to Cambodia?", role="user"),
|
|
||||||
message_to_chatml('["How was my trip to Cambodia?"]', role="assistant"),
|
|
||||||
message_to_chatml("A: The trip was amazing. I went to the Angkor Wat temple in August 2017 and it was beautiful.", role="user"),
|
|
||||||
|
|
||||||
message_to_chatml("Q: Who did I visit that temple with?", role="user"),
|
A: The trip was amazing. I went to the Angkor Wat temple and it was beautiful.
|
||||||
message_to_chatml('["Who did I visit the Angkor Wat Temple in Cambodia with? dt>=\\"2017-08-01\\" dt<\\"2017-09-01\\""]', role="assistant"),
|
|
||||||
message_to_chatml("A: You visited the Angkor Wat Temple in Cambodia with Pablo, Namita and Xi.", role="user"),
|
|
||||||
|
|
||||||
message_to_chatml("Q: What national parks did I go to last year?", role="user"),
|
Q: Who did i visit that temple with?
|
||||||
message_to_chatml(
|
|
||||||
f'["National park I visited in {last_new_year.strftime("%Y")} dt>=\\"{last_new_year.strftime("%Y-%m-%d")}\\" dt<\\"{current_new_year.strftime("%Y-%m-%d")}\\""]',
|
|
||||||
role="assistant",
|
|
||||||
),
|
|
||||||
message_to_chatml(
|
|
||||||
f'A: You visited the Grand Canyon and Yellowstone National Park in {last_new_year.strftime("%Y")}.',
|
|
||||||
role="user",
|
|
||||||
),
|
|
||||||
|
|
||||||
message_to_chatml("Q: How are you feeling?", role="user"),
|
["Who did I visit the Angkor Wat Temple in Cambodia with?"]
|
||||||
message_to_chatml("[]", role="assistant"),
|
|
||||||
message_to_chatml("A: I'm feeling a little bored. Helping you will hopefully make me feel better!", role="user"),
|
|
||||||
|
|
||||||
message_to_chatml("Q: How many tennis balls fit in the back of a 2002 Honda Civic?", role="user"),
|
A: You visited the Angkor Wat Temple in Cambodia with Pablo, Namita and Xi.
|
||||||
message_to_chatml('["What is the size of a tennis ball?", "What is the trunk size of a 2002 Honda Civic?"]', role="assistant"),
|
|
||||||
message_to_chatml("A: 1085 tennis balls will fit in the trunk of a Honda Civic", role="user"),
|
|
||||||
|
|
||||||
message_to_chatml("Q: Is Bob older than Tom?", role="user"),
|
Q: What national parks did I go to last year?
|
||||||
message_to_chatml('["When was Bob born?", "What is Tom\'s age?"]', role="assistant"),
|
|
||||||
message_to_chatml("A: Yes, Bob is older than Tom. As Bob was born on 1984-01-01 and Tom is 30 years old.", role="user"),
|
|
||||||
|
|
||||||
message_to_chatml("Q: What is their age difference?", role="user"),
|
["National park I visited in {last_new_year.strftime("%Y")} dt>=\\"{last_new_year.strftime("%Y-%m-%d")}\\" dt<\\"{current_new_year.strftime("%Y-%m-%d")}\\""]
|
||||||
message_to_chatml('["What is Bob\'s age?", "What is Tom\'s age?"]', role="assistant"),
|
|
||||||
message_to_chatml(
|
|
||||||
f"A: Bob is {current_new_year.year - 1984 - 30} years older than Tom. As Bob is {current_new_year.year - 1984} years old and Tom is 30 years old.",
|
|
||||||
role="user",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
# fmt: on
|
|
||||||
|
|
||||||
# Add last few user messages, inferred queries and answer triplets from actual conversation for context
|
A: You visited the Grand Canyon and Yellowstone National Park in {last_new_year.strftime("%Y")}.
|
||||||
for chat in conversation_log.get("chat", [])[-4:]:
|
|
||||||
if chat["by"] == "khoj":
|
|
||||||
queries = (
|
|
||||||
chat["intent"]["inferred-queries"]
|
|
||||||
if chat["intent"].get("inferred-queries", "[]") != "[]"
|
|
||||||
else [chat["intent"]["query"]]
|
|
||||||
)
|
|
||||||
messages.extend(
|
|
||||||
[
|
|
||||||
message_to_chatml(f'Q: {chat["intent"]["query"]}', role="user"),
|
|
||||||
message_to_chatml(f"{queries}", role="assistant"),
|
|
||||||
message_to_chatml(f'{chat["message"]}', role="user"),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
# Finally add current user message for which to infer search queries to ChatML message list
|
Q: How are you feeling today?
|
||||||
messages.append(message_to_chatml(f"Q: {message}", role="user"))
|
|
||||||
|
[]
|
||||||
|
|
||||||
|
A: I'm feeling a little bored. Helping you will hopefully make me feel better!
|
||||||
|
|
||||||
|
Q: How many tennis balls fit in the back of a 2002 Honda Civic?
|
||||||
|
|
||||||
|
["What is the size of a tennis ball?", "What is the trunk size of a 2002 Honda Civic?"]
|
||||||
|
|
||||||
|
A: 1085 tennis balls will fit in the trunk of a Honda Civic
|
||||||
|
|
||||||
|
Q: Is Bob older than Tom?
|
||||||
|
|
||||||
|
["When was Bob born?", "What is Tom's age?"]
|
||||||
|
|
||||||
|
A: Yes, Bob is older than Tom. As Bob was born on 1984-01-01 and Tom is 30 years old.
|
||||||
|
|
||||||
|
Q: What is their age difference?
|
||||||
|
|
||||||
|
["What is Bob's age?", "What is Tom's age?"]
|
||||||
|
|
||||||
|
A: Bob is {current_new_year.year - 1984 - 30} years older than Tom. As Bob is {current_new_year.year - 1984} years old and Tom is 30 years old.
|
||||||
|
|
||||||
|
{chat_history}
|
||||||
|
Q: {text}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
# Get Response from GPT
|
# Get Response from GPT
|
||||||
response = openai.ChatCompletion.create(
|
response = openai.Completion.create(
|
||||||
messages=messages,
|
prompt=prompt, model=model, temperature=temperature, max_tokens=max_tokens, stop=["A: ", "\n"]
|
||||||
model=model,
|
|
||||||
temperature=temperature,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Extract, Clean Message from GPT's Response
|
# Extract, Clean Message from GPT's Response
|
||||||
response_text = response["choices"][0]["message"]["content"]
|
response_text = response["choices"][0]["text"]
|
||||||
try:
|
try:
|
||||||
questions = json.loads(
|
questions = json.loads(
|
||||||
# Clean response to increase likelihood of valid JSON. E.g replace ' with " to enclose strings
|
# Clean response to increase likelihood of valid JSON. E.g replace ' with " to enclose strings
|
||||||
|
@ -189,7 +173,7 @@ Current Date: {today.strftime("%H:%M %A %Y-%m-%d")}"""
|
||||||
.replace("', '", '", "')
|
.replace("', '", '", "')
|
||||||
)
|
)
|
||||||
except json.decoder.JSONDecodeError:
|
except json.decoder.JSONDecodeError:
|
||||||
logger.warn(f"GPT returned invalid JSON. Set question to empty list.\n{response_text}")
|
logger.warn(f"GPT returned invalid JSON. Falling back to using user message as search query.\n{response_text}")
|
||||||
questions = [text]
|
questions = [text]
|
||||||
logger.debug(f"Extracted Questions by GPT: {questions}")
|
logger.debug(f"Extracted Questions by GPT: {questions}")
|
||||||
return questions
|
return questions
|
||||||
|
|
|
@ -191,6 +191,7 @@ def update(t: Optional[SearchType] = None, force: Optional[bool] = False):
|
||||||
def chat(q: Optional[str] = None):
|
def chat(q: Optional[str] = None):
|
||||||
# Initialize Variables
|
# Initialize Variables
|
||||||
api_key = state.processor_config.conversation.openai_api_key
|
api_key = state.processor_config.conversation.openai_api_key
|
||||||
|
model = state.processor_config.conversation.model
|
||||||
|
|
||||||
# Load Conversation History
|
# Load Conversation History
|
||||||
chat_session = state.processor_config.conversation.chat_session
|
chat_session = state.processor_config.conversation.chat_session
|
||||||
|
@ -204,7 +205,7 @@ def chat(q: Optional[str] = None):
|
||||||
return {"status": "ok", "response": []}
|
return {"status": "ok", "response": []}
|
||||||
|
|
||||||
# Infer search queries from user message
|
# Infer search queries from user message
|
||||||
inferred_queries = extract_questions(q, api_key=api_key, conversation_log=meta_log)
|
inferred_queries = extract_questions(q, model=model, api_key=api_key, conversation_log=meta_log)
|
||||||
|
|
||||||
# Collate search results as context for GPT
|
# Collate search results as context for GPT
|
||||||
result_list = []
|
result_list = []
|
||||||
|
|
Loading…
Add table
Reference in a new issue