50 lines
3.3 KiB
Python
50 lines
3.3 KiB
Python
from langchain.agents import create_agent
|
||
from langchain_openai import ChatOpenAI
|
||
from langgraph.checkpoint.memory import InMemorySaver
|
||
from langchain_community.tools import DuckDuckGoSearchRun
|
||
from langchain_community.vectorstores import Clickhouse, ClickhouseSettings
|
||
from langchain_community.embeddings import DeepInfraEmbeddings
|
||
from datetime import datetime
|
||
from redis.asyncio import Redis
|
||
|
||
SYSTEM_PROMPT = f"""
|
||
Сегодня {datetime.today().isoformat()}.
|
||
Ты — карьерный копилот для ИТ.
|
||
Ответ всегда должен быть, не допускай пустых ответов.
|
||
Требования к ответам:
|
||
- Пиши кратко (до 5–6 строк, буллеты приветствуются).
|
||
- Всегда проверяй факты: бери данные о вакансиях только из контекста и ссылок в web-поиске.
|
||
- В ответ всегда давай источники (минимум 1, лучше 2–3): ссылка на публичный
|
||
- Вакансии можно брать только из контекста, либо обращаться к web-поиску.
|
||
- Всегда указывай дату вакансии и ссылку на нее.
|
||
- Если вакансия из контекста, то сформируй ссылку на telegram-сообщение, где была указана эта вакансия.
|
||
пост/новость/страницу компании. Без «уверенностей».
|
||
- Персональные/идентифицирующие данные из непубличных источников не
|
||
раскрывай. Если цитируешь, то только из публичных каналов/страниц с ссылкой.
|
||
- Если данных недостаточно: честно скажи «не хватает надёжных источников»,
|
||
предложи расширить период/переформулировать, либо выполнить веб-поиск.
|
||
- После полезного ответа предложи один мягкий следующий шаг.
|
||
Отвечай простым текстом. Не используй HTML, Markdown, звёздочки, подчёркивания. Просто текст, но используй emoji.
|
||
"""
|
||
|
||
redis = Redis()
|
||
llm = ChatOpenAI(model_name="zai-org/GLM-4.6", openai_api_base="https://api.deepinfra.com/v1/openai")
|
||
embedding = DeepInfraEmbeddings(model_id="Qwen/Qwen3-Embedding-8B")
|
||
vectorstore = Clickhouse(embedding, ClickhouseSettings(port=8123, username="default", password="", index_type="vector_similarity"))
|
||
search_tool = DuckDuckGoSearchRun()
|
||
|
||
async def get_relevant_vacancies(requirements: str):
|
||
"""Получает релевантные вакансии из базы данных по переданным требованиям."""
|
||
return await vectorstore.asimilarity_search(requirements, k=10)
|
||
|
||
async def get_user_resume(user_id: int):
|
||
"""Получает резюме пользователя для подбора вакансий."""
|
||
return await redis.get(user_id)
|
||
|
||
agent = create_agent(
|
||
model=llm,
|
||
tools=[search_tool, get_relevant_vacancies, get_user_resume],
|
||
system_prompt=SYSTEM_PROMPT,
|
||
checkpointer=InMemorySaver(),
|
||
)
|