Skip to content

Commit fc4fba2

Browse files
committed
Merge branch 'mued_api_adopted' into dev
2 parents ad2cb0e + e3711d3 commit fc4fba2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1572
-2271
lines changed

.dockerignore

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,4 @@ data/
147147
reports/
148148

149149
# Synthetic data conversations
150-
src/agents/utils/example_inputs/
151-
src/agents/utils/synthetic_conversations/
152-
src/agents/utils/synthetic_conversation_generation.py
153-
src/agents/utils/testbench_prompts.py
154-
src/agents/utils/langgraph_viz.py
155-
156-
# development agents
157-
src/agents/student_agent/
150+
src/agents/utils/example_inputs/

.github/workflows/dev.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
if: always()
5151
run: |
5252
source .venv/bin/activate
53+
export PYTHONPATH=$PYTHONPATH:.
5354
pytest --junit-xml=./reports/pytest.xml --tb=auto -v
5455
5556
- name: Upload test results

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ jobs:
5050
if: always()
5151
run: |
5252
source .venv/bin/activate
53+
export PYTHONPATH=$PYTHONPATH:.
5354
pytest --junit-xml=./reports/pytest.xml --tb=auto -v
5455
5556
- name: Upload test results

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ coverage.xml
5050
*.py,cover
5151
.hypothesis/
5252
.pytest_cache/
53+
reports/
5354

5455
# Translations
5556
*.mo

