From 210ae3d665e2cf790d702395f6da71b4743e8d9f Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Thu, 5 Mar 2026 15:13:57 -0800 Subject: [PATCH] feat: add LLM suggest button to Skills & Keywords section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Places a ✨ Suggest button inline with the Skills & Keywords subheader. On click, calls suggest_resume_keywords() and stores results in session state. Suggestions render as per-category chip panels (skills, domains, keywords); clicking a chip appends it to the YAML and removes it from the panel. A βœ• Clear button dismisses the panel entirely. --- app/pages/2_Settings.py | 59 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/app/pages/2_Settings.py b/app/pages/2_Settings.py index 0886c1b..0d16bf3 100644 --- a/app/pages/2_Settings.py +++ b/app/pages/2_Settings.py @@ -741,11 +741,33 @@ with tab_resume: st.balloons() st.divider() - st.subheader("🏷️ Skills & Keywords") - st.caption( - f"Matched against job descriptions to surface {_name}'s most relevant experience " - "and highlight keyword overlap in research briefs. Search the bundled list or add your own." - ) + _kw_header_col, _kw_btn_col = st.columns([5, 1]) + with _kw_header_col: + st.subheader("🏷️ Skills & Keywords") + st.caption( + f"Matched against job descriptions to surface {_name}'s most relevant experience " + "and highlight keyword overlap in research briefs. Search the bundled list or add your own." + ) + with _kw_btn_col: + st.write("") + st.write("") + _run_kw_suggest = st.button( + "✨ Suggest", key="kw_suggest_btn", + help="Ask the LLM to suggest skills, domains, and keywords based on your resume.", + ) + + if _run_kw_suggest: + _kw_current = load_yaml(KEYWORDS_CFG) if KEYWORDS_CFG.exists() else {} + with st.spinner("Asking LLM for keyword suggestions…"): + try: + _kw_sugg = _suggest_resume_keywords(RESUME_PATH, _kw_current) + st.session_state["_kw_suggestions"] = _kw_sugg + except RuntimeError as _e: + st.warning( + f"No LLM backend available: {_e}. " + "Check that Ollama is running and has GPU access, or enable a cloud backend in Settings β†’ System β†’ LLM.", + icon="⚠️", + ) from scripts.skills_utils import load_suggestions as _load_sugg, filter_tag as _filter_tag @@ -809,6 +831,33 @@ with tab_resume: save_yaml(KEYWORDS_CFG, kw_data) st.rerun() + # ── LLM keyword suggestion chips ────────────────────────────────────── + _kw_sugg_data = st.session_state.get("_kw_suggestions") + if _kw_sugg_data: + _KW_ICONS = {"skills": "πŸ› οΈ", "domains": "🏒", "keywords": "πŸ”‘"} + _any_shown = False + for _cat, _icon in _KW_ICONS.items(): + _cat_sugg = [t for t in _kw_sugg_data.get(_cat, []) + if t not in kw_data.get(_cat, [])] + if not _cat_sugg: + continue + _any_shown = True + st.caption(f"**{_icon} {_cat.capitalize()} suggestions** β€” click to add:") + _chip_cols = st.columns(min(len(_cat_sugg), 4)) + for _i, _tag in enumerate(_cat_sugg): + with _chip_cols[_i % 4]: + if st.button(f"+ {_tag}", key=f"kw_sugg_{_cat}_{_i}"): + _new_list = list(kw_data.get(_cat, [])) + [_tag] + kw_data[_cat] = _new_list + save_yaml(KEYWORDS_CFG, kw_data) + _kw_sugg_data[_cat] = [t for t in _kw_sugg_data[_cat] if t != _tag] + st.session_state["_kw_suggestions"] = _kw_sugg_data + st.rerun() + if _any_shown: + if st.button("βœ• Clear suggestions", key="kw_clear_sugg"): + st.session_state.pop("_kw_suggestions", None) + st.rerun() + # ── System tab ──────────────────────────────────────────────────────────────── with tab_system: st.caption("Infrastructure, LLM backends, integrations, and service connections.")