anam_code / agent /tools.py
Vaibhav Kathait
Initial deploy
6754826
Raw History Blame Contribute Delete
7.7 kB
import asyncio
import json
from datetime import datetime
import blood_rag
import reports
from rag import search_supplements as _search_supplements
# ── Notepad state ──────────────────────────────────────────────────────────────
_notes: list = [] # [{"id": int, "text": str, "time": str}]
_listeners: list = [] # one asyncio.Queue per connected SSE client
_counter: int = 0
def _broadcast(payload: dict):
data = json.dumps(payload)
for q in list(_listeners):
try:
q.put_nowait(data)
except asyncio.QueueFull:
pass
def add_listener(q: asyncio.Queue):
_listeners.append(q)
def remove_listener(q: asyncio.Queue):
if q in _listeners:
_listeners.remove(q)
def get_notes_snapshot() -> dict:
return {"notes": list(_notes)}
# ── Tool implementations ───────────────────────────────────────────────────────
def write_to_notepad(text: str) -> str:
global _counter
_counter += 1
entry = {
"id": _counter,
"text": text.strip(),
"time": datetime.now().strftime("%I:%M:%S %p"),
}
_notes.append(entry)
_broadcast(get_notes_snapshot())
return f'Written to notepad: "{text.strip()}"'
def read_notepad() -> str:
if not _notes:
return "The notepad is empty."
lines = [f"{n['time']} β€” {n['text']}" for n in _notes]
return "Current notes:\n" + "\n".join(lines)
def clear_notepad() -> str:
_notes.clear()
_broadcast(get_notes_snapshot())
return "Notepad cleared."
def get_datetime() -> str:
return datetime.now().strftime("%A, %B %d %Y β€” %I:%M %p")
# ── Clinical tools ────────────────────────────────────────────────────────────
async def get_blood_report_summary() -> str:
report = reports.get_current_report()
if not report.get("has_report"):
return (
"No blood test report has been uploaded yet. Ask the user to upload their "
"blood test report (PDF) using the Blood Test Report uploader."
)
return report["summary"]
async def search_supplements(query: str) -> str:
return await _search_supplements(query)
async def search_blood_knowledge(query: str) -> str:
"""Search the locally indexed blood test documents."""
return await blood_rag.search(query)
async def run_tool(name: str, args: dict) -> str:
if name == "write_to_notepad":
return write_to_notepad(args.get("text", ""))
if name == "read_notepad":
return read_notepad()
if name == "clear_notepad":
return clear_notepad()
if name == "get_datetime":
return get_datetime()
if name == "get_blood_report_summary":
return await get_blood_report_summary()
if name == "search_supplements":
return await search_supplements(args.get("query", ""))
if name == "search_blood_knowledge":
return await search_blood_knowledge(args.get("query", ""))
return f"Unknown tool: {name}"
# ── OpenAI tool schemas ────────────────────────────────────────────────────────
TOOLS = [
{
"type": "function",
"function": {
"name": "write_to_notepad",
"description": (
"Write a note to the live notepad. Use this whenever the user says "
"'note that', 'write down', 'remember', 'save this', 'keep track of', "
"or asks you to record anything."
),
"parameters": {
"type": "object",
"properties": {
"text": {
"type": "string",
"description": (
"The note text. Be concise β€” capture the key information "
"in plain language, no bullet points or markdown."
),
}
},
"required": ["text"],
},
},
},
{
"type": "function",
"function": {
"name": "read_notepad",
"description": (
"Read all notes currently on the notepad. Use when the user asks "
"'what did I note', 'read my notes', or 'what have you written down'."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "clear_notepad",
"description": "Erase all notes from the notepad. Use only when the user explicitly asks to clear or delete all notes.",
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_datetime",
"description": "Get the current date and time.",
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "get_blood_report_summary",
"description": (
"Get a summary of the user's most recently uploaded blood test report, "
"including which markers are low, high, or normal. Call this first "
"whenever the user asks about their blood test, lab results, deficiencies, "
"or what supplements they should take."
),
"parameters": {"type": "object", "properties": {}, "required": []},
},
},
{
"type": "function",
"function": {
"name": "search_blood_knowledge",
"description": (
"Search the locally indexed blood test RAG for relevant passages about "
"a patient's blood test results, markers, deficiencies, or lab values. "
"Use this when the user asks about their blood work, specific markers, "
"or what their results mean."
),
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The question or marker to search for, e.g. 'iron deficiency anemia' or 'vitamin D levels'.",
}
},
"required": ["query"],
},
},
},
{
"type": "function",
"function": {
"name": "search_supplements",
"description": (
"Search the supplement knowledge base for recommendations related to a "
"specific marker or deficiency (e.g. 'low vitamin D', 'low iron / "
"ferritin'). Call this once per abnormal marker found in the user's blood "
"report before recommending supplements."
),
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The marker or deficiency to look up, e.g. 'low vitamin D' or 'high triglycerides'.",
}
},
"required": ["query"],
},
},
},
]