60 lines
3.4 KiB
Python
60 lines
3.4 KiB
Python
import os
|
||
from langchain.agents import create_agent
|
||
from langchain_openai import ChatOpenAI
|
||
from langgraph.checkpoint.memory import InMemorySaver
|
||
from langchain_community.vectorstores import Clickhouse, ClickhouseSettings
|
||
from langchain_community.embeddings import DeepInfraEmbeddings
|
||
from redis import Redis
|
||
from redis.asyncio import Redis as AsyncRedis
|
||
|
||
SYSTEM_PROMPT = """
|
||
Ты — карьерный копилот для ИТ.
|
||
Требования к ответам:
|
||
- Пиши кратко (до 5–6 строк, буллеты приветствуются).
|
||
- Всегда проверяй факты: бери данные о вакансиях только из контекста.
|
||
- В ответ всегда давай источники (минимум 1, лучше 2–3): ссылка на публичный канал или сообщение в телеграмме.
|
||
- Если явно нет ссылки на сообщение о вакансии из telegram, собери ее из доступных chat_id и message_id.
|
||
- Вакансии можно брать только из контекста. Не давай вакансию, если у тебя нет о ней информации в контексте.
|
||
- Всегда указывай дату вакансии и ссылку на нее.
|
||
- Если данных недостаточно: честно скажи «не хватает надёжных источников», предложи расширить период/переформулировать, либо выполнить веб-поиск.
|
||
- После полезного ответа предложи один мягкий следующий шаг.
|
||
Отвечай простым текстом, не используй форматирование markdown.
|
||
Если в контексте ты получил вакансию с форматированием markdown, то убери это форматирование.
|
||
Не ищи вакансии, если этого явно не требуется в запросе пользователя.
|
||
"""
|
||
|
||
redis = Redis(host=os.getenv("REDIS_HOST", "127.0.0.1"))
|
||
async_redis = AsyncRedis(host=os.getenv("REDIS_HOST", "127.0.0.1"))
|
||
llm = ChatOpenAI(model_name="gpt-5-mini", reasoning_effort="minimal")
|
||
embedding = DeepInfraEmbeddings(model_id="Qwen/Qwen3-Embedding-8B")
|
||
vectorstore = Clickhouse(embedding, ClickhouseSettings(
|
||
host=os.getenv("CLICKHOUSE_HOST", "127.0.0.1"),
|
||
port=8123,
|
||
username="default",
|
||
password="",
|
||
index_type="vector_similarity",
|
||
))
|
||
|
||
|
||
def get_relevant_vacancies(requirements: str):
|
||
"""Получает релевантные вакансии из базы данных по переданным требованиям."""
|
||
formatted_vacancies = ""
|
||
for document in vectorstore.similarity_search(requirements, k=5):
|
||
metadata = document.metadata
|
||
formatted_vacancies += f"chat_id = {metadata['chat_id']}\ntelegram_id = {metadata['telegram_id']}\n{document.page_content}"
|
||
return formatted_vacancies
|
||
|
||
|
||
def get_user_resume(user_id: int):
|
||
"""Получает резюме пользователя для подбора вакансий."""
|
||
resume_bytes = redis.get(user_id)
|
||
return resume_bytes.decode("utf-8") if resume_bytes else ""
|
||
|
||
|
||
agent = create_agent(
|
||
model=llm,
|
||
tools=[get_relevant_vacancies, get_user_resume],
|
||
system_prompt=SYSTEM_PROMPT,
|
||
checkpointer=InMemorySaver(),
|
||
)
|