import re from typing import List from loguru import logger import config from llm.call_llm import get_completion, get_completion_from_messages from words_db import words_db from create_db import get_similar_k_words from prompts import trans_prompt, query_prompt, learn_prompt from prompts import system_message_mapper def format_common_prompt(raw_prompt, variable): """get format prompt by repalce variable in raw_prompt """ return raw_prompt.format(variable) def format_chat_prompt(message, chat_history) -> str: """get format prompt """ prompt = "" for turn in chat_history: # add history info user_message, bot_message = turn prompt = f"{prompt}\nUser: {user_message}\nAssistant: {bot_message}" prompt = f"{prompt}\nUser: {message}\nAssistant:" return prompt def respond(message, chat_history, llm="gpt-3.5-turbo", history_len=3, temperature=0.1, max_tokens=2048): """get respond from LLM """ # deal with commands respond_message = command_parser(message) if respond_message: chat_history.append((message, respond_message)) respond_message = "" return respond_message, chat_history # map natural language to command respond_message = command_mapper(message) if respond_message: chat_history.append((message, respond_message)) respond_message = "" return respond_message, chat_history # no commands return, so chat with LLM if message is None or len(message) < 1: return "", chat_history try: chat_history = chat_history[-history_len:] if history_len > 0 else [] # constrain history length formatted_prompt = format_chat_prompt(message, chat_history) # format prompt bot_message = get_completion( formatted_prompt, llm, api_key=config.api_key, temperature=temperature, max_tokens=max_tokens) bot_message = re.sub(r"\\n", '
', bot_message) # replace \n with
chat_history.append((message, bot_message)) return "", chat_history except Exception as e: return e, chat_history def command_parser(input: str) -> str: """parse 4 type commands 1. :add 2. :remove 3. :learn 4. :query return info of action to user """ if input.startswith(":add"): words = input.split(" ")[1:] info = add_words(words) return info if input.startswith(":remove"): words = input.split(" ")[1:] info = remove_words(words) return info if input.startswith(":learn"): if len(input.split(" ")) != 2: return "学习模式将基于词库进行,请指定一个query单词" query = input.split(" ")[1] info = learn_words(query) return f"Based on your query word: {query} and dictionary, learning sentence is:\n{info}" if input.startswith(":query"): if len(input.split(" ")) > 2: return "查询模式仅支持单个单词,请使用:query 进行查询" word = input.split(" ")[1] info = query_word(word) return f"{word}\n{info}" if input.startswith(":show"): info = show_all_words() return info if input.startswith(":help"): return "目前支持的指令有:\n:add ...\n:remove ...\n:learn \n:query " return "" def show_all_words() -> str: """show all words in db """ try: all_words = words_db.query_word() return f"目前词库中的所有单词:\n{all_words}" except Exception as e: logger.error(str(e)) return "查询失败" def add_words(input: List[str]): word_tuple_list = [ (word, get_completion( prompt=format_common_prompt(trans_prompt, word), api_key=config.api_key)) for word in input ] try: for word_tuple in word_tuple_list: word, definition = word_tuple words_db.add_word(word, definition) logger.info(f"已经添加单词: {word} 和其释义: {definition}") except Exception as e: logger.error(str(e)) return f"添加单词失败: {input}" return f"已添加单词: {input}" def remove_words(input: List[str]): try: for word in input: words_db.delete_word(word) logger.info(f"已经删除单词: {word} 和其释义") except Exception as e: logger.error(str(e)) return f"删除单词失败: {input}" return f"已删除单词: {input}" def learn_words(query_word) -> str: # get top 3 words from vec db and generate material words = get_similar_k_words(query_word) respond = get_completion( prompt=format_common_prompt(learn_prompt, words), api_key=config.api_key) logger.info(f"进入学习模式,学习下列单词: {words}") return respond def query_word(input: str) -> str: # just query infomation about a word from gpt respond = get_completion( prompt=format_common_prompt(query_prompt, input), api_key=config.api_key) logger.info(f"查询单词: {input}") return respond def command_mapper(input: str) -> str: """map natural language to command, return command function """ user_message = input messages = [ {'role':'system', 'content': system_message_mapper}, {'role':'user', 'content': f"{user_message}"}, ] respond = get_completion_from_messages(messages, api_key=config) mapped_command = command_parser(respond) logger.info(f"用户输入: {user_message}\n指令解析器输出: {mapped_command}") return mapped_command