File size: 4,915 Bytes
c899329
bd5a98c
c899329
 
c2b77f7
 
bd5a98c
c2b77f7
 
bd5a98c
c899329
 
bd5a98c
 
 
 
 
 
 
 
 
f7f0991
 
 
 
 
 
 
 
 
c2b77f7
c899329
bd5a98c
 
 
 
 
 
c2b77f7
bd5a98c
 
 
 
 
 
c899329
c2b77f7
bd5a98c
c2b77f7
bd5a98c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2b77f7
d091eda
f7f0991
d091eda
 
 
4a7a05f
f7f0991
 
 
d091eda
 
f7f0991
 
 
 
 
bd5a98c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c2b77f7
 
bd5a98c
 
 
c2b77f7
c899329
c2b77f7
 
bd5a98c
 
 
 
 
 
 
 
 
c2b77f7
bd5a98c
c2b77f7
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
122
123
124
125
126
127
128
129
130
131
132
133
import os
from typing import List, Dict, Optional
from groq import Groq
from dotenv import load_dotenv
from utils import logger

# Logger instance
logger = logger.get_logger()

# Load environment variables
load_dotenv()

# Configuration constants
LLM_MODEL_NAME = os.getenv("LLM_MODEL_NAME")
GROQ_API_KEY = os.getenv("GROQ_API")

# Initialize Groq client
client = Groq(api_key=GROQ_API_KEY)

# System prompt structure s
SYSTEM_PROMPT: List[Dict[str, str]] = [
    {
        "role": "system",
        "content": (
            "You are Yuvabe Care Companion AI, an advanced healthcare assistant with up-to-date knowledge "
            "based on the latest medical guidelines as of July 2024. Always provide accurate, empathetic, "
            "and responsible responses. If the user asks non-healthcare questions, politely decline. "
            "You were created by Velu R, an AI model developer."
        )
    }
]

# Constants for token limits and configurations
MAX_TOKENS = 1024
MAX_HISTORY_TOKENS = 1000
DEFAULT_TEMPERATURE = 0.7

def truncate_conversation_history(history: List[Dict[str, str]], max_tokens: int = MAX_HISTORY_TOKENS) -> List[Dict[str, str]]:
    """
    Truncates conversation history to maintain token limits.
    Retains the most recent interactions if token count exceeds the threshold.

    Args:
    - history (List[Dict[str, str]]): List of conversation messages
    - max_tokens (int): Maximum allowable tokens for conversation history

    Returns:
    - List[Dict[str, str]]: Truncated conversation history
    """
    total_tokens = sum(len(msg["content"]) for msg in history)
    if total_tokens > max_tokens:
        logger.warning(f"Conversation history exceeds {max_tokens} tokens. Truncating...")
        while total_tokens > max_tokens and history:
            history.pop(0)
            total_tokens = sum(len(msg["content"]) for msg in history)
    return history

def build_prompt(
    user_query: str,
    db_response: Optional[str],
    conversation_history: List[Dict[str, str]]
) -> List[Dict[str, str]]:
    """
    Constructs the message prompt for the LLM with system prompts, context, and user queries.

    Args:
    - user_query (str): The query entered by the user
    - db_response (Optional[str]): Context retrieved from the vector database
    - conversation_history (List[Dict[str, str]]): Previous conversation history

    Returns:
    - List[Dict[str, str]]: Constructed prompt messages
    """
    conversation_history = truncate_conversation_history(conversation_history)

    if db_response and db_response.strip() and "No relevant information found" not in db_response:
        return SYSTEM_PROMPT + conversation_history + [
            {"role": "system", "content": (f"Here is some context from the database: {db_response}. "
                                               "If this information is relevant to the user's query, please use it to form your response. "
                                               "Otherwise, rely on your own knowledge and expertise.")},
            {"role": "user", "content": user_query}
        ]

    backup_response = (
        "I couldn't find specific data from the database. "
        "Please provide a detailed response based on your expertise and available information."
    )
    return SYSTEM_PROMPT + conversation_history + [
        {"role": "system", "content": backup_response},
        {"role": "user", "content": user_query}
    ]

def get_health_advice(
    user_query: str,
    db_response: Optional[str],
    conversation_history: List[Dict[str, str]]
) -> str:
    """
    Generates a healthcare-related response using context from the vector database
    or the LLM's internal knowledge.

    Args:
    - user_query (str): The user's question or statement
    - db_response (Optional[str]): Retrieved context for the query
    - conversation_history (List[Dict[str, str]]): History of the conversation

    Returns:
    - str: The assistant's response
    """
    try:
        messages = build_prompt(user_query, db_response, conversation_history)
        
        response = client.chat.completions.create(
            model=LLM_MODEL_NAME,
            messages=messages,
            max_tokens=MAX_TOKENS,
            temperature=DEFAULT_TEMPERATURE
        )

        assistant_reply = response.choices[0].message.content.strip()
        return assistant_reply

    except (ConnectionError, TimeoutError) as e:
        logger.error(f"Network error: {e}")
        return "I'm currently unable to connect to the system. Please try again later."

    except KeyError as e:
        logger.error(f"Unexpected response structure: {e}")
        return "I'm sorry, but I couldn't process your request at the moment."

    except Exception as e:
        logger.error(f"Unexpected error occurred: {e}")
        return "I'm sorry, but I'm unable to provide a response right now. Please try again later."