feat: LGBTQIA+ focus + Phase 2/3 audit fixes

LGBTQIA+ inclusion section in research briefs:
- user_profile.py: add candidate_lgbtq_focus bool accessor
- user.yaml.example: add candidate_lgbtq_focus flag (default false)
- company_research.py: gate new LGBTQIA+ section behind flag; section
  count now dynamic (7 base + 1 per opt-in section, max 9)
- 2_Settings.py: add "Research Brief Preferences" expander with
  checkboxes for both accessibility and LGBTQIA+ focus flags;
  mission_preferences now round-trips through save (no silent drop)

Phase 2 fixes:
- manage-vllm.sh: MODEL_DIR and VLLM_BIN now read from env vars
  (VLLM_MODELS_DIR, VLLM_BIN) with portable defaults
- search_profiles.yaml: replace personal CS/TAM/Bay Area profiles
  with a documented generic starter profile

Phase 3 fix:
- llm.yaml: rename alex-cover-writer:latest → llama3.2:3b with
  inline comment for users to substitute their fine-tuned model;
  fix model-exclusion comment
This commit is contained in:
pyr0ball 2026-02-24 20:02:03 -08:00
parent cf185dfbaf
commit 7abf753469
7 changed files with 67 additions and 117 deletions

View file

@ -121,6 +121,19 @@ with tab_profile:
if nb.button(" Add", key="add_nda") and new_nda.strip(): if nb.button(" Add", key="add_nda") and new_nda.strip():
nda_list.append(new_nda.strip()) nda_list.append(new_nda.strip())
with st.expander("🔍 Research Brief Preferences"):
st.caption("Optional identity-related sections added to pre-interview research briefs. For your personal decision-making only — never included in applications.")
u_access_focus = st.checkbox(
"Include disability & accessibility section",
value=_u.get("candidate_accessibility_focus", False),
help="Adds an ADA accommodation, ERG, and WCAG assessment to each company brief.",
)
u_lgbtq_focus = st.checkbox(
"Include LGBTQIA+ inclusion section",
value=_u.get("candidate_lgbtq_focus", False),
help="Adds an assessment of the company's LGBTQIA+ ERGs, policies, and culture signals.",
)
with st.expander("📁 File Paths"): with st.expander("📁 File Paths"):
u_docs = st.text_input("Documents directory", _u.get("docs_dir", "~/Documents/JobSearch")) u_docs = st.text_input("Documents directory", _u.get("docs_dir", "~/Documents/JobSearch"))
u_ollama = st.text_input("Ollama models directory", _u.get("ollama_models_dir", "~/models/ollama")) u_ollama = st.text_input("Ollama models directory", _u.get("ollama_models_dir", "~/models/ollama"))
@ -160,6 +173,9 @@ with tab_profile:
"nda_companies": nda_list, "nda_companies": nda_list,
"docs_dir": u_docs, "ollama_models_dir": u_ollama, "vllm_models_dir": u_vllm, "docs_dir": u_docs, "ollama_models_dir": u_ollama, "vllm_models_dir": u_vllm,
"inference_profile": u_inf_profile, "inference_profile": u_inf_profile,
"mission_preferences": _u.get("mission_preferences", {}),
"candidate_accessibility_focus": u_access_focus,
"candidate_lgbtq_focus": u_lgbtq_focus,
"services": { "services": {
"streamlit_port": _svc["streamlit_port"], "streamlit_port": _svc["streamlit_port"],
"ollama_host": svc_ollama_host, "ollama_port": int(svc_ollama_port), "ollama_host": svc_ollama_host, "ollama_port": int(svc_ollama_port),

View file

@ -23,7 +23,7 @@ backends:
api_key: ollama api_key: ollama
base_url: http://localhost:11434/v1 base_url: http://localhost:11434/v1
enabled: true enabled: true
model: alex-cover-writer:latest model: llama3.2:3b # replace with your fine-tuned cover letter model if you have one
type: openai_compat type: openai_compat
supports_images: false supports_images: false
ollama_research: ollama_research:
@ -61,6 +61,6 @@ vision_fallback_order:
- vision_service - vision_service
- claude_code - claude_code
- anthropic - anthropic
# Note: 'ollama' (alex-cover-writer) intentionally excluded — research # Note: 'ollama' intentionally excluded from research order — research
# must never use the fine-tuned writer model, and this also avoids evicting # must never use the cover letter model, and this also avoids evicting
# the writer from GPU memory while a cover letter task is in flight. # the writer from GPU memory while a cover letter task is in flight.

View file

@ -1,5 +1,22 @@
# Search profiles — define one or more named profiles with different
# job titles, locations, boards, and keyword filters.
# The first profile is used by default in the Job Review and Discovery pages.
#
# Each profile supports:
# name — identifier shown in the UI
# titles — job titles to search (exact phrases)
# locations — "Remote" or city/metro strings
# boards — standard boards: linkedin, indeed, glassdoor, zip_recruiter, google
# custom_boards — extra boards: adzuna, theladders, craigslist
# exclude_keywords — filter out postings containing these phrases
# hours_old — only return jobs posted within this many hours
# results_per_board — max results per board per run
# mission_tags — optional tags that influence cover-letter mission alignment
# (must match a key in mission_preferences in user.yaml)
profiles: profiles:
- boards: - name: primary
boards:
- linkedin - linkedin
- indeed - indeed
- glassdoor - glassdoor
@ -7,117 +24,16 @@ profiles:
- google - google
custom_boards: custom_boards:
- adzuna - adzuna
- theladders
- craigslist - craigslist
titles:
- "Your Target Title"
- "Alternative Title"
locations:
- Remote
exclude_keywords: exclude_keywords:
- sales - sales
- account executive - account executive
- sales engineer
- SDR - SDR
- BDR - BDR
- business development
- sales development
- sales manager
- sales representative
- sales rep
hours_old: 240 hours_old: 240
locations:
- Remote
- San Francisco Bay Area, CA
name: cs_leadership
results_per_board: 75
titles:
- Customer Success Manager
- Customer Engagement Manager
- Director of Customer Success
- VP Customer Success
- Head of Customer Success
- Technical Account Manager
- TAM
- Customer Experience Lead
- CSM
- CX
- Customer Success Consultant
- boards:
- linkedin
- indeed
custom_boards:
- adzuna
- craigslist
exclude_keywords:
- sales
- account executive
- SDR
- BDR
- sales development
hours_old: 336
locations:
- Remote
- San Francisco Bay Area, CA
mission_tags:
- music
name: music_industry
results_per_board: 50 results_per_board: 50
titles:
- Customer Success Manager
- Partner Success Manager
- Artist Success Manager
- Creator Success Manager
- Technical Account Manager
- Community Manager
- Account Manager
- Label Relations Manager
- boards:
- linkedin
- indeed
custom_boards:
- adzuna
- craigslist
exclude_keywords:
- sales
- account executive
- SDR
- BDR
hours_old: 336
locations:
- Remote
- San Francisco Bay Area, CA
mission_tags:
- animal_welfare
name: animal_welfare
results_per_board: 50
titles:
- Customer Success Manager
- Program Manager
- Community Engagement Manager
- Operations Manager
- Partner Success Manager
- Account Manager
- Development Manager
- boards:
- linkedin
- indeed
custom_boards:
- adzuna
- craigslist
exclude_keywords:
- sales
- account executive
- SDR
- BDR
hours_old: 336
locations:
- Remote
- San Francisco Bay Area, CA
mission_tags:
- education
name: education
results_per_board: 50
titles:
- Customer Success Manager
- District Success Manager
- Implementation Specialist
- Partner Success Manager
- Account Manager
- School Success Manager
- Customer Experience Manager

View file

@ -21,11 +21,15 @@ mission_preferences:
animal_welfare: "" # e.g. "I volunteer at my local shelter every weekend" animal_welfare: "" # e.g. "I volunteer at my local shelter every weekend"
education: "" # e.g. "I tutored underserved kids for 3 years and care deeply about literacy" education: "" # e.g. "I tutored underserved kids for 3 years and care deeply about literacy"
# Set to true to include an Inclusion & Accessibility section in research briefs. # Set to true to include optional identity-related sections in research briefs.
# When true, each company brief will assess disability/ADA accommodation signals, # Both are for your personal decision-making only — never included in applications.
# ERGs, and accessibility culture. Useful if this is a personal factor in your decisions.
# Adds a disability inclusion & accessibility section (ADA, ERGs, WCAG signals).
candidate_accessibility_focus: false candidate_accessibility_focus: false
# Adds an LGBTQIA+ inclusion section (ERGs, non-discrimination policies, culture signals).
candidate_lgbtq_focus: false
docs_dir: "~/Documents/JobSearch" docs_dir: "~/Documents/JobSearch"
ollama_models_dir: "~/models/ollama" ollama_models_dir: "~/models/ollama"
vllm_models_dir: "~/models/vllm" vllm_models_dir: "~/models/vllm"

View file

@ -371,7 +371,8 @@ def research_company(job: dict, use_scraper: bool = True, on_stage=None) -> dict
name = _profile.name if _profile else "the candidate" name = _profile.name if _profile else "the candidate"
career_summary = _profile.career_summary if _profile else "" career_summary = _profile.career_summary if _profile else ""
accessibility_focus = _profile.candidate_accessibility_focus if _profile else False accessibility_focus = _profile.candidate_accessibility_focus if _profile else False
_section_count = 8 if accessibility_focus else 7 lgbtq_focus = _profile.candidate_lgbtq_focus if _profile else False
_section_count = 7 + (1 if accessibility_focus else 0) + (1 if lgbtq_focus else 0)
_accessibility_section = """ _accessibility_section = """
## Inclusion & Accessibility ## Inclusion & Accessibility
Assess {company}'s commitment to disability inclusion and accessibility. Cover: Assess {company}'s commitment to disability inclusion and accessibility. Cover:
@ -383,6 +384,17 @@ Assess {company}'s commitment to disability inclusion and accessibility. Cover:
If no specific signals are found, say so clearly absence of public commitment is itself signal. If no specific signals are found, say so clearly absence of public commitment is itself signal.
This section is for the candidate's personal decision-making only and will not appear in any application. This section is for the candidate's personal decision-making only and will not appear in any application.
""".format(company=company) if accessibility_focus else "" """.format(company=company) if accessibility_focus else ""
_lgbtq_section = """
## LGBTQIA+ Inclusion
Assess {company}'s culture and policies around LGBTQIA+ inclusion. Cover:
- Non-discrimination policies that explicitly include sexual orientation and gender identity
- LGBTQIA+ Employee Resource Group (ERG) or Pride Network
- Benefits that support LGBTQIA+ employees (gender-affirming care, domestic partner benefits)
- Public statements, donations, or advocacy (Pride sponsorships, HRC Corporate Equality Index rating)
- Glassdoor or press signals about how LGBTQIA+ employees experience the company day-to-day
If no specific signals are found, say so clearly absence of public commitment is itself signal.
This section is for the candidate's personal decision-making only and will not appear in any application.
""".format(company=company) if lgbtq_focus else ""
prompt = f"""You are preparing {name} for a job interview. prompt = f"""You are preparing {name} for a job interview.
{f"Candidate background: {career_summary}" if career_summary else ""} {f"Candidate background: {career_summary}" if career_summary else ""}
@ -421,7 +433,7 @@ Draw on the live snippets above; if none available, note what is publicly known.
Culture issues, layoffs, exec departures, financial stress, or Glassdoor concerns worth knowing before the call. Culture issues, layoffs, exec departures, financial stress, or Glassdoor concerns worth knowing before the call.
If nothing notable, write "No significant red flags identified." If nothing notable, write "No significant red flags identified."
{_accessibility_section} {_lgbtq_section}{_accessibility_section}
## Talking Points for {name} ## Talking Points for {name}
Five specific talking points for the phone screen. Each must: Five specific talking points for the phone screen. Each must:
- Reference a concrete experience from {name}'s matched background by name - Reference a concrete experience from {name}'s matched background by name

View file

@ -4,8 +4,8 @@
set -euo pipefail set -euo pipefail
VLLM_BIN="/devl/miniconda3/envs/vllm/bin/python" VLLM_BIN="${VLLM_BIN:-python3}"
MODEL_DIR="/Library/Assets/LLM/vllm/models" MODEL_DIR="${VLLM_MODELS_DIR:-${HOME}/models/vllm}"
PID_FILE="/tmp/vllm-server.pid" PID_FILE="/tmp/vllm-server.pid"
LOG_FILE="/tmp/vllm-server.log" LOG_FILE="/tmp/vllm-server.log"
MODEL_FILE="/tmp/vllm-server.model" MODEL_FILE="/tmp/vllm-server.model"

View file

@ -22,6 +22,7 @@ _DEFAULTS = {
"inference_profile": "remote", "inference_profile": "remote",
"mission_preferences": {}, "mission_preferences": {},
"candidate_accessibility_focus": False, "candidate_accessibility_focus": False,
"candidate_lgbtq_focus": False,
"services": { "services": {
"streamlit_port": 8501, "streamlit_port": 8501,
"ollama_host": "localhost", "ollama_host": "localhost",
@ -62,6 +63,7 @@ class UserProfile:
self.inference_profile: str = data["inference_profile"] self.inference_profile: str = data["inference_profile"]
self.mission_preferences: dict[str, str] = data.get("mission_preferences", {}) self.mission_preferences: dict[str, str] = data.get("mission_preferences", {})
self.candidate_accessibility_focus: bool = bool(data.get("candidate_accessibility_focus", False)) self.candidate_accessibility_focus: bool = bool(data.get("candidate_accessibility_focus", False))
self.candidate_lgbtq_focus: bool = bool(data.get("candidate_lgbtq_focus", False))
self._svc = data["services"] self._svc = data["services"]
# ── Service URLs ────────────────────────────────────────────────────────── # ── Service URLs ──────────────────────────────────────────────────────────