-
Notifications
You must be signed in to change notification settings - Fork 1
[critical] [feat] Stand-alone core agent micro-service in Python #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
lf1up
wants to merge
4
commits into
main
Choose a base branch
from
feat/stand-alone-agent
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| # ============================================================================= | ||
| # Docker Ignore - CareerSim Agent | ||
| # ============================================================================= | ||
|
|
||
| # Python | ||
| __pycache__/ | ||
| *.py[cod] | ||
| *$py.class | ||
| *.so | ||
| .Python | ||
| *.egg-info/ | ||
| *.egg | ||
| .eggs/ | ||
| dist/ | ||
| build/ | ||
| *.manifest | ||
| *.spec | ||
|
|
||
| # Virtual environments | ||
| .venv/ | ||
| venv/ | ||
| ENV/ | ||
| env/ | ||
|
|
||
| # IDE | ||
| .idea/ | ||
| .vscode/ | ||
| *.swp | ||
| *.swo | ||
| *~ | ||
|
|
||
| # Testing | ||
| .pytest_cache/ | ||
| .coverage | ||
| htmlcov/ | ||
| .tox/ | ||
| .nox/ | ||
|
|
||
| # Logs | ||
| logs/ | ||
| *.log | ||
|
|
||
| # Local environment | ||
| .env | ||
| .env.local | ||
| .env.*.local | ||
|
|
||
| # HuggingFace cache (will be mounted as volume) | ||
| .cache/ | ||
|
|
||
| # Git | ||
| .git/ | ||
| .gitignore | ||
|
|
||
| # Docker | ||
| Dockerfile | ||
| docker-compose*.yml | ||
| .docker/ | ||
|
|
||
| # Documentation | ||
| *.md | ||
| !README.md | ||
| docs/ | ||
|
|
||
| # Misc | ||
| .DS_Store | ||
| Thumbs.db |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| # ============================================================================= | ||
| # CareerSim Agent Configuration | ||
| # ============================================================================= | ||
| # Copy this file to .env and fill in your values: | ||
| # cp .env.example .env | ||
| # ============================================================================= | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # OpenAI API Configuration (REQUIRED) | ||
| # ----------------------------------------------------------------------------- | ||
|
|
||
| # Your OpenAI API key (required for AI responses) | ||
| OPENAI_API_KEY=your-openai-api-key | ||
|
|
||
| # Base URL for OpenAI-compatible API | ||
| # Use https://api.openai.com/v1 for OpenAI direct | ||
| # Use https://openrouter.ai/api/v1 for OpenRouter | ||
| OPENAI_BASE_URL=https://openrouter.ai/api/v1 | ||
|
|
||
| # Model to use for conversation generation | ||
| # OpenAI: gpt-4o, gpt-4o-mini, gpt-4-turbo, gpt-3.5-turbo | ||
| # OpenRouter: openai/gpt-4o, anthropic/claude-3.5-sonnet, etc. | ||
| OPENAI_MODEL=openai/gpt-5.2 | ||
|
|
||
| # Provider name (openai, anthropic, google, etc.) | ||
| OPENAI_PROVIDER=openai | ||
|
|
||
| # Maximum tokens in AI response | ||
| OPENAI_MAX_TOKENS=250000 | ||
|
|
||
| # Temperature for response generation (0.0 = deterministic, 1.0 = creative) | ||
| OPENAI_TEMPERATURE=0.7 | ||
|
|
||
| # Top-p (nucleus sampling) - alternative to temperature | ||
| OPENAI_TOP_P=1.0 | ||
|
|
||
| # Frequency penalty (0.0 - 2.0) - reduces repetition of token sequences | ||
| OPENAI_FREQUENCY_PENALTY=0 | ||
|
|
||
| # Presence penalty (0.0 - 2.0) - encourages new topics | ||
| OPENAI_PRESENCE_PENALTY=0 | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # Evaluation Model Configuration (Optional) | ||
| # Used for goal evaluation - can use a different/cheaper model | ||
| # ----------------------------------------------------------------------------- | ||
|
|
||
| # Model for evaluation tasks (defaults to main model if not set) | ||
| OPENAI_EVAL_MODEL=google/gemini-2.5-flash | ||
|
|
||
| # Provider for evaluation model | ||
| OPENAI_EVAL_PROVIDER=google | ||
|
|
||
| OPENAI_EVAL_MAX_TOKENS=250000 | ||
|
|
||
| # Lower temperature for more consistent evaluations | ||
| OPENAI_EVAL_TEMPERATURE=0.3 | ||
| OPENAI_EVAL_TOP_P=1.0 | ||
|
|
||
| # Penalties for evaluation model | ||
| OPENAI_EVAL_FREQUENCY_PENALTY=0.3 | ||
| OPENAI_EVAL_PRESENCE_PENALTY=0.3 | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # Gradio UI Configuration | ||
| # ----------------------------------------------------------------------------- | ||
|
|
||
| # Port for the Gradio web interface | ||
| GRADIO_SERVER_PORT=7860 | ||
|
|
||
| # Set to true to create a public share link (useful for remote access) | ||
| GRADIO_SHARE=false | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # Application Settings | ||
| # ----------------------------------------------------------------------------- | ||
|
|
||
| # Logging level: DEBUG, INFO, WARNING, ERROR | ||
| LOG_LEVEL=DEBUG | ||
|
|
||
| # Skip preloading HuggingFace models at startup (faster startup, slower first request) | ||
| # Set to 1/true to skip, 0/false to preload | ||
| SKIP_PRELOAD=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| # ============================================================================= | ||
| # CareerSim Agent - Core Microservice | ||
| # ============================================================================= | ||
| # Multi-stage Dockerfile for the LangGraph conversation agent with Gradio API | ||
| # Connect from backend using gradio_client | ||
| # ============================================================================= | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # Stage 1: Builder - Install dependencies | ||
| # ----------------------------------------------------------------------------- | ||
| FROM python:3.11-slim AS builder | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Install build dependencies | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| build-essential \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Install uv for faster dependency installation | ||
| RUN pip install --no-cache-dir uv | ||
|
|
||
| # Copy dependency files | ||
| COPY pyproject.toml ./ | ||
|
|
||
| # Create virtual environment and install dependencies | ||
| RUN uv venv /app/.venv | ||
| ENV PATH="/app/.venv/bin:$PATH" | ||
| RUN uv pip install --no-cache . | ||
|
|
||
| # ----------------------------------------------------------------------------- | ||
| # Stage 2: Runtime - Final image | ||
| # ----------------------------------------------------------------------------- | ||
| FROM python:3.11-slim AS runtime | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| # Install runtime dependencies (for torch/transformers) | ||
| RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
| libgomp1 \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Create non-root user for security | ||
| RUN useradd --create-home --shell /bin/bash appuser | ||
|
|
||
| # Copy virtual environment from builder | ||
| COPY --from=builder /app/.venv /app/.venv | ||
|
|
||
| # Set environment variables | ||
| ENV PATH="/app/.venv/bin:$PATH" | ||
| ENV PYTHONUNBUFFERED=1 | ||
| ENV PYTHONDONTWRITEBYTECODE=1 | ||
|
|
||
| # HuggingFace cache directory (will be mounted as volume) | ||
| ENV HF_HOME=/app/.cache/huggingface | ||
| ENV TRANSFORMERS_CACHE=/app/.cache/huggingface | ||
|
|
||
| # Gradio configuration for API access | ||
| ENV GRADIO_SERVER_NAME=0.0.0.0 | ||
| ENV GRADIO_SERVER_PORT=7860 | ||
|
|
||
| # Copy application code | ||
| COPY --chown=appuser:appuser src/ ./src/ | ||
| COPY --chown=appuser:appuser data/ ./data/ | ||
| COPY --chown=appuser:appuser pyproject.toml ./ | ||
|
|
||
| # Install package in editable mode | ||
| RUN pip install --no-cache-dir -e . | ||
|
|
||
| # Create cache directory with correct permissions | ||
| RUN mkdir -p /app/.cache/huggingface && chown -R appuser:appuser /app/.cache | ||
| RUN mkdir -p /app/logs && chown -R appuser:appuser /app/logs | ||
|
|
||
| # Switch to non-root user | ||
| USER appuser | ||
|
|
||
| # Expose Gradio port | ||
| EXPOSE 7860 | ||
|
|
||
| # Health check - Gradio provides a /info endpoint | ||
| HEALTHCHECK --interval=30s --timeout=10s --retries=5 --start-period=120s \ | ||
| CMD python -c "import httpx; r = httpx.get('http://localhost:7860/', timeout=5.0); exit(0 if r.status_code == 200 else 1)" | ||
|
|
||
| # Default command - run the agent | ||
| CMD ["python", "-m", "careersim_agent.main"] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| # CareerSim Agent | ||
|
|
||
| A standalone Python LangGraph agent with a Gradio developer UI for career simulation conversations. | ||
|
|
||
| ## Features | ||
|
|
||
| - **LangGraph-based conversation flow** with persona-driven AI responses | ||
| - **Local HuggingFace transformers** for sentiment and emotion analysis | ||
| - **Goal evaluation** using zero-shot classification | ||
| - **Gradio developer console** with: | ||
| - Real-time state inspection | ||
| - Node execution tracing | ||
| - Goal progress dashboard | ||
| - Manual trigger buttons (inactivity, followup) | ||
| - **API endpoints** for programmatic access via `gradio_client` | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### Local Development | ||
|
|
||
| ```bash | ||
| # Create and activate virtual environment | ||
| python3 -m venv .venv | ||
| source .venv/bin/activate # On Windows: .venv\Scripts\activate | ||
|
|
||
| # Install dependencies | ||
| pip install -e . | ||
|
|
||
| # Or using uv (faster) | ||
| uv venv | ||
| source .venv/bin/activate | ||
| uv sync | ||
|
|
||
| # Copy and configure environment | ||
| cp .env.example .env | ||
| # Edit .env and add your OPENAI_API_KEY | ||
|
|
||
| # Run the agent | ||
| python -m careersim_agent.main | ||
| ``` | ||
|
|
||
| The Gradio UI will open at http://localhost:7860 | ||
|
|
||
| > **Note**: First run will download HuggingFace models (~500MB). Set `SKIP_PRELOAD=1` to defer this. | ||
|
|
||
| ### Docker (as Core Microservice) | ||
|
|
||
| Run the agent as part of the cluster: | ||
|
|
||
| ```bash | ||
| # From the project root | ||
| docker-compose -f docker-compose.local.yml up core | ||
|
|
||
| # Or with the full stack | ||
| docker-compose -f docker-compose.local.yml up | ||
| ``` | ||
|
|
||
| The service will be available at: | ||
| - **Internal (for backend)**: `http://core:7860` | ||
| - **External (for dev)**: `http://localhost:7860` | ||
|
|
||
| ## API Usage (gradio_client) | ||
|
|
||
| Connect from the backend using `gradio_client`: | ||
|
|
||
| ```python | ||
| from gradio_client import Client | ||
|
|
||
| # Connect to the core service | ||
| client = Client("http://core:7860") # or http://localhost:7860 | ||
|
|
||
| # List available simulations | ||
| result = client.predict(api_name="/api_list_simulations") | ||
| print(result["simulations"]) | ||
|
|
||
| # Start a session | ||
| result = client.predict( | ||
| simulation_slug="behavioral-interview-brenda", | ||
| api_name="/api_start_session" | ||
| ) | ||
| session_id = result["session_id"] | ||
| print(f"Started session: {session_id}") | ||
| print(f"Initial message: {result['messages']}") | ||
|
|
||
| # Send a message | ||
| result = client.predict( | ||
| session_id=session_id, | ||
| message="Hello, I'm ready for my interview.", | ||
| api_name="/api_send_message" | ||
| ) | ||
| print(f"AI response: {result['messages'][-1]}") | ||
| print(f"Goal progress: {result['goal_progress']}") | ||
|
|
||
| # Trigger proactive message (inactivity, followup) | ||
| result = client.predict( | ||
| session_id=session_id, | ||
| trigger_type="followup", | ||
| api_name="/api_trigger_proactive" | ||
| ) | ||
|
|
||
| # Get full session state | ||
| result = client.predict( | ||
| session_id=session_id, | ||
| api_name="/api_get_session_state" | ||
| ) | ||
|
|
||
| # End session | ||
| result = client.predict( | ||
| session_id=session_id, | ||
| api_name="/api_end_session" | ||
| ) | ||
| ``` | ||
|
|
||
| ### API Endpoints | ||
|
|
||
| | Endpoint | Description | | ||
| |----------|-------------| | ||
| | `/api_list_simulations` | List all available simulations | | ||
| | `/api_start_session` | Start a new conversation session | | ||
| | `/api_send_message` | Send a user message and get AI response | | ||
| | `/api_trigger_proactive` | Trigger proactive message (start/inactivity/followup) | | ||
| | `/api_get_session_state` | Get full session state | | ||
| | `/api_end_session` | End and cleanup a session | | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ``` | ||
| agent/ | ||
| ├── data/ | ||
| │ ├── personas.json # Persona definitions | ||
| │ └── simulations.json # Simulation + goals | ||
| ├── src/careersim_agent/ | ||
| │ ├── main.py # Entry point | ||
| │ ├── config.py # Settings | ||
| │ ├── graph/ # LangGraph components | ||
| │ │ ├── state.py # State schema | ||
| │ │ ├── builder.py # Graph construction | ||
| │ │ └── nodes/ # Node implementations | ||
| │ ├── prompts/ # Prompt templates | ||
| │ ├── services/ # Data loader, transformers | ||
| │ └── ui/ # Gradio interface | ||
| └── tests/ | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| Edit `data/personas.json` and `data/simulations.json` to customize personas and scenarios. | ||
|
|
||
| ## Development | ||
|
|
||
| This is a lab/experimental environment designed for rapid iteration. | ||
| It can evolve into a production microservice. | ||
|
|
||
| Key simplifications vs production: | ||
| - JSON files instead of database | ||
| - In-memory state (no checkpointing) | ||
| - Manual triggers instead of background schedulers | ||
| - Local transformers instead of external service |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Docker builder stage fails without source code
High Severity
The builder stage copies only
pyproject.tomlthen runsuv pip install --no-cache ., which invokes the hatchling build backend. Hatchling requires thesrc/careersim_agentdirectory (specified viapackagesinpyproject.toml) to build the wheel, but source code isn't copied until the runtime stage. This causes the Docker build to fail with a hatchling error about missing package files. The intent was to pre-install dependencies for layer caching, butuv pip install .tries to build the whole project, not just its dependencies.