From 458691a95c0c098702df290201b31c084f15fc34 Mon Sep 17 00:00:00 2001 From: Egor Fedorov Date: Tue, 9 Sep 2025 21:24:54 +0300 Subject: [PATCH 1/5] fix(backend): use async operations --- backend/app/services/pdf_parser.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/app/services/pdf_parser.py b/backend/app/services/pdf_parser.py index 27f9250..7a1ab30 100644 --- a/backend/app/services/pdf_parser.py +++ b/backend/app/services/pdf_parser.py @@ -158,7 +158,7 @@ async def parse_cv( # Generate JSON schema for precise parsing json_schema = self._get_cv_json_schema() - result = self.gigachat_client.chat( + result = await self.gigachat_client.achat( { "messages": [ { @@ -339,7 +339,7 @@ async def parse_vacancy( # Generate JSON schema for precise parsing json_schema = self._get_vacancy_json_schema() - result = self.gigachat_client.chat( + result = await self.gigachat_client.achat( { "messages": [ { @@ -472,7 +472,7 @@ async def analyze_cv_with_gigachat(self, file_id: str, question: str) -> str: PDFParsingError: If analysis fails """ try: - result = self.gigachat_client.chat( + result = await self.gigachat_client.achat( { "function_call": "auto", "messages": [ @@ -502,7 +502,7 @@ async def analyze_vacancy_with_gigachat(self, file_id: str, question: str) -> st PDFParsingError: If analysis fails """ try: - result = self.gigachat_client.chat( + result = await self.gigachat_client.achat( { "function_call": "auto", "messages": [ From 71ad6a1bb20872d1a787ff2e1f5e959257485a9f Mon Sep 17 00:00:00 2001 From: Egor Fedorov Date: Tue, 9 Sep 2025 21:36:46 +0300 Subject: [PATCH 2/5] remove interview --- backend/app/api/routers/ws.py | 32 +--------------------- frontend/src/hooks/use-webcam-streaming.ts | 11 -------- 2 files changed, 1 insertion(+), 42 deletions(-) diff --git a/backend/app/api/routers/ws.py b/backend/app/api/routers/ws.py index f9f5519..f659b54 100644 --- a/backend/app/api/routers/ws.py +++ b/backend/app/api/routers/ws.py @@ -137,7 +137,7 @@ def cut_fragment_video(self, path: str, start_ms: int, end_ms: int) -> bool: def extract_audio_from_video(self, video_path: str) -> str | None: """Extract audio from video file and save as WAV with same base filename.""" - # Generate audio file path with .wav extension + # Generate audio file path with .wav extensionu audio_path = video_path.replace(".webm", ".wav") logger.debug("Extracting audio from %s to %s", video_path, audio_path) @@ -439,36 +439,6 @@ async def websocket_video_stream( if text_data == "audio-ready": await service.handle_audio_marker() continue - if text_data is not None: - # Treat any other text frame as a direct user answer (debug mode support) - logger.info( - "Received direct text on WS for interview %s: %s", - interview_id, - text_data[:200], - ) - await service.update_state(InterviewSocketState.GENERATING_RESPONSE) - latest_message = await service.submit_user_answer( - interview_id, text_data.strip() - ) - if latest_message is None: - logger.warning( - "Failed to submit direct text for interview %s", - interview_id, - ) - else: - logger.info( - "Direct text submitted successfully for interview %s", - interview_id, - ) - if settings.use_yandex_speech_synthesis: - await service.update_state( - InterviewSocketState.SPEECH_SYNTHESIS - ) - await service.send_message_to_user(latest_message) - await service.update_state( - InterviewSocketState.AWAITING_USER_ANSWER - ) - continue if data_bytes and len(data_bytes) > 0: service.add_video_chunk(data_bytes) diff --git a/frontend/src/hooks/use-webcam-streaming.ts b/frontend/src/hooks/use-webcam-streaming.ts index a6ea08c..ec2fac7 100644 --- a/frontend/src/hooks/use-webcam-streaming.ts +++ b/frontend/src/hooks/use-webcam-streaming.ts @@ -212,16 +212,6 @@ export function useWebcamStreaming( setSocketState("speech_recognition"); } - /** - * Отправка текстового сообщения напрямую по WebSocket (dev/debug режим) - */ - function sendTextMessage(text: string) { - if (!text) return; - console.log("Sending text message over WS:", text); - sendMessage(text); - setSocketState("generating_response"); - } - function startRecording() { console.log("Attempting to start recording..."); setIsRecording(true); @@ -258,7 +248,6 @@ export function useWebcamStreaming( startRecording, handleStopRecording, sendAudioReadyMarker, - sendTextMessage, socketState, }; } From d2fef95eec09dfd23a3234064d4a43b0c4a06daf Mon Sep 17 00:00:00 2001 From: Egor Fedorov Date: Tue, 9 Sep 2025 21:40:03 +0300 Subject: [PATCH 3/5] fix ws --- frontend/nginx.conf | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/frontend/nginx.conf b/frontend/nginx.conf index 6c25588..99ab337 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -74,6 +74,23 @@ http { } } + # WebSocket proxy for /ws/ endpoints + location /ws/ { + proxy_pass http://backend:8000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + # WebSocket specific timeouts + proxy_read_timeout 86400; + proxy_send_timeout 86400; + proxy_connect_timeout 60; + } + # Proxy regular API requests to backend location /api/ { proxy_pass http://backend:8000/; From 9f31c0056c57bbb6cbeab480d692623a5f1cf16d Mon Sep 17 00:00:00 2001 From: Egor Fedorov Date: Tue, 9 Sep 2025 21:41:22 +0300 Subject: [PATCH 4/5] fix message --- frontend/src/components/interviews/interview-chat.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/frontend/src/components/interviews/interview-chat.tsx b/frontend/src/components/interviews/interview-chat.tsx index 7e5e80a..be2c216 100644 --- a/frontend/src/components/interviews/interview-chat.tsx +++ b/frontend/src/components/interviews/interview-chat.tsx @@ -32,7 +32,7 @@ export function InterviewChat({ interviewId }: Props) { refetchInterval: 1000, }); const isFinished = interview.data.state === "done"; - const { webcamRef, sendAudioReadyMarker, socketState, sendTextMessage } = + const { webcamRef, sendAudioReadyMarker, socketState } = useWebcamStreaming(interviewId, { disabled: isFinished, }); @@ -170,7 +170,6 @@ export function InterviewChat({ interviewId }: Props) { e.key === "Enter" && debugPrompt.trim().length > 0 ) { - sendTextMessage(debugPrompt.trim()); setDebugPrompt(""); } }} @@ -178,7 +177,6 @@ export function InterviewChat({ interviewId }: Props) {