AGENTS.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# AGENTS.md
2+
3+
This file provides guidance to AI agents when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a boilerplate for creating AI educational chatbots that integrate with the **Lambda-Feedback** educational platform. It deploys as an AWS Lambda function (containerized via Docker) that receives student chat messages with educational context and returns LLM-powered chatbot responses.
8+
9+
## Commands
10+
11+
**Testing:**
12+
```bash
13+
pytest # Run all unit tests
14+
python tests/manual_agent_run.py # Test agent locally with example inputs
15+
python tests/manual_agent_requests.py # Test running Docker container
16+
```
17+
18+
**Docker:**
19+
```bash
20+
docker build -t llm_chat .
21+
docker run --env-file .env -p 8080:8080 llm_chat
22+
```
23+
24+
**Manual API test (while Docker is running):**
25+
```bash
26+
curl -X POST http://localhost:8080/2015-03-31/functions/function/invocations \
27+
-H 'Content-Type: application/json' \
28+
-d '{"body":"{\"conversationId\": \"12345Test\", \"messages\": [{\"role\": \"USER\", \"content\": \"hi\"}], \"user\": {\"type\": \"LEARNER\"}}"}'
29+
```
30+
31+
**Run a single test:**
32+
```bash
33+
pytest tests/test_module.py # Run specific test file
34+
pytest tests/test_index.py::test_function_name # Run specific test
35+
```
36+
37+
## Architecture
38+
39+
### Request Flow
40+
41+
```
42+
Lambda event → index.py (handler)
43+
→ validates via lf_toolkit ChatRequest schema
44+
→ src/module.py (chat_module)
45+
→ extracts muEd API context (messages, conversationId, question context, user type)
46+
→ parses educational context to prompt text via src/agent/context.py
47+
→ src/agent/agent.py (BaseAgent / LangGraph)
48+
→ routes to call_llm or summarize_conversation node
49+
→ calls LLM provider (OpenAI / Google / Azure / Ollama)
50+
→ returns ChatResponse (output, summary, conversationalStyle, processingTime)
51+
```
52+
53+
### Key Files
54+
55+
| File | Role |
56+
|------|------|
57+
| `index.py` | AWS Lambda entry point; parses event body, validates schema |
58+
| `src/module.py` | Transforms muEd API request → invokes agent → builds ChatResponse |
59+
| `src/agent/agent.py` | LangGraph stateful graph; manages message history and summarization |
60+
| `src/agent/prompts.py` | System prompts for tutor behavior, summarization, style detection |
61+
| `src/agent/llm_factory.py` | Factory classes for each LLM provider (OpenAI, Google, Azure, Ollama) |
62+
| `src/agent/context.py` | Converts muEd question/submission context dicts to LLM prompt text |
63+
| `tests/utils.py` | Shared test helpers: `assert_valid_chat_request`, `assert_valid_chat_response` |
64+
| `tests/example_inputs/` | Real muEd payloads used for end-to-end tests |
65+
66+
### Agent Logic (LangGraph)
67+
68+
`BaseAgent` maintains a state graph with two nodes:
69+
- **`call_llm`**: Invokes the LLM with system prompt + conversation summary + conversational style preference
70+
- **`summarize_conversation`**: Triggered when message count exceeds ~11; summarizes history and also extracts the student's preferred conversational style
71+
72+
Messages are trimmed after summarization to keep context window manageable. The `summary` and `conversationalStyle` fields persist across calls via the `ChatRequest` metadata.
73+
74+
### muEd API Format
75+
76+
`src/module.py` handles the muEd request format (https://mued.org/). The `context` field in `ChatRequest` contains nested educational data (question parts, student submissions, task info) that gets parsed into a tutoring prompt via `src/agent/context.py`.
77+
78+
### LLM Configuration
79+
80+
LLM provider and model are set via environment variables (see `.env.example`). The `llm_factory.py` selects the provider at runtime. The Lambda function name/identity is set in `config.json`.
81+
82+
The agent uses **two separate LLM instances**`self.llm` for chat responses and `self.summarisation_llm` for conversation summarisation and style analysis. By default both use the same provider, but you can point them at different models (e.g. a cheaper model for summarisation) by changing the class in `agent.py`.
83+
84+
## Deployment
85+
86+
- Pushing to `dev` branch triggers the dev deployment GitHub Actions workflow
87+
- Pushing to `main` triggers staging deployment, with manual approval required for production
88+
- All environment variables (API keys, model names) are injected via GitHub Actions secrets/variables — do not hardcode them

CLAUDE.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a boilerplate for creating AI educational chatbots that integrate with the **Lambda-Feedback** educational platform. It deploys as an AWS Lambda function (containerized via Docker) that receives student chat messages with educational context and returns LLM-powered chatbot responses.
8+
9+
## Commands
10+
11+
**Testing:**
12+
```bash
13+
pytest # Run all unit tests
14+
python tests/manual_agent_run.py # Test agent locally with example inputs
15+
python tests/manual_agent_requests.py # Test running Docker container
16+
```
17+
18+
**Docker:**
19+
```bash
20+
docker build -t llm_chat .
21+
docker run --env-file .env -p 8080:8080 llm_chat
22+
```
23+
24+
**Manual API test (while Docker is running):**
25+
```bash
26+
curl -X POST http://localhost:8080/2015-03-31/functions/function/invocations \
27+
-H 'Content-Type: application/json' \
28+
-d '{"body":"{\"conversationId\": \"12345Test\", \"messages\": [{\"role\": \"USER\", \"content\": \"hi\"}], \"user\": {\"type\": \"LEARNER\"}}"}'
29+
```
30+
31+
**Run a single test:**
32+
```bash
33+
pytest tests/test_module.py # Run specific test file
34+
pytest tests/test_index.py::test_function_name # Run specific test
35+
```
36+
37+
## Architecture
38+
39+
### Request Flow
40+
41+
```
42+
Lambda event → index.py (handler)
43+
→ validates via lf_toolkit ChatRequest schema
44+
→ src/module.py (chat_module)
45+
→ extracts muEd API context (messages, conversationId, question context, user type)
46+
→ parses educational context to prompt text via src/agent/context.py
47+
→ src/agent/agent.py (BaseAgent / LangGraph)
48+
→ routes to call_llm or summarize_conversation node
49+
→ calls LLM provider (OpenAI / Google / Azure / Ollama)
50+
→ returns ChatResponse (output, summary, conversationalStyle, processingTime)
51+
```
52+
53+
### Key Files
54+
55+
| File | Role |
56+
|------|------|
57+
| `index.py` | AWS Lambda entry point; parses event body, validates schema |
58+
| `src/module.py` | Transforms muEd API request → invokes agent → builds ChatResponse |
59+
| `src/agent/agent.py` | LangGraph stateful graph; manages message history and summarization |
60+
| `src/agent/prompts.py` | System prompts for tutor behavior, summarization, style detection |
61+
| `src/agent/llm_factory.py` | Factory classes for each LLM provider (OpenAI, Google, Azure, Ollama) |
62+
| `src/agent/context.py` | Converts muEd question/submission context dicts to LLM prompt text |
63+
| `tests/utils.py` | Shared test helpers: `assert_valid_chat_request`, `assert_valid_chat_response` |
64+
| `tests/example_inputs/` | Real muEd payloads used for end-to-end tests |
65+
66+
### Agent Logic (LangGraph)
67+
68+
`BaseAgent` maintains a state graph with two nodes:
69+
- **`call_llm`**: Invokes the LLM with system prompt + conversation summary + conversational style preference
70+
- **`summarize_conversation`**: Triggered when message count exceeds ~11; summarizes history and also extracts the student's preferred conversational style
71+
72+
Messages are trimmed after summarization to keep context window manageable. The `summary` and `conversationalStyle` fields persist across calls via the `ChatRequest` metadata.
73+
74+
### muEd API Format
75+
76+
`src/module.py` handles the muEd request format (https://mued.org/). The `context` field in `ChatRequest` contains nested educational data (question parts, student submissions, task info) and the `user` field contains user-specific information (e.g., user type, preferences, task progress) that gets parsed into a tutoring prompt via `src/agent/context.py`.
77+
78+
### LLM Configuration
79+
80+
LLM provider and model are set via environment variables (see `.env.example`). The `llm_factory.py` selects the provider at runtime. The Lambda function name/identity is set in `config.json`.
81+
82+
The agent uses **two separate LLM instances**`self.llm` for chat responses and `self.summarisation_llm` for conversation summarisation and style analysis. By default both use the same provider, but you can point them at different models (e.g. a cheaper model for summarisation) by changing the class in `agent.py`.
83+
84+
## Deployment
85+
86+
- Pushing to `dev` branch triggers the dev deployment GitHub Actions workflow
87+
- Pushing to `main` triggers staging deployment, with manual approval required for production
88+
- All environment variables (API keys, model names) are injected via GitHub Actions secrets/variables — do not hardcode them

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ COPY src ./src
2525

2626
COPY index.py .
2727

28-
COPY index_test.py .
28+
COPY tests ./tests
2929

3030
# Set the Lambda function handler
3131
CMD ["index.handler"]

0 commit comments

Comments
 (0)