Skip to content

Commit a1e05d6

Browse files
ngoclam9415claude
andcommitted
Add interview agent settings UI and lifespan initialization
- Initialize default prompt settings at app startup via lifespan handler - Add custom compact Settings UI for interview_agent category with: - Inline number input for max_followups_per_opener - Textarea for user_preference (tone + tacit knowledge focus) - Single "Save Changes" button per category - Rename expert_guidance to user_preference across backend and frontend - Add follow-up counter function for tracking questions since last opener Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d563866 commit a1e05d6

9 files changed

Lines changed: 536 additions & 171 deletions

File tree

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,6 @@ dana_studio/dana/studio/api_backup
101101
.output
102102
knowledge_packs
103103
log/
104-
test.py
104+
test.py
105+
106+
CLAUDE_backup.md

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"request": "launch",
5151
"justMyCode": false,
5252
"module": "dana_studio.dana.studio.__main__",
53-
"args": ["--reload", "--skip-build"],
53+
"args": ["--port", "8080", "--reload", "--skip-build"],
5454
"console": "integratedTerminal",
5555
"env" : {
5656
"DANAPATH" : "${workspaceFolder}"

dana_studio/dana/studio/api/routers/v2/knowledge_pack/kp_interview_session.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,75 @@ def _find_relevant_messages(conversation_messages: list):
567567
return conversation_messages
568568

569569

570+
def _count_followups_since_last_opener(messages: list) -> int:
571+
"""
572+
Count follow-up questions since the last interview_note question.
573+
574+
Iterates backwards through messages to find the last interview_note question,
575+
counting how many followup category questions came after it.
576+
577+
Args:
578+
messages: List of conversation message objects
579+
580+
Returns:
581+
Number of follow-up questions since the last opener
582+
"""
583+
followup_count = 0
584+
585+
for msg in reversed(messages):
586+
if msg.sender == "assistant" and msg.require_user:
587+
question_info = _extract_question_info(msg.content)
588+
if question_info:
589+
category = question_info.get("category", "")
590+
if category == "interview_note":
591+
break # Found the opener, stop counting
592+
elif category == "followup":
593+
followup_count += 1
594+
595+
return followup_count
596+
597+
598+
async def _get_interview_agent_settings(db: Session, applies_to: str = "global") -> dict:
599+
"""
600+
Fetch all interview_agent settings in one query, filtered by applies_to.
601+
602+
Args:
603+
db: Database session
604+
applies_to: Filter settings by applies_to field (default "global")
605+
606+
Returns:
607+
Dict with parsed settings:
608+
{
609+
"max_followups_per_opener": 2,
610+
"user_preference": "..."
611+
}
612+
"""
613+
from dana.studio.api.repositories import get_application_settings_repo
614+
615+
settings_repo = get_application_settings_repo()
616+
all_settings = await settings_repo.get_settings_by_category("interview_agent", db)
617+
618+
# Filter by applies_to and build result dict
619+
result = {}
620+
for setting in all_settings:
621+
# Check applies_to filter (default "global" matches all)
622+
setting_applies_to = setting.applies_to or "global"
623+
if setting_applies_to != applies_to and setting_applies_to != "global":
624+
continue
625+
626+
# Parse value based on key
627+
if setting.key == "max_followups_per_opener":
628+
result["max_followups_per_opener"] = int(setting.value or "2")
629+
elif setting.key == "user_preference":
630+
result["user_preference"] = setting.value or ""
631+
632+
# Set defaults for missing settings
633+
result.setdefault("max_followups_per_opener", 2)
634+
result.setdefault("user_preference", "")
635+
636+
return result
637+
638+
570639
def _enhance_progress_data_with_converter_statuses(progress_data: InterviewProgressData, note_path: str) -> InterviewProgressData:
571640
"""
572641
Enhance InterviewProgressData with question statuses from InterviewNoteProcessor.
@@ -1076,13 +1145,23 @@ async def session_chat(
10761145
domain = template.template_metadata.get("domain", "General")
10771146
role = template.template_metadata.get("role", "Expert")
10781147

1148+
# Fetch interview agent settings and count follow-ups
1149+
interview_settings = await _get_interview_agent_settings(db, applies_to="global")
1150+
followup_count = _count_followups_since_last_opener(conversation.messages)
1151+
logger.debug(
1152+
f"Interview settings: max_followups={interview_settings['max_followups_per_opener']}, current_followups={followup_count}"
1153+
)
1154+
10791155
question_handler = InterviewQuestionHandler(
10801156
kp_id=template.kp_id,
10811157
template_path=str(template_path),
10821158
rag_docs=rag_resource,
10831159
llm=llm,
10841160
domain=domain,
10851161
role=role,
1162+
max_followups=interview_settings["max_followups_per_opener"],
1163+
followup_count=followup_count,
1164+
user_preference=interview_settings["user_preference"],
10861165
)
10871166
# Set database session for ReadDocumentsTool
10881167
question_handler.db = db

dana_studio/dana/studio/api/server/server.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ async def lifespan(app: FastAPI):
8989
# Create base tables first
9090
Base.metadata.create_all(bind=engine)
9191

92+
# Initialize default prompt settings
93+
from sqlalchemy.orm import Session
94+
from dana.studio.api.shared.prompt_defaults import initialize_default_prompts
95+
96+
with Session(engine) as db:
97+
await initialize_default_prompts(db)
98+
9299
await broadcast_engine.connect()
93100
get_task_manager() # INIT
94101
yield

0 commit comments

Comments
 (0)