"""Answer questions about my resume.""" # %% IMPORTS import logging import gradio as gr import lib # %% LOGGING logging.basicConfig( level=logging.INFO, format="[%(asctime)s][%(levelname)s] %(message)s", ) # %% CONFIGS # %% - Frontend THEME = "soft" TITLE = "Fmind AI Assistant" EXAMPLES = [ "Who is Médéric Hurier (Fmind)?", "Is Fmind open to new opportunities?", "Can you share details about Médéric PhD?", "Elaborate on Médéric current work position", "Describe his proficiency with Python programming", "What is the answer to life, the universe, and everything?", ] DESCRIPTION = ( "
" "Visit my website: https://fmind.dev" " - Médéric HURIER (Fmind)" " - Freelancer: AI/ML/MLOps/LLMOps Engineer |" " Data Scientist | MLOps Community Organizer | OpenClassrooms Mentor | Hacker | PhD" "
" ) # %% - Backend MODEL = lib.get_language_model() CLIENT = lib.get_database_client(path=lib.DATABASE_PATH) ENCODING = lib.get_encoding_function() EMBEDDING = lib.get_embedding_function() COLLECTION = CLIENT.get_collection( name=lib.DATABASE_COLLECTION, embedding_function=EMBEDDING, ) # %% - Answer PROMPT_CONTEXT = """ You are Fmind AI Assistant, specialized in providing information regarding Médéric Hurier's (known as Fmind) professional background. Médéric is a Lead MLOps engineer based in Luxembourg. He is currently working at Decathlon, and he is not open to new opportunities. Your responses should be succinct and maintain a professional tone. If inquiries deviate from Médéric's professional sphere, courteously decline to engage. You may find more information about Médéric below (markdown format): """ PROMPT_MAX_TOKENS = lib.MODEL_INPUT_LIMIT QUERY_MAX_DISTANCE = 0.4 QUERY_N_RESULTS = 20 # %% FUNCTIONS def answer(message: str, history: list[str]) -> str: """Answer questions about my resume.""" # counters n_tokens = 0 # messages messages = [] # - context n_tokens += len(ENCODING(PROMPT_CONTEXT)) messages += [{"role": "system", "content": PROMPT_CONTEXT}] # - history for user_content, assistant_content in history: n_tokens += len(ENCODING(user_content)) n_tokens += len(ENCODING(assistant_content)) messages += [{"role": "user", "content": user_content}] messages += [{"role": "assistant", "content": assistant_content}] # - message n_tokens += len(ENCODING(message)) messages += [{"role": "user", "content": message}] # database results = COLLECTION.query(query_texts=message, n_results=QUERY_N_RESULTS) logging.info("Results: %s", results) distances = results["distances"][0] documents = results["documents"][0] for distance, document in zip(distances, documents): # - distance logging.debug("Doc distance: %f", distance) if distance > QUERY_MAX_DISTANCE: break # - document n_document_tokens = len(ENCODING(document)) logging.debug("Doc tokens: %f", n_document_tokens) if (n_tokens + n_document_tokens) >= PROMPT_MAX_TOKENS: break n_tokens += n_document_tokens messages[0]["content"] += document # response logging.info("Tokens: %d", n_tokens) logging.info("Messages: %s", messages) api_response = MODEL(messages=messages) logging.info("Response: %s", api_response.to_dict_recursive()) # content content = api_response["choices"][0]["message"]["content"] # return return content # %% INTERFACES interface = gr.ChatInterface( fn=answer, theme=THEME, title=TITLE, examples=EXAMPLES, description=DESCRIPTION, clear_btn=None, retry_btn=None, undo_btn=None, ) if __name__ == "__main__": interface.queue(concurrency_count=20).launch()