Retrieval supplies context, not certainty.
Embeddings and Chroma retrieval bring relevant news into the language-model context. News can qualify numerical advice, but a retrieved report is still a source with its own date and uncertainty.
Player statistics tell part of the story. Retrieval brings the surrounding context.
Team lead · RAG & integration · 6 people
University team project · April 2026
Python / Chroma / XGBoost / Streamlit
Evidence gives the numbers a second dimension.
Fantasy Premier League managers need both numerical player context and news that can change how those numbers should be interpreted. FPL-Intel combines data ingestion, feature engineering, player scoring, retrieval, and a conversational interface.
This was a six-member university team project. The inspected saved database contains 826 players, 20 teams, 380 fixtures, and 20 news articles. These are historical snapshot counts, not a current football feed.
I led the team, implemented the RAG component, integrated the application, and deployed the Streamlit app. Source history also supports deployment fixes, scoring-target redesign, advice logic, and documentation.
The ingestion, feature engineering, model, and interface work belong to the wider team system. My central technical story is how retrieval and application integration connect those components.
The runtime router uses explicit rules. Calling the application an autonomous agent would overstate how requests are dispatched.
Embeddings and Chroma retrieval bring relevant news into the language-model context. News can qualify numerical advice, but a retrieved report is still a source with its own date and uncertainty.
The model approximates a formula-derived expected-points score. The language layer explains player context around those scores. Neither step establishes a verified prediction of future match outcomes.
Application integration and deployment exposed practical dependency and configuration issues. I worked on deployment fixes and documentation alongside the RAG path, so the project could be explored through Streamlit.
The active saved model report covers 524 modeled players and 22 features. Its target is:
xP = points_per_90 × average_minutes_per_gameweek / 90 × fixture_ease_factor
The score is adjusted for availability and clipped to 0–15. Saved XGBoost results are MAE 0.2373 / R² 0.9376; Random Forest results are MAE 0.3440 / R² 0.8759. These measure approximation of that constructed target, not prediction of independently observed future gameweek points.
The report identifies imputation before the split and a random player split rather than temporal validation. An improvement would fit preprocessing only on training data and evaluate against genuinely future outcomes with time-aware splits.
Historical saved results; training and evaluation were not rerun for this portfolio. The original project was inspected read-only.
Choose a prepared question to inspect player context, source references, and an explanation. These are authored examples, not recovered historical model outputs.
Illustrative retrieval walkthrough. All players, scores, news notes, and answers below are authored synthetic fixtures. Dated April 2026 for historical context; no live AI or football advice.
Prepared score 6.2 / 15 · 74 average minutes
The player returned to team training. Selection for the next match is still uncertain.
A score is only one signal. This prepared example highlights uncertain minutes beside the scoring context; a return to training does not confirm a starting place.
In the original application: a rule-based router selects a path; retrieval supplies context to an LLM. This local example explains that boundary without executing it.
The documented Streamlit deployment redirects through Streamlit authentication in the launch check. Live application functionality is unverified; this embedded walkthrough is independent of that service.
Questions about the work, an engineering opportunity, or an idea to explore? I’d like to hear it.
Get in touch