Syncing local state to remote: update src/agent.py
This commit is contained in:
+50
-50
@@ -1,57 +1,57 @@
|
|||||||
import os
|
import argparse
|
||||||
from typing import Dict, Any
|
from langchain.agents import create_openai_functions_agent, AgentExecutor
|
||||||
from langchain_ollama import OllamaLLM
|
from langchain_core.prompts import ChatPromptTemplate
|
||||||
from langchain.agents import initialize_agent, Tool, AgentType
|
from langchain_core.messages import HumanMessage
|
||||||
from langchain.memory import ConversationBufferMemory
|
from langchain_ollama import Ollama
|
||||||
from src.utils import search_course_docs, fetch_course_meta
|
from src.utils import load_faq_to_chroma, search_course_docs, fetch_course_meta
|
||||||
|
|
||||||
|
# Initialize embeddings and LLM
|
||||||
|
llm = Ollama(model="llama3.1")
|
||||||
|
|
||||||
|
# Load or create Chroma collection
|
||||||
|
try:
|
||||||
|
chroma = load_faq_to_chroma()
|
||||||
|
except Exception:
|
||||||
|
chroma = None
|
||||||
|
|
||||||
# Define tools
|
# Define tools
|
||||||
search_tool = Tool(
|
from langchain.tools import tool
|
||||||
name="search_course_docs",
|
|
||||||
func=search_course_docs,
|
|
||||||
description="Search local FAQ docs in ChromaDB. Use when question about course content. Returns list of relevant documents."
|
|
||||||
)
|
|
||||||
meta_tool = Tool(
|
|
||||||
name="fetch_course_meta",
|
|
||||||
func=fetch_course_meta,
|
|
||||||
description="Fetch course metadata (schedule, exams) from MCP-style tool. Use when question about schedule or metadata. Returns list of matching items."
|
|
||||||
)
|
|
||||||
|
|
||||||
# System prompt to guide routing
|
@tool
|
||||||
SYSTEM_PROMPT = (
|
def search_course_docs_tool(query: str, k: int = 3) -> str:
|
||||||
"You are an FAQ bot for the course. Use search_course_docs for content questions and fetch_course_meta for schedule or metadata questions.\n"
|
"""Search local FAQ docs in ChromaDB."""
|
||||||
"When answering, include a field 'source' with value 'chroma' or 'mcp_meta' to indicate which tool was used."
|
docs = search_course_docs(query, k)
|
||||||
)
|
return "\n".join([doc.page_content for doc in docs])
|
||||||
|
|
||||||
# LLM and agent setup
|
@tool
|
||||||
llm = OllamaLLM(model="llama3")
|
def fetch_course_meta_tool(query: str) -> str:
|
||||||
memory = ConversationBufferMemory(memory_key="chat_history")
|
"""Fetch course metadata via MCP-style tool."""
|
||||||
agent = initialize_agent(
|
results = fetch_course_meta(query)
|
||||||
tools=[search_tool, meta_tool],
|
return str(results)
|
||||||
llm=llm,
|
|
||||||
agent=AgentType.CHAT_ZERO_SHOT_REACT_DESCRIPTION,
|
|
||||||
memory=memory,
|
|
||||||
verbose=True,
|
|
||||||
system_prompt=SYSTEM_PROMPT,
|
|
||||||
)
|
|
||||||
|
|
||||||
def ask(question: str) -> Dict[str, Any]:
|
tools = [search_course_docs_tool, fetch_course_meta_tool]
|
||||||
response = agent.run(question)
|
|
||||||
# Parse response to extract source if present
|
# Prompt template with source hint
|
||||||
source = "unknown"
|
prompt = ChatPromptTemplate.from_messages([
|
||||||
if "source:" in response.lower():
|
("system", "You are a helpful FAQ assistant. Use the tools only when necessary. In your answer, include a line like 'source: chroma' or 'source: mcp_meta' to indicate which tool was used.")
|
||||||
parts = response.lower().split("source:")
|
])
|
||||||
source = parts[1].strip().split()[0]
|
|
||||||
return {"answer": response, "source": source}
|
agent = create_openai_functions_agent(llm=llm, tools=tools, prompt=prompt)
|
||||||
|
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# Simple CLI with 3 preset questions
|
parser = argparse.ArgumentParser(description="FAQ bot CLI")
|
||||||
questions = [
|
parser.add_argument("--question", type=str, help="Question to ask the bot")
|
||||||
"Как подключить ChromaDB?",
|
args = parser.parse_args()
|
||||||
"Что такое MCP‑tool?",
|
if args.question:
|
||||||
"Когда проходят экзамены?"
|
response = executor.invoke({"input": args.question})
|
||||||
]
|
print(response["output"])
|
||||||
for q in questions:
|
else:
|
||||||
print("Q:", q)
|
# Interactive mode
|
||||||
print("A:", ask(q)["answer"], "(source:", ask(q)["source"], ")")
|
print("FAQ Bot. Type 'exit' to quit.")
|
||||||
print()
|
while True:
|
||||||
|
q = input("> ")
|
||||||
|
if q.lower() in ("exit", "quit"):
|
||||||
|
break
|
||||||
|
resp = executor.invoke({"input": q})
|
||||||
|
print(resp["output"])
|
||||||
|
|||||||
Reference in New Issue
Block a user