"""FAQ‑бот: ChromaDB для конспектов + MCP‑style tool для метаданных курса.""" import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage from langchain.agents import create_agent load_dotenv() from tools import search_course_docs, fetch_course_meta # noqa: E402 llm = ChatOpenAI( model="openai/gpt-oss-20b:free", base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1", api_key=os.getenv("JOURNAL_MCP_PAT"), temperature=0.0, ) SYSTEM_PROMPT = """Ты — FAQ‑бот курса KFU-26-1 по LangChain/LangGraph. Доступные инструменты: 1. search_course_docs — поиск по конспектам курса в ChromaDB (Ollama embeddings) Используй для вопросов о технологиях: LangChain, LangGraph, MCP, агентах, коде 2. fetch_course_meta — метаданные курса через MCP‑style tool (расписание, дедлайны, контакты, глоссарий) Используй для вопросов о расписании, сроках, контактах преподавателя Правила маршрутизации: - Вопрос про содержание, технологии, концепции → search_course_docs [source: chroma] - Вопрос про расписание, дедлайны, контакты, термины → fetch_course_meta [source: mcp_meta] - Не вызывай оба инструмента без необходимости — выбери один подходящий В каждом ответе укажи источник: [source: chroma] или [source: mcp_meta]""" agent = create_agent( llm=llm, tools=[search_course_docs, fetch_course_meta], system_prompt=SYSTEM_PROMPT, ) async def ask(question: str, thread_id: str = "faq-1") -> str: """Задать вопрос агенту и получить ответ.""" result = await agent.ainvoke( {"messages": [HumanMessage(content=question)]}, {"configurable": {"thread_id": thread_id}}, ) return result["messages"][-1].content