56 lines
2.2 KiB
Python
56 lines
2.2 KiB
Python
"""Tool definitions for the FAQ bot.
|
||
|
||
The module defines two tools:
|
||
1. `search_course_docs` – a semantic search over the local Chroma FAQ store.
|
||
2. `fetch_course_meta` – a simple HTTP GET to a local JSON file that mimics an MCP
|
||
metadata service.
|
||
|
||
Both tools are decorated with `@tool` so that LangChain can expose them to the
|
||
agent.
|
||
"""
|
||
|
||
import json
|
||
import os
|
||
from pathlib import Path
|
||
from typing import Any
|
||
|
||
import httpx
|
||
from langchain.tools import tool
|
||
|
||
from config import COURSE_META_JSON
|
||
from vector_store import search_course_docs
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 1. Semantic search tool
|
||
# ---------------------------------------------------------------------------
|
||
@tool("search_course_docs", "Search local FAQ documents.")
|
||
async def search_course_docs_tool(query: str, k: int = 3) -> str:
|
||
"""Return top‑k relevant FAQ snippets for *query*.
|
||
|
||
The function is asynchronous to match the signature expected by LangChain
|
||
agents. It simply forwards the call to the synchronous helper in
|
||
``vector_store``.
|
||
"""
|
||
return search_course_docs(query, k)
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 2. Metadata fetch tool – MCP‑style
|
||
# ---------------------------------------------------------------------------
|
||
@tool("fetch_course_meta", "Get course metadata from a local JSON file.")
|
||
async def fetch_course_meta_tool(query: str) -> str:
|
||
"""Return JSON string of metadata matching *query*.
|
||
|
||
The function reads a static JSON file. In a real deployment this would be a
|
||
HTTP request to an MCP server. For the purposes of the assignment we keep
|
||
it simple and local.
|
||
"""
|
||
if not Path(COURSE_META_JSON).exists():
|
||
return f"Metadata file {COURSE_META_JSON} not found."
|
||
data = json.loads(Path(COURSE_META_JSON).read_text(encoding="utf-8"))
|
||
# Very naive lookup: return the whole file if query is empty or substring
|
||
if not query or query.lower() in json.dumps(data).lower():
|
||
return json.dumps(data, indent=2)
|
||
return f"No metadata found for query: {query}."
|
||
|
||
# Expose the tools for external imports
|
||
__all__ = ["search_course_docs_tool", "fetch_course_meta_tool"] |