from typing import Optional from bielik import llm from state import ChatState, Message from pydantic_restrictions import Summary, introductionChapter, UnderstandDistortionClassifier, ThoughtChecker from neo4j_driver import driver def introduction_talk(chat_history, systemPrompt): if chat_history is None: chat_history = [] else: chat_history = [msg for msg in chat_history if msg.get("role") != "system"] chat_history.insert(0, {"role": "system", "content": systemPrompt}) talk_llm = llm.with_structured_output(introductionChapter) result = talk_llm.invoke(chat_history) return result def check_situation(message): classifier_llm = llm.with_structured_output(UnderstandDistortionClassifier) result = classifier_llm.invoke([ { "role": "system", "content": """Sklasyfikuj input użytkownika: - 'understand': Jeśli jego wiadomość świadczy o tym, że rozumie on o czym mówimy i nie ma pytań co do tego - 'no understand': Jeśli jego wiadomość świadczy o tym, że nie rozumie on tego zniekształcenia albo chce więcej informacji o nim, bądź prosi o dokładniejsze wytłumaczenie. - 'low expression': jeśli jego wiadomość jest mało wylewna i użytkownik nie przedstawił ani chęci działania ani prośby o wytłumaczenie """ }, {"role": "user", "content": message} ]) return result.message_type def create_interview(message, old_data): summarizer_llm = llm.with_structured_output(Summary) result = summarizer_llm.invoke([ { "role": "system", "content": f""" [ROLA] Jesteś modułem SCALAJĄCYM. Twoim jedynym zadaniem jest stworzyć JEDEN krótki opis, który łączy wcześniejszy tekst (PREV) z nowym tekstem (NEW). [WEJŚCIE] PREV: {old_data if old_data else ""} NEW: {message if message else ""} [ZASADY] - Jeśli PREV jest puste → zwróć tylko NEW. - Jeśli NEW jest puste → zwróć tylko PREV. - Jeśli oba są → połącz w logiczną całość. - Usuń powtórzenia (także oczywiste parafrazy). - ZERO halucynacji: nie dodawaj nic spoza PREV/NEW. - Styl: bardzo prosty, neutralny. - Długość: maksymalnie 1–2 krótkie zdania. - Język: polski. - Zwróć wyłącznie JSON ze podanym schematem """ } ]) return result def getQuestions(intent): query = """ MATCH (q:Question)<-[:HAS_EXAMPLE_QUESTION]-(i:Intent {name:$intencja}) RETURN q.content AS nazwa ORDER BY nazwa; """ records, _, _ = driver.execute_query( query, parameters_={"intencja": intent}, ) result = [] for record in records: result.append(record["nazwa"]) return result def get_last_user_message(state: ChatState) -> Optional[Message]: for m in reversed(state.get("messages", [])): if m.get("role") == "user": return m return None def beliefs_check_function(message): beliefs_llm = llm.with_structured_output(ThoughtChecker) result = beliefs_llm.invoke([ { "role": "system", "content": """Twoje zadanie: oceń, czy wypowiedź zawiera MYŚL lub PRZEKONANIE, czyli subiektywną interpretację, ocenę lub wniosek o sobie, innych lub świecie. Jeśli to jedynie OPIS SYTUACJI lub EMOCJI, zwróć False. Definicje: - MYŚL/PRZEKONANIE → interpretacja, ocena, wniosek, uogólnienie lub przewidywanie (np. 'Na pewno mnie nie lubią', 'Zawsze wszystko psuję'). - SYTUACJA → fakt, kontekst, zdarzenie (np. 'Rozmawiałem z szefem', 'Byłem w pracy'). - EMOCJA → stan uczuciowy, bez oceny poznawczej (np. 'Czuję złość', 'Jest mi smutno', 'Boje się'). Zasada: Jeśli brak interpretacji, zwróć False, nawet jeśli pojawia się emocja. Zwróć wyłącznie JSON zgodny z modelem: {'decision_beliefs': true/false}.""" }, {"role": "user", "content": message} ]) return result.decision_beliefs