File size: 3,334 Bytes
21dfff9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import anthropic
import os
from dotenv import load_dotenv
from tools.search_tool import search_duckduckgo
from tools.retriever_tool import Retriever

load_dotenv()

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[logging.FileHandler("debug.log"), logging.StreamHandler()]
)

logger = logging.getLogger(__name__)

client = anthropic.Anthropic(
    api_key=os.getenv("ANTHROPIC_API_KEY"),
)
# print("Anthropic API key:", os.getenv("ANTHROPIC_API_KEY"))

retriever = Retriever(
    top_k=3,
    similarity_threshold=0.2,
    batch_size=8 
)

def call_llm(prompt, model="claude-3-7-sonnet-20250219"):
    response = client.messages.create(
        model=model,
        max_tokens=500,
        temperature=0,
        system="""You are an expert clinical AI assistant. You must strictly reply in ONLY one of the following formats: TOOL: [Document], TOOL: [Search], or TOOL: [Both].

For questions about general medical information like recovery times, procedure durations, or standard practices, prefer TOOL: [Search].
For questions about specific medical cases or rare conditions found in the document database, use TOOL: [Document].
For questions that would benefit from both sources, use TOOL: [Both].

Never explain, never say anything else.""",
        messages=[
            {"role": "user", "content": f"""Question: "{prompt}"

Decide the best tool for answering it. Reply exactly with TOOL: [Document], TOOL: [Search], or TOOL: [Both]. No other text."""}
        ]
    )
    return response.content[0].text

def agent_respond(question):
    logger.debug(f"Received question: {question}")
    
    tool_decision = call_llm(
        f"""Decide which tool(s) are needed to answer this question: "{question}".
        Available tools:
        - Document RAG (for clinical facts)
        - Search (for public info)

        Reply in format:
        TOOL: [Document/Search/Both/All]
        """
    )
    
    logger.debug(f"Tool decision raw response: '{tool_decision}'")
    
    use_document = "document" in tool_decision.lower()
    use_search = "search" in tool_decision.lower()
    
    logger.debug(f"Parsed decision - Use Document: {use_document}, Use Search: {use_search}")
    
    results = []
    
    if use_document:
        logger.debug("Retrieving from documents...")
        try:
            doc_info = retriever.query(question)
            logger.debug(f"Document retrieval returned {len(doc_info)} characters")
            results.append(f"Document info:\n{doc_info}")
        except Exception as e:
            logger.error(f"Document retrieval error: {e}")
            results.append(f"Document retrieval error: {str(e)}")
    
    if use_search:
        logger.debug("Searching web...")
        try:
            search_info = search_duckduckgo(question)
            logger.debug(f"Search returned {len(search_info)} characters")
            results.append(f"Search info:\n{search_info}")
        except Exception as e:
            logger.error(f"Search error: {e}")
            results.append(f"Search error: {str(e)}")
    
    if results:
        return "\n\n".join(results)
    else:
        logger.warning("No results from either tool")
        return "Could not determine the right tool to use or both tools failed."