File size: 3,556 Bytes
beb32ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed67987
 
34ba0fa
114ee0c
ed67987
 
 
 
 
 
 
 
 
 
5c68cc7
ed67987
5c68cc7
ed67987
 
beb32ed
 
ed67987
beb32ed
5c68cc7
ed67987
 
 
114ee0c
 
ed67987
 
 
 
 
 
 
beb32ed
 
 
 
 
 
ed67987
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
beb32ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d37f75a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
"""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?",
]

# %% - 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. His calendar is booked until the conclusion of 2024.
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,
    clear_btn=None,
    retry_btn=None,
    undo_btn=None,
)


if __name__ == "__main__":
    interface.queue(concurrency_count=20).launch()