From 07907986e0488bf6d5c6e8dfcf42d6e916ee98a0 Mon Sep 17 00:00:00 2001 From: "Kenneth C. Arnold" Date: Fri, 13 Jun 2025 11:39:43 -0400 Subject: [PATCH 1/5] fail if we're rendering the study page when study condition is null --- frontend/src/pages/study/index.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/frontend/src/pages/study/index.tsx b/frontend/src/pages/study/index.tsx index b38a0739..4448aa1d 100644 --- a/frontend/src/pages/study/index.tsx +++ b/frontend/src/pages/study/index.tsx @@ -273,6 +273,14 @@ export default function Draft() { ); } + if (studyCondition === null) { + return ( +
+ Study condition is not set. Please check your setup. +
+ ); + } + let results = null; if (errorMsg !== '') From 4d353c61a9e9834d2afb5f8675b801e497261ce2 Mon Sep 17 00:00:00 2001 From: "Kenneth C. Arnold" Date: Fri, 13 Jun 2025 11:50:00 -0400 Subject: [PATCH 2/5] Clarify logging: update API calls to remove "_Backend" suffix and separately log the generation type --- backend/server.py | 21 +++++++++++++-------- backend/test_generation.sh | 2 +- frontend/src/pages/draft/index.tsx | 9 ++++++--- frontend/src/pages/study/index.tsx | 9 ++++++--- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/backend/server.py b/backend/server.py index 24cc2ebf..95a1334d 100644 --- a/backend/server.py +++ b/backend/server.py @@ -2,7 +2,7 @@ import os import json -from typing import List, Dict, Optional, Annotated +from typing import List, Dict, Optional, Annotated, Literal from pathlib import Path from datetime import datetime @@ -89,6 +89,7 @@ class Log(BaseModel): class GenerationLog(Log): + generation_type: Literal["Completion", "Question", "Keywords", "Structure", "RMove"] prompt: str result: str completion: Optional[str] = None @@ -119,19 +120,22 @@ async def generation(payload: GenerationRequestPayload, background_tasks: Backgr ''' To test this endpoint from curl: - $ curl -X POST -H "Content-Type: application/json" -d '{"username": "test", "gtype": "Completion_Backend", "prompt": "This is a test prompt."}' http://localhost:8000/api/generation + $ curl -X POST -H "Content-Type: application/json" -d '{"username": "test", "gtype": "Completion", "prompt": "This is a test prompt."}' http://localhost:8000/api/generation ''' + # Sometimes gtype will have a _Backend suffix, so we strip it out + payload.gtype = payload.gtype.replace("_Backend", "") + start_time = datetime.now() - if payload.gtype == "Completion_Backend": + if payload.gtype == "Completion": result = await nlp.chat_completion(payload.prompt) - elif payload.gtype == "Question_Backend": + elif payload.gtype == "Question": result = await nlp.question(payload.prompt) - elif payload.gtype == "Keywords_Backend": + elif payload.gtype == "Keywords": result = await nlp.keywords(payload.prompt) - elif payload.gtype == "Structure_Backend": + elif payload.gtype == "Structure": result = await nlp.structure(payload.prompt) - elif payload.gtype == "RMove_Backend": + elif payload.gtype == "RMove": result = await nlp.rmove(payload.prompt) else: raise ValueError(f"Invalid generation type: {payload.gtype}") @@ -140,7 +144,8 @@ async def generation(payload: GenerationRequestPayload, background_tasks: Backgr log_entry = GenerationLog( timestamp=end_time.timestamp(), username=payload.username, - interaction=payload.gtype, + interaction="suggestion_generated", + generation_type=payload.gtype, prompt=payload.prompt if LOG_DOCTEXT else "", result=result.result if LOG_DOCTEXT else "", delay=(end_time - start_time).total_seconds(), diff --git a/backend/test_generation.sh b/backend/test_generation.sh index b4921003..1dc28814 100644 --- a/backend/test_generation.sh +++ b/backend/test_generation.sh @@ -1,2 +1,2 @@ #!/bin/bash -curl -X POST -H "Content-Type: application/json" -d '{"username": "test", "gtype": "Completion_Backend", "prompt": "This is a test prompt."}' https://textfocals.com/api/generation +curl -X POST -H "Content-Type: application/json" -d '{"username": "test", "gtype": "Completion", "prompt": "This is a test prompt."}' https://textfocals.com/api/generation diff --git a/frontend/src/pages/draft/index.tsx b/frontend/src/pages/draft/index.tsx index b851ee71..ecb079eb 100644 --- a/frontend/src/pages/draft/index.tsx +++ b/frontend/src/pages/draft/index.tsx @@ -215,7 +215,8 @@ export default function Draft() { updateGeneration(null); log({ username: username, - interaction: type, + interaction: "error", + generation_type: type, prompt: contextText, result: errMsg }); @@ -358,14 +359,16 @@ export default function Draft() { onClick={ async () => { log({ username: username, - interaction: `${mode}_Frontend`, + interaction: "request_suggestion", + // eslint-disable-next-line camelcase + generation_type: mode, prompt: beforeContext }); if (beforeContext === '') return; getGeneration( username, - `${mode}_Backend`, + mode, beforeContext ); } } diff --git a/frontend/src/pages/study/index.tsx b/frontend/src/pages/study/index.tsx index 4448aa1d..3d5c96e0 100644 --- a/frontend/src/pages/study/index.tsx +++ b/frontend/src/pages/study/index.tsx @@ -218,7 +218,8 @@ export default function Draft() { updateGeneration(null); log({ username: username, - interaction: type, + interaction: "error", + generation_type: type, prompt: contextText, result: errMsg }); @@ -366,11 +367,13 @@ export default function Draft() { onClick={ async () => { log({ username: username, - interaction: `${studyCondition}_Frontend`, + interaction: "request_suggestion", + // eslint-disable-next-line camelcase + generation_type: studyCondition, prompt: beforeContext }); if (beforeContext === '') return; - getGeneration(username, `${studyCondition}_Backend`, beforeContext); + getGeneration(username, studyCondition, beforeContext); } } > { iconFunc(studyCondition as keyof typeof visibleNameForMode) } From 34e4632e667df430c0a975d888be152b74c91e1c Mon Sep 17 00:00:00 2001 From: "Kenneth C. Arnold" Date: Fri, 13 Jun 2025 11:50:49 -0400 Subject: [PATCH 3/5] only initialize the logger once. --- backend/server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/backend/server.py b/backend/server.py index 95a1334d..b8656aae 100644 --- a/backend/server.py +++ b/backend/server.py @@ -22,6 +22,10 @@ import nlp import logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + # Load ENV vars load_dotenv() @@ -157,9 +161,6 @@ async def generation(payload: GenerationRequestPayload, background_tasks: Backgr setattr(log_entry, key, value) background_tasks.add_task(make_log, log_entry) - logging.basicConfig(level=logging.INFO) - logger = logging.getLogger(__name__) - final_end_time = datetime.now() log = final_end_time - start_time logger.info(f"Total generation request operation took: {log.total_seconds()} seconds") From 99a8082376b248da725fc2b632052500ab96c601 Mon Sep 17 00:00:00 2001 From: "Kenneth C. Arnold" Date: Fri, 13 Jun 2025 11:56:15 -0400 Subject: [PATCH 4/5] Rename "interaction" to "event" in logs, and clarify some of these event names. --- backend/server.py | 8 ++++---- frontend/src/api/index.ts | 2 +- frontend/src/logs/index.tsx | 4 ++-- frontend/src/pages/draft/index.tsx | 6 +++--- frontend/src/pages/study/index.tsx | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/backend/server.py b/backend/server.py index b8656aae..be5c8bb3 100644 --- a/backend/server.py +++ b/backend/server.py @@ -89,7 +89,7 @@ class Log(BaseModel): timestamp: float ok: bool = True username: ValidatedUsername - interaction: str + event: str class GenerationLog(Log): @@ -148,7 +148,7 @@ async def generation(payload: GenerationRequestPayload, background_tasks: Backgr log_entry = GenerationLog( timestamp=end_time.timestamp(), username=payload.username, - interaction="suggestion_generated", + event="suggestion_generated", generation_type=payload.gtype, prompt=payload.prompt if LOG_DOCTEXT else "", result=result.result if LOG_DOCTEXT else "", @@ -176,7 +176,7 @@ async def reflections(payload: ReflectionRequestPayload, background_tasks: Backg log_entry = ReflectionLog( username=payload.username, - interaction="reflection", + event="reflection_generated", prompt=payload.prompt if LOG_DOCTEXT else "", paragraph=payload.paragraph if LOG_DOCTEXT else "", timestamp=end_time.timestamp(), @@ -202,7 +202,7 @@ async def chat(payload: ChatRequestPayload): # } for message in payload.messages] # make_log( # Log(username=payload.username, - # interaction="chat", + # event="chat_message", # prompt=payload.messages[-1]['content'], # ui_id=None) # ) diff --git a/frontend/src/api/index.ts b/frontend/src/api/index.ts index 5b49fc70..c6ff0d46 100644 --- a/frontend/src/api/index.ts +++ b/frontend/src/api/index.ts @@ -3,7 +3,7 @@ export const SERVER_URL = '/api'; // Define a type for payload. Includes at least: eventType and username export interface LogPayload { username: string; - interaction: string; + event: string; [key: string]: any; } diff --git a/frontend/src/logs/index.tsx b/frontend/src/logs/index.tsx index d8cc3986..69e47e6b 100644 --- a/frontend/src/logs/index.tsx +++ b/frontend/src/logs/index.tsx @@ -7,7 +7,7 @@ import classes from './styles.module.css'; interface Log { username: string; - interaction: string; + event: string; prompt: string; result: string; completion: string; @@ -65,7 +65,7 @@ function App() { { groupedLogs[username].map((log: Log) => (
  • -

    Interaction: { log.interaction }

    +

    Event: { log.event }

    Prompt: { log.prompt }

    Result: { log.result }

    Completion: { log.completion }

    diff --git a/frontend/src/pages/draft/index.tsx b/frontend/src/pages/draft/index.tsx index ecb079eb..490df428 100644 --- a/frontend/src/pages/draft/index.tsx +++ b/frontend/src/pages/draft/index.tsx @@ -152,7 +152,7 @@ export default function Draft() { log({ username: username, - interaction: 'Delete', + event: 'Delete', prompt: savedItems[savedItemIdx].document, result: savedItems[savedItemIdx].generation }); @@ -215,7 +215,7 @@ export default function Draft() { updateGeneration(null); log({ username: username, - interaction: "error", + event: "generation_error", generation_type: type, prompt: contextText, result: errMsg @@ -359,7 +359,7 @@ export default function Draft() { onClick={ async () => { log({ username: username, - interaction: "request_suggestion", + event: "request_suggestion", // eslint-disable-next-line camelcase generation_type: mode, prompt: beforeContext diff --git a/frontend/src/pages/study/index.tsx b/frontend/src/pages/study/index.tsx index 3d5c96e0..865e852c 100644 --- a/frontend/src/pages/study/index.tsx +++ b/frontend/src/pages/study/index.tsx @@ -155,7 +155,7 @@ export default function Draft() { log({ username: username, - interaction: 'Delete', + event: 'Delete', prompt: savedItems[savedItemIdx].document, result: savedItems[savedItemIdx].generation }); @@ -218,7 +218,7 @@ export default function Draft() { updateGeneration(null); log({ username: username, - interaction: "error", + event: "generation_error", generation_type: type, prompt: contextText, result: errMsg @@ -367,7 +367,7 @@ export default function Draft() { onClick={ async () => { log({ username: username, - interaction: "request_suggestion", + event: "request_suggestion", // eslint-disable-next-line camelcase generation_type: studyCondition, prompt: beforeContext From c3e0e5076ec95dd0f0b76c1032c04335d816a4df Mon Sep 17 00:00:00 2001 From: "Kenneth C. Arnold" Date: Fri, 13 Jun 2025 11:57:35 -0400 Subject: [PATCH 5/5] appease the linter --- frontend/src/pages/draft/index.tsx | 1 + frontend/src/pages/study/index.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/frontend/src/pages/draft/index.tsx b/frontend/src/pages/draft/index.tsx index 490df428..6f665b98 100644 --- a/frontend/src/pages/draft/index.tsx +++ b/frontend/src/pages/draft/index.tsx @@ -216,6 +216,7 @@ export default function Draft() { log({ username: username, event: "generation_error", + // eslint-disable-next-line camelcase generation_type: type, prompt: contextText, result: errMsg diff --git a/frontend/src/pages/study/index.tsx b/frontend/src/pages/study/index.tsx index 865e852c..799f6f6e 100644 --- a/frontend/src/pages/study/index.tsx +++ b/frontend/src/pages/study/index.tsx @@ -219,6 +219,7 @@ export default function Draft() { log({ username: username, event: "generation_error", + // eslint-disable-next-line camelcase generation_type: type, prompt: contextText, result: errMsg