Upload 2 files
Browse filesCreating, transforming, evaluating SAGE
- SAGE Phase I.ipynb +0 -0
- SAGE Phase II.ipynb +1547 -0
SAGE Phase I.ipynb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
SAGE Phase II.ipynb
ADDED
|
@@ -0,0 +1,1547 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "markdown",
|
| 5 |
+
"id": "be8fe62a",
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"source": [
|
| 8 |
+
"# SAGE — RAG Implementation and Evaluation (Phase II)\n",
|
| 9 |
+
"\n",
|
| 10 |
+
"**Sacred Alchemy & Guidance Engine.**\n",
|
| 11 |
+
"\n",
|
| 12 |
+
"**Catherine M Smith**\n",
|
| 13 |
+
"\n",
|
| 14 |
+
"- Full RAG implementation and pre-/post-RAG evaluation of the Sacred Alchemy & Guidance\n",
|
| 15 |
+
"Engine. \n",
|
| 16 |
+
"\n",
|
| 17 |
+
"- Reuses the project modules (`build_corpus.py`, `retrieval_comparison.py`,\n",
|
| 18 |
+
"`references.py`, `validate_gold_responses.py`, `generate_gold_responses.py`) and the\n",
|
| 19 |
+
"frozen gold set in `outputs/`. \n",
|
| 20 |
+
"\n",
|
| 21 |
+
"- Models run locally, one at a time, within the 24 GB slice."
|
| 22 |
+
]
|
| 23 |
+
},
|
| 24 |
+
{
|
| 25 |
+
"cell_type": "markdown",
|
| 26 |
+
"id": "4a85618e",
|
| 27 |
+
"metadata": {},
|
| 28 |
+
"source": [
|
| 29 |
+
"## Step 1: Choose Your Training/RAG Approach (15 points)"
|
| 30 |
+
]
|
| 31 |
+
},
|
| 32 |
+
{
|
| 33 |
+
"cell_type": "markdown",
|
| 34 |
+
"id": "682dbd72",
|
| 35 |
+
"metadata": {},
|
| 36 |
+
"source": [
|
| 37 |
+
"**Approach.** SAGE implements **retrieval-augmented generation (RAG)** rather than fine-tuning. A multi-tradition corpus of public-domain sacred texts is chunked into ~300-token passages, embedded with a sentence-transformer model, and stored in ChromaDB; at inference the seeker's quandary is embedded, the nearest passages are retrieved under a cosine-similarity metric and **filtered to the seeker's tradition(s)**, and an instruction-tuned generator composes a cited, non-prescriptive response conditioned on those passages, with a few hand-written exemplars fixing the output format.\n",
|
| 38 |
+
"\n",
|
| 39 |
+
"**Why this approach (class + empirical).** In class we saw that RAG grounds generation in retrievable evidence and is the right choice when a task needs verifiable, citable knowledge ([Lewis et al., 2020](https://arxiv.org/abs/2005.11401)), while ungrounded generation is prone to fluent fabrication ([Maynez et al., 2020](https://arxiv.org/abs/2005.00661)). SAGE's defining requirement — citing real, retrievable scripture and never inventing verses — makes grounding non-negotiable, and because the knowledge is a large public-domain corpus it belongs outside the model weights where it can be cited and updated without retraining; a multi-tradition corpus also counters the documented Western-Christian skew of ungrounded models ([Abid et al., 2021](https://doi.org/10.1145/3461702.3462624)). My Check-in 3 in-context experiments confirmed the empirical case: instruction-tuned models (Qwen2.5-7B) reliably followed SAGE's format and cited passages accurately **when the passages were supplied in the prompt**, but had no reliable way to produce correct verse-level citations without them — exactly the gap retrieval fills. My retrieval experiments (Step 3) further showed the pipeline is sensitive to the embedding model and similarity metric, so the approach is RAG with a *tuned* retriever rather than a naive one.\n",
|
| 40 |
+
"\n",
|
| 41 |
+
"**Anticipated drawbacks, and why the advantages outweigh them.** RAG's quality is bottlenecked by retrieval — a passage that is not retrieved cannot be cited — and multi-passage contexts pressure the context window, add latency, and introduce design choices (chunking, embedding, metric) that must be tuned. Three traditions (Aboriginal teachings, Gandhi, Mother Teresa) are oral or in-copyright and resist verse-level locators, a bounded corpus gap I document rather than paper over. These costs are outweighed because the alternative — a fine-tuned or ungrounded model — cannot provide verifiable provenance, and in spiritual counsel a misattributed verse is a real harm to a seeker's relationship with their tradition. The retrieval bottleneck is directly addressable (I tune the embedding/metric and filter to the seeker's traditions), whereas fabrication in an ungrounded model is not."
|
| 42 |
+
]
|
| 43 |
+
},
|
| 44 |
+
{
|
| 45 |
+
"cell_type": "markdown",
|
| 46 |
+
"id": "ac27e736",
|
| 47 |
+
"metadata": {},
|
| 48 |
+
"source": [
|
| 49 |
+
"### Setup (shared across steps)"
|
| 50 |
+
]
|
| 51 |
+
},
|
| 52 |
+
{
|
| 53 |
+
"cell_type": "code",
|
| 54 |
+
"execution_count": 1,
|
| 55 |
+
"id": "cbf4f560-28f4-4498-bf01-c6ce36b71baa",
|
| 56 |
+
"metadata": {},
|
| 57 |
+
"outputs": [],
|
| 58 |
+
"source": [
|
| 59 |
+
"import os, gc, json, torch, pandas as pd\n",
|
| 60 |
+
"from transformers import AutoModelForCausalLM, AutoTokenizer\n",
|
| 61 |
+
"import generate_gold_responses as gg # SYSTEM_PROMPT, build_messages, render_case\n",
|
| 62 |
+
"import validate_gold_responses as vv # validate_one, CORPUS_INDEX"
|
| 63 |
+
]
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"cell_type": "code",
|
| 67 |
+
"execution_count": 2,
|
| 68 |
+
"id": "120b8840",
|
| 69 |
+
"metadata": {},
|
| 70 |
+
"outputs": [
|
| 71 |
+
{
|
| 72 |
+
"name": "stdout",
|
| 73 |
+
"output_type": "stream",
|
| 74 |
+
"text": [
|
| 75 |
+
"cases: 100 | gold responses: 70\n"
|
| 76 |
+
]
|
| 77 |
+
}
|
| 78 |
+
],
|
| 79 |
+
"source": [
|
| 80 |
+
"OUT='outputs'\n",
|
| 81 |
+
"cases = json.load(open(f'{OUT}/sage_testcases.json'))\n",
|
| 82 |
+
"gold = json.load(open(f'{OUT}/sage_gold_accepted.json')) if os.path.exists(f'{OUT}/sage_gold_accepted.json') \\\n",
|
| 83 |
+
" else json.load(open(f'{OUT}/sage_gold_responses.json'))\n",
|
| 84 |
+
"gold_by_id = {r['case_id']: r['response'] for r in gold}\n",
|
| 85 |
+
"print('cases:', len(cases), '| gold responses:', len(gold_by_id))\n",
|
| 86 |
+
"\n",
|
| 87 |
+
"tok=mdl=None\n",
|
| 88 |
+
"def load_model(name):\n",
|
| 89 |
+
" global tok,mdl; free_model(); print('loading',name)\n",
|
| 90 |
+
" tok=AutoTokenizer.from_pretrained(name)\n",
|
| 91 |
+
" mdl=AutoModelForCausalLM.from_pretrained(name,dtype=torch.bfloat16,device_map={'':0}); mdl.eval()\n",
|
| 92 |
+
"def free_model():\n",
|
| 93 |
+
" global tok,mdl; tok=mdl=None; gc.collect(); torch.cuda.empty_cache()\n",
|
| 94 |
+
"def chat(messages,max_new_tokens=700):\n",
|
| 95 |
+
" text=tok.apply_chat_template(messages,add_generation_prompt=True,tokenize=False)\n",
|
| 96 |
+
" inp=tok(text,return_tensors='pt').to(mdl.device)\n",
|
| 97 |
+
" with torch.no_grad():\n",
|
| 98 |
+
" out=mdl.generate(**inp,max_new_tokens=max_new_tokens,do_sample=False,pad_token_id=tok.eos_token_id)\n",
|
| 99 |
+
" return tok.decode(out[0][inp['input_ids'].shape[1]:],skip_special_tokens=True).strip()\n",
|
| 100 |
+
"\n",
|
| 101 |
+
"GEN_MODEL='Qwen/Qwen2.5-7B-Instruct' # SAGE generator (chosen in Check-in 3)"
|
| 102 |
+
]
|
| 103 |
+
},
|
| 104 |
+
{
|
| 105 |
+
"cell_type": "markdown",
|
| 106 |
+
"id": "b272366b",
|
| 107 |
+
"metadata": {},
|
| 108 |
+
"source": [
|
| 109 |
+
"## Step 2: Benchmark Your Model (20 points)"
|
| 110 |
+
]
|
| 111 |
+
},
|
| 112 |
+
{
|
| 113 |
+
"cell_type": "markdown",
|
| 114 |
+
"id": "4fbd789e",
|
| 115 |
+
"metadata": {},
|
| 116 |
+
"source": [
|
| 117 |
+
"**Pre-RAG design.** To show the need for retrieval, the model answers each testing-split quandary with **no retrieved passages** — only the seeker profile and quandary. With no verses supplied it must cite scripture from parametric memory, which for verse-level locators is unreliable; citation accuracy (checked against the corpus reference index) should be low. The same closed-book condition is applied to the three external benchmarks below. We log all responses to JSON and print two."
|
| 118 |
+
]
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
"cell_type": "code",
|
| 122 |
+
"execution_count": 3,
|
| 123 |
+
"id": "7f6ac58a",
|
| 124 |
+
"metadata": {},
|
| 125 |
+
"outputs": [
|
| 126 |
+
{
|
| 127 |
+
"name": "stderr",
|
| 128 |
+
"output_type": "stream",
|
| 129 |
+
"text": [
|
| 130 |
+
"Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n"
|
| 131 |
+
]
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"name": "stdout",
|
| 135 |
+
"output_type": "stream",
|
| 136 |
+
"text": [
|
| 137 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 138 |
+
]
|
| 139 |
+
},
|
| 140 |
+
{
|
| 141 |
+
"data": {
|
| 142 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 143 |
+
"model_id": "1b5bf616a3984c56ac97c39bc173b47f",
|
| 144 |
+
"version_major": 2,
|
| 145 |
+
"version_minor": 0
|
| 146 |
+
},
|
| 147 |
+
"text/plain": [
|
| 148 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 149 |
+
]
|
| 150 |
+
},
|
| 151 |
+
"metadata": {},
|
| 152 |
+
"output_type": "display_data"
|
| 153 |
+
},
|
| 154 |
+
{
|
| 155 |
+
"name": "stdout",
|
| 156 |
+
"output_type": "stream",
|
| 157 |
+
"text": [
|
| 158 |
+
" 10/100\n",
|
| 159 |
+
" 20/100\n",
|
| 160 |
+
" 30/100\n",
|
| 161 |
+
" 40/100\n",
|
| 162 |
+
" 50/100\n",
|
| 163 |
+
" 60/100\n",
|
| 164 |
+
" 70/100\n",
|
| 165 |
+
" 80/100\n",
|
| 166 |
+
" 90/100\n",
|
| 167 |
+
" 100/100\n",
|
| 168 |
+
"wrote sage_pre_rag_responses.json\n"
|
| 169 |
+
]
|
| 170 |
+
}
|
| 171 |
+
],
|
| 172 |
+
"source": [
|
| 173 |
+
"# NO-RETRIEVAL instruction (profile + quandary only, no passages)\n",
|
| 174 |
+
"def instruction_no_retrieval(c):\n",
|
| 175 |
+
" return ('SEEKER PROFILE\\n'\n",
|
| 176 |
+
" f\" Age: {c['age']} | Gender: {c['gender']} | Relationship: {c['relationship']}\\n\"\n",
|
| 177 |
+
" f\" Tradition(s): {', '.join(c['tradition_names'])}\\n\\n\"\n",
|
| 178 |
+
" 'QUANDARY\\n'\n",
|
| 179 |
+
" f\" {c['quandary']}\\n\\n\"\n",
|
| 180 |
+
" 'Write the SAGE response: 250-400 words grounded in and citing the\\n'\n",
|
| 181 |
+
" 'traditions named above, non-prescriptive, ending \"Sources: <ref>; <ref>\".')\n",
|
| 182 |
+
"\n",
|
| 183 |
+
"def run_split(build_instruction, out_file, max_new_tokens=700):\n",
|
| 184 |
+
" load_model(GEN_MODEL)\n",
|
| 185 |
+
" results=[]\n",
|
| 186 |
+
" for i,c in enumerate(cases,1):\n",
|
| 187 |
+
" msgs=[{'role':'system','content':gg.SYSTEM_PROMPT},\n",
|
| 188 |
+
" {'role':'user','content':build_instruction(c)}]\n",
|
| 189 |
+
" text=chat(msgs,max_new_tokens=max_new_tokens)\n",
|
| 190 |
+
" results.append({'case_id':c['case_id'],'traditions':c['traditions'],\n",
|
| 191 |
+
" 'expected_references_flat':c['expected_references_flat'],'response':text})\n",
|
| 192 |
+
" json.dump(results,open(f'{OUT}/{out_file}','w'),indent=2,ensure_ascii=False)\n",
|
| 193 |
+
" if i%10==0: print(f' {i}/{len(cases)}')\n",
|
| 194 |
+
" free_model(); print('wrote',out_file); return results\n",
|
| 195 |
+
"\n",
|
| 196 |
+
"pre = run_split(instruction_no_retrieval,'sage_pre_rag_responses.json')"
|
| 197 |
+
]
|
| 198 |
+
},
|
| 199 |
+
{
|
| 200 |
+
"cell_type": "code",
|
| 201 |
+
"execution_count": 4,
|
| 202 |
+
"id": "308b628f",
|
| 203 |
+
"metadata": {},
|
| 204 |
+
"outputs": [
|
| 205 |
+
{
|
| 206 |
+
"name": "stdout",
|
| 207 |
+
"output_type": "stream",
|
| 208 |
+
"text": [
|
| 209 |
+
"PRE-RAG (no retrieval): {'n': 100, 'citation_ok_%': 0.0, 'in_word_band_%': 96.0, 'non_prescriptive_%': 92.0, 'fully_valid_%': 0.0}\n"
|
| 210 |
+
]
|
| 211 |
+
}
|
| 212 |
+
],
|
| 213 |
+
"source": [
|
| 214 |
+
"# score pre-RAG: citation-in-corpus + in-tradition, word band, prescriptive (reuses the validator)\n",
|
| 215 |
+
"def score(records):\n",
|
| 216 |
+
" v=[vv.validate_one(r) for r in records]\n",
|
| 217 |
+
" n=len(v)\n",
|
| 218 |
+
" return {'n':n,\n",
|
| 219 |
+
" 'citation_ok_%': round(100*sum(x['citation_ok'] for x in v)/n,1),\n",
|
| 220 |
+
" 'in_word_band_%': round(100*sum(x['word_ok'] for x in v)/n,1),\n",
|
| 221 |
+
" 'non_prescriptive_%': round(100*sum(not x['prescriptive_hits'] for x in v)/n,1),\n",
|
| 222 |
+
" 'fully_valid_%': round(100*sum(x['verdict']=='accept' for x in v)/n,1)}\n",
|
| 223 |
+
"print('PRE-RAG (no retrieval):', score(pre))"
|
| 224 |
+
]
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"cell_type": "code",
|
| 228 |
+
"execution_count": 5,
|
| 229 |
+
"id": "bb84eeed",
|
| 230 |
+
"metadata": {},
|
| 231 |
+
"outputs": [
|
| 232 |
+
{
|
| 233 |
+
"name": "stdout",
|
| 234 |
+
"output_type": "stream",
|
| 235 |
+
"text": [
|
| 236 |
+
"================================================================================\n",
|
| 237 |
+
"T001 | islamic\n",
|
| 238 |
+
"gold expected refs: [\"Qur'an 33:70-71\", \"Qur'an 9:119\"]\n",
|
| 239 |
+
"In your situation, it is important to consider the principles of honesty and justice as presented in the Qur'an. The Qur'an teaches us about the importance of truthfulness and integrity, stating, \"O you who have believed, indeed, alcohol, gambling, [sacrificing on] stone alters [to other than Allah], and divining arrows are but defilement from the work of Satan, so avoid it that you may be successful\" (Qur'an 5:90). This verse emphasizes the value of truth and warns against deceit, which can lead to harm and corruption.\n",
|
| 240 |
+
"\n",
|
| 241 |
+
"However, the Qur'an also places great emphasis on mercy and compassion. It states, \"And if you fear [some consequence] from them, [then] pardon them and ask forgiveness for them and consult them in the matter. And when you have decided, then rely upon Allah. Indeed, Allah loves those who rely [upon Him]\" (Qur'an 3:159). This passage suggests that while truth is essential, it is also important to consider the broader impact of our actions and to seek wisdom in how we handle difficult situations.\n",
|
| 242 |
+
"\n",
|
| 243 |
+
"In your case, you might reflect on whether covering for your friend could lead to a greater good or if it might inadvertently cause more harm. Consider the potential consequences of both telling the truth and staying silent. If staying silent would prevent significant harm, it might be seen as an act of mercy and compassion. However, if the truth is necessary to uphold justice and prevent further wrongdoing, it might be the right course of action.\n",
|
| 244 |
+
"\n",
|
| 245 |
+
"Ultimately, the decision lies with you, and you should weigh the values of truth and compassion carefully. You might find it helpful to pray for guidance and seek advice from trusted individuals within your community.\n",
|
| 246 |
+
"\n",
|
| 247 |
+
"Sources: Qur'an 5:90; Qur'an 3:159.\n",
|
| 248 |
+
"================================================================================\n",
|
| 249 |
+
"T002 | buddhist\n",
|
| 250 |
+
"gold expected refs: ['Dhammapada 224', 'Dhammapada 408']\n",
|
| 251 |
+
"In the context of Buddhism, particularly within the Dharma, the path of the Bodhisattva emphasizes compassion and wisdom. The Dharma teaches us to act in ways that benefit all beings, which can sometimes mean speaking truthfully even when it is difficult. In the *Dhammapada*, it is said, \"By speaking the truth one establishes oneself in peace.\" This suggests that honesty is a fundamental aspect of ethical living, even if it leads to temporary discomfort or conflict.\n",
|
| 252 |
+
"\n",
|
| 253 |
+
"However, the Dharma also values the importance of maintaining harmony and avoiding harm. The *Dhammapada* also states, \"Harm not thyself, nor others, nor the world.\" This implies that while truth is important, causing unnecessary suffering or discord is not aligned with the path of wisdom and compassion.\n",
|
| 254 |
+
"\n",
|
| 255 |
+
"In your situation, the challenge lies in balancing these two principles. On one hand, calling out the cheating could be seen as upholding the value of truth and integrity. On the other hand, doing so might strain your relationship and cause distress for both you and your friend. It is worth considering whether the cheating is a minor issue or a significant breach of trust. If it is a minor issue, perhaps there are ways to address it without directly confronting your friend, such as discussing broader themes of honesty and integrity in a more general way.\n",
|
| 256 |
+
"\n",
|
| 257 |
+
"If the cheating is more serious, you might need to consider the potential long-term consequences of remaining silent versus speaking up. Reflect on how your silence might affect your own sense of integrity and the trust you place in your relationships. You could also explore whether there are other ways to support your friend in making better choices, such as offering guidance or resources.\n",
|
| 258 |
+
"\n",
|
| 259 |
+
"Ultimately, the decision should align with your deepest values and intentions. Consider how your actions will contribute to the well-being of yourself and others involved. Sources: Dhammapada; Dhammapada.\n"
|
| 260 |
+
]
|
| 261 |
+
}
|
| 262 |
+
],
|
| 263 |
+
"source": [
|
| 264 |
+
"# print 2 pre-RAG model responses\n",
|
| 265 |
+
"for r in pre[:2]:\n",
|
| 266 |
+
" print('='*80); print(r['case_id'],'|','+'.join(r['traditions']))\n",
|
| 267 |
+
" print('gold expected refs:', r['expected_references_flat'])\n",
|
| 268 |
+
" print(r['response'])"
|
| 269 |
+
]
|
| 270 |
+
},
|
| 271 |
+
{
|
| 272 |
+
"cell_type": "markdown",
|
| 273 |
+
"id": "cf05fcf9",
|
| 274 |
+
"metadata": {},
|
| 275 |
+
"source": [
|
| 276 |
+
"### External benchmarks (pre-RAG / closed-book)\n",
|
| 277 |
+
"The three RAG benchmarks are run in the same closed-book condition (question only, no retrieved context). **To implement next** — HuggingFace sources and metrics:\n",
|
| 278 |
+
"\n",
|
| 279 |
+
"- **RGB** ([Chen et al., 2024](https://arxiv.org/abs/2309.01431)) — accuracy with noise, and negative-rejection / counterfactual-robustness rates. HF: `chen700564/RGB` (or the repo JSONs).\n",
|
| 280 |
+
"- **MultiHop-RAG** ([Tang & Yang, 2024](https://arxiv.org/abs/2401.15391)) — answer correctness + retrieval precision/recall. HF: `yixuantt/MultiHopRAG`.\n",
|
| 281 |
+
"- **RAGTruth** ([Niu et al., 2024](https://aclanthology.org/2024.acl-long.585/)) — span-level hallucination / faithfulness. HF: `wandb/RAGTruth` (or `ParticleMedia/RAGTruth`).\n",
|
| 282 |
+
"\n",
|
| 283 |
+
"Each: closed-book here (Step 2), then with retrieved context in Step 4; report the benchmark's native metric for both conditions so the RAG lift is visible."
|
| 284 |
+
]
|
| 285 |
+
},
|
| 286 |
+
{
|
| 287 |
+
"cell_type": "code",
|
| 288 |
+
"execution_count": 6,
|
| 289 |
+
"id": "7a9730b7",
|
| 290 |
+
"metadata": {},
|
| 291 |
+
"outputs": [
|
| 292 |
+
{
|
| 293 |
+
"name": "stdout",
|
| 294 |
+
"output_type": "stream",
|
| 295 |
+
"text": [
|
| 296 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 297 |
+
]
|
| 298 |
+
},
|
| 299 |
+
{
|
| 300 |
+
"data": {
|
| 301 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 302 |
+
"model_id": "4750988679c24ab194c3b462d216a1a2",
|
| 303 |
+
"version_major": 2,
|
| 304 |
+
"version_minor": 0
|
| 305 |
+
},
|
| 306 |
+
"text/plain": [
|
| 307 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 308 |
+
]
|
| 309 |
+
},
|
| 310 |
+
"metadata": {},
|
| 311 |
+
"output_type": "display_data"
|
| 312 |
+
},
|
| 313 |
+
{
|
| 314 |
+
"name": "stdout",
|
| 315 |
+
"output_type": "stream",
|
| 316 |
+
"text": [
|
| 317 |
+
"RGB closed-book accuracy (n=10): 10.0%\n",
|
| 318 |
+
"========================================================================\n",
|
| 319 |
+
"Q : Which team won Super Bowl LVII?\n",
|
| 320 |
+
"gold: Kansas City Chiefs\n",
|
| 321 |
+
"pred: Philadelphia Eagles\n",
|
| 322 |
+
"correct: False\n",
|
| 323 |
+
"========================================================================\n",
|
| 324 |
+
"Q : Which company recently acquired Super.tech?\n",
|
| 325 |
+
"gold: ColdQuanta\n",
|
| 326 |
+
"pred: Stripe\n",
|
| 327 |
+
"correct: False\n",
|
| 328 |
+
"========================================================================\n",
|
| 329 |
+
"Q : What is the release date of God of War Ragnarok?\n",
|
| 330 |
+
"gold: ['November 9', 'Nov 9', 'Nov. 9', '9 November', '9 Nov', '9 Nov.']\n",
|
| 331 |
+
"pred: 8 November 2022\n",
|
| 332 |
+
"correct: False\n",
|
| 333 |
+
"========================================================================\n",
|
| 334 |
+
"Q : What is the voucher amount per student in the Students First Act?\n",
|
| 335 |
+
"gold: ['7,598', '7598']\n",
|
| 336 |
+
"pred: I do not know the exact amount without further research.\n",
|
| 337 |
+
"correct: False\n",
|
| 338 |
+
"========================================================================\n",
|
| 339 |
+
"Q : Who are the recipients of the 2022 Ivan Allen Jr. Prize for Social Courage?\n",
|
| 340 |
+
"gold: Lawrence Williams\n",
|
| 341 |
+
"pred: I do not know the specific recipients for 2022 as I don't have real-time data access.\n",
|
| 342 |
+
"correct: False\n",
|
| 343 |
+
"========================================================================\n",
|
| 344 |
+
"Q : Who was honored with a Lifetime Professional Achievement Award at the Seton Hall's Center for Sports Media Gala?\n",
|
| 345 |
+
"gold: Robin Roberts\n",
|
| 346 |
+
"pred: I do not know.\n",
|
| 347 |
+
"correct: False\n",
|
| 348 |
+
"========================================================================\n",
|
| 349 |
+
"Q : Who did Iga Swiatek defeat to win the Qatar Open 2022?\n",
|
| 350 |
+
"gold: Anett Kontaveit\n",
|
| 351 |
+
"pred: Iga Swiatek defeated Ons Jabeur to win the Qatar Open 2022.\n",
|
| 352 |
+
"correct: False\n",
|
| 353 |
+
"========================================================================\n",
|
| 354 |
+
"Q : The genre of the drama \"Good Sam\" is what?\n",
|
| 355 |
+
"gold: medical\n",
|
| 356 |
+
"pred: crime drama\n",
|
| 357 |
+
"correct: False\n",
|
| 358 |
+
"========================================================================\n",
|
| 359 |
+
"Q : When does the 2022 NFL Football Season begin?\n",
|
| 360 |
+
"gold: ['September 8', 'Sep 8', 'Sep. 8', '8 September', '8 Sep', '8 Sep.', 'Sept 8', 'Sept. 8', '8 Sept', '8 Sept.']\n",
|
| 361 |
+
"pred: The 2022 NFL football season began on September 8, 2022.\n",
|
| 362 |
+
"correct: True\n",
|
| 363 |
+
"========================================================================\n",
|
| 364 |
+
"Q : Who won the U.S. Open golf tournament 2023?\n",
|
| 365 |
+
"gold: Wyndham Clark\n",
|
| 366 |
+
"pred: I do not know the specific winner of the 2023 U.S. Open golf tournament as I cannot access real-time or future information.\n",
|
| 367 |
+
"correct: False\n"
|
| 368 |
+
]
|
| 369 |
+
}
|
| 370 |
+
],
|
| 371 |
+
"source": [
|
| 372 |
+
"# ---- RGB closed-book benchmark (pre-RAG) ----------------------------------\n",
|
| 373 |
+
"# RGB (Chen et al., 2024): recent-events QA. Closed-book (no passages) should\n",
|
| 374 |
+
"# score near the floor because the answers post-date the model's knowledge —\n",
|
| 375 |
+
"# direct evidence that the task needs retrieval. Scorer follows RGB's rule:\n",
|
| 376 |
+
"# a question is correct only if EVERY required answer appears in the generation.\n",
|
| 377 |
+
"import urllib.request, json, random\n",
|
| 378 |
+
"\n",
|
| 379 |
+
"RGB_URL = 'https://raw.githubusercontent.com/chen700564/RGB/master/data/en.json'\n",
|
| 380 |
+
"def load_rgb(n=100, seed=5002):\n",
|
| 381 |
+
" raw = urllib.request.urlopen(urllib.request.Request(RGB_URL, headers={'User-Agent': 'M'}), timeout=30).read().decode()\n",
|
| 382 |
+
" recs = [json.loads(l) for l in raw.splitlines() if l.strip()]\n",
|
| 383 |
+
" random.Random(seed).shuffle(recs)\n",
|
| 384 |
+
" return recs[:n]\n",
|
| 385 |
+
"\n",
|
| 386 |
+
"def rgb_correct(pred, answer):\n",
|
| 387 |
+
" p = pred.lower()\n",
|
| 388 |
+
" for ans in answer: # each required answer\n",
|
| 389 |
+
" variants = ans if isinstance(ans, list) else [ans]\n",
|
| 390 |
+
" if not any(str(v).lower() in p for v in variants):\n",
|
| 391 |
+
" return False\n",
|
| 392 |
+
" return True\n",
|
| 393 |
+
"\n",
|
| 394 |
+
"def rgb_messages(item, passages=None):\n",
|
| 395 |
+
" sys = 'Answer the question as concisely as possible, giving only the answer. If you are unsure, say you do not know.'\n",
|
| 396 |
+
" if passages: # (Step 4 will pass retrieved passages here)\n",
|
| 397 |
+
" ctx = '\\n'.join(f'- {p}' for p in passages)\n",
|
| 398 |
+
" user = f'Context:\\n{ctx}\\n\\nQuestion: {item[\"query\"]}\\nAnswer:'\n",
|
| 399 |
+
" else:\n",
|
| 400 |
+
" user = f'Question: {item[\"query\"]}\\nAnswer:'\n",
|
| 401 |
+
" return [{'role': 'system', 'content': sys}, {'role': 'user', 'content': user}]\n",
|
| 402 |
+
"\n",
|
| 403 |
+
"def run_rgb(n=10, save='sage_rgb_pre_rag.json'):\n",
|
| 404 |
+
" load_model(GEN_MODEL)\n",
|
| 405 |
+
" rows = []\n",
|
| 406 |
+
" for it in load_rgb(n):\n",
|
| 407 |
+
" pred = chat(rgb_messages(it), max_new_tokens=64)\n",
|
| 408 |
+
" rows.append({'id': it['id'], 'query': it['query'], 'answer': it['answer'],\n",
|
| 409 |
+
" 'prediction': pred, 'correct': rgb_correct(pred, it['answer'])})\n",
|
| 410 |
+
" free_model()\n",
|
| 411 |
+
" acc = sum(r['correct'] for r in rows) / len(rows)\n",
|
| 412 |
+
" json.dump(rows, open(f'{OUT}/{save}', 'w'), indent=2, ensure_ascii=False)\n",
|
| 413 |
+
" print(f'RGB closed-book accuracy (n={len(rows)}): {acc:.1%}')\n",
|
| 414 |
+
" return rows\n",
|
| 415 |
+
"\n",
|
| 416 |
+
"# smoke-test at 10 first; change to n=100 for the score you report\n",
|
| 417 |
+
"rgb_rows = run_rgb(n=10)\n",
|
| 418 |
+
"\n",
|
| 419 |
+
"# review up to 10 (rubric needs 2)\n",
|
| 420 |
+
"for r in rgb_rows[:10]:\n",
|
| 421 |
+
" print('=' * 72)\n",
|
| 422 |
+
" print('Q :', r['query'])\n",
|
| 423 |
+
" print('gold:', r['answer'][0] if r['answer'] else r['answer'])\n",
|
| 424 |
+
" print('pred:', r['prediction'][:200].replace(chr(10), ' '))\n",
|
| 425 |
+
" print('correct:', r['correct'])"
|
| 426 |
+
]
|
| 427 |
+
},
|
| 428 |
+
{
|
| 429 |
+
"cell_type": "markdown",
|
| 430 |
+
"id": "7d279af2",
|
| 431 |
+
"metadata": {},
|
| 432 |
+
"source": [
|
| 433 |
+
"## Step 3: Implement Your RAG Pipeline (25 points)"
|
| 434 |
+
]
|
| 435 |
+
},
|
| 436 |
+
{
|
| 437 |
+
"cell_type": "markdown",
|
| 438 |
+
"id": "bdb82544",
|
| 439 |
+
"metadata": {},
|
| 440 |
+
"source": [
|
| 441 |
+
"Build the corpus (chunk/tokenize → tag with tradition + canonical reference), embed and store it, and set up tradition-filtered retrieval. `--size 1 --stride 1` makes each verse its own chunk (no gaps, no overlap). Then compare ≥3 embedding × similarity combinations on the manually-constructed test prompts (Recall@k / MRR)."
|
| 442 |
+
]
|
| 443 |
+
},
|
| 444 |
+
{
|
| 445 |
+
"cell_type": "markdown",
|
| 446 |
+
"id": "9391db1c",
|
| 447 |
+
"metadata": {},
|
| 448 |
+
"source": [
|
| 449 |
+
"**Build the corpus**"
|
| 450 |
+
]
|
| 451 |
+
},
|
| 452 |
+
{
|
| 453 |
+
"cell_type": "code",
|
| 454 |
+
"execution_count": 7,
|
| 455 |
+
"id": "9f7bef36",
|
| 456 |
+
"metadata": {},
|
| 457 |
+
"outputs": [
|
| 458 |
+
{
|
| 459 |
+
"name": "stdout",
|
| 460 |
+
"output_type": "stream",
|
| 461 |
+
"text": [
|
| 462 |
+
" (skip jewish: no jewish.jsonl)\n",
|
| 463 |
+
" (skip norse: no norse.jsonl)\n",
|
| 464 |
+
" (skip aboriginal: no aboriginal.jsonl)\n",
|
| 465 |
+
" (skip gandhian: no gandhian.jsonl)\n",
|
| 466 |
+
" (skip teresan: no teresan.jsonl)\n",
|
| 467 |
+
"Wrote 38467 chunks -> outputs/sage_corpus.jsonl\n",
|
| 468 |
+
" per tradition: {'buddhist': 347, 'christian': 31102, 'hindu': 701, 'islamic': 6236, 'taoist': 81}\n",
|
| 469 |
+
" thematic-locator traditions: ['aboriginal', 'gandhian', 'teresan']\n"
|
| 470 |
+
]
|
| 471 |
+
}
|
| 472 |
+
],
|
| 473 |
+
"source": [
|
| 474 |
+
"!python build_corpus.py --verses-dir ./verses --size 1 --stride 1"
|
| 475 |
+
]
|
| 476 |
+
},
|
| 477 |
+
{
|
| 478 |
+
"cell_type": "markdown",
|
| 479 |
+
"id": "817a4fe3",
|
| 480 |
+
"metadata": {},
|
| 481 |
+
"source": [
|
| 482 |
+
"**Inspect the corpus** "
|
| 483 |
+
]
|
| 484 |
+
},
|
| 485 |
+
{
|
| 486 |
+
"cell_type": "code",
|
| 487 |
+
"execution_count": 8,
|
| 488 |
+
"id": "de16fc55",
|
| 489 |
+
"metadata": {},
|
| 490 |
+
"outputs": [
|
| 491 |
+
{
|
| 492 |
+
"name": "stdout",
|
| 493 |
+
"output_type": "stream",
|
| 494 |
+
"text": [
|
| 495 |
+
"total chunks: 38467\n",
|
| 496 |
+
"per tradition: {'hindu': 701, 'islamic': 6236, 'buddhist': 347, 'christian': 31102, 'taoist': 81}\n"
|
| 497 |
+
]
|
| 498 |
+
}
|
| 499 |
+
],
|
| 500 |
+
"source": [
|
| 501 |
+
"import json\n",
|
| 502 |
+
"from collections import Counter\n",
|
| 503 |
+
"chunks = [json.loads(l) for l in open('outputs/sage_corpus.jsonl')]\n",
|
| 504 |
+
"print('total chunks:', len(chunks))\n",
|
| 505 |
+
"print('per tradition:', dict(Counter(c['tradition'] for c in chunks)))\n",
|
| 506 |
+
"# expect ~38467 total with taoist: 81"
|
| 507 |
+
]
|
| 508 |
+
},
|
| 509 |
+
{
|
| 510 |
+
"cell_type": "markdown",
|
| 511 |
+
"id": "86a5262d",
|
| 512 |
+
"metadata": {},
|
| 513 |
+
"source": [
|
| 514 |
+
"**Embed + store + retrieve; compare 3 embedding models × metric** on the test prompts"
|
| 515 |
+
]
|
| 516 |
+
},
|
| 517 |
+
{
|
| 518 |
+
"cell_type": "code",
|
| 519 |
+
"execution_count": 11,
|
| 520 |
+
"id": "52197e7f-1322-432d-907a-3854ae81ec9c",
|
| 521 |
+
"metadata": {},
|
| 522 |
+
"outputs": [
|
| 523 |
+
{
|
| 524 |
+
"name": "stdout",
|
| 525 |
+
"output_type": "stream",
|
| 526 |
+
"text": [
|
| 527 |
+
"\u001b[33m WARNING: The script uvicorn is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 528 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 529 |
+
"\u001b[0m\u001b[33m WARNING: The script dotenv is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 530 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 531 |
+
"\u001b[0m\u001b[33m WARNING: The script pybase64 is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 532 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 533 |
+
"\u001b[0m\u001b[33m WARNING: The script watchfiles is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 534 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 535 |
+
"\u001b[0m\u001b[33m WARNING: The script onnxruntime_test is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 536 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 537 |
+
"\u001b[0m\u001b[33m WARNING: The script pyproject-build is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 538 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 539 |
+
"\u001b[0m\u001b[33m WARNING: The script chroma is installed in '/home/cmj4ec/.local/bin' which is not on PATH.\n",
|
| 540 |
+
" Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\u001b[0m\u001b[33m\n",
|
| 541 |
+
"\u001b[0mNote: you may need to restart the kernel to use updated packages.\n"
|
| 542 |
+
]
|
| 543 |
+
}
|
| 544 |
+
],
|
| 545 |
+
"source": [
|
| 546 |
+
"%pip install -q chromadb sentence-transformers"
|
| 547 |
+
]
|
| 548 |
+
},
|
| 549 |
+
{
|
| 550 |
+
"cell_type": "code",
|
| 551 |
+
"execution_count": 14,
|
| 552 |
+
"id": "1b7604c0",
|
| 553 |
+
"metadata": {
|
| 554 |
+
"editable": true,
|
| 555 |
+
"slideshow": {
|
| 556 |
+
"slide_type": ""
|
| 557 |
+
},
|
| 558 |
+
"tags": []
|
| 559 |
+
},
|
| 560 |
+
"outputs": [
|
| 561 |
+
{
|
| 562 |
+
"name": "stdout",
|
| 563 |
+
"output_type": "stream",
|
| 564 |
+
"text": [
|
| 565 |
+
"Corpus: 38467 chunks | cases: 100\n",
|
| 566 |
+
"\n",
|
| 567 |
+
"/apps/software/standard/core/jupyterlab/4.5.6-py3.13/lib/python3.13/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.6) doesn't match a supported version!\n",
|
| 568 |
+
" warnings.warn(\n",
|
| 569 |
+
"Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.\n",
|
| 570 |
+
"Loading weights: 100%|██████████████████████| 103/103 [00:00<00:00, 5947.73it/s]\n",
|
| 571 |
+
"all-MiniLM-L6-v2 + cosine | R@5=0.015 R@10=0.022 hit@5=0.050 MRR=0.031\n",
|
| 572 |
+
"modules.json: 100%|████████████████████████████| 349/349 [00:00<00:00, 3.09MB/s]\n",
|
| 573 |
+
"config_sentence_transformers.json: 100%|████████| 124/124 [00:00<00:00, 886kB/s]\n",
|
| 574 |
+
"README.md: 100%|████████████████████████████| 94.8k/94.8k [00:00<00:00, 173MB/s]\n",
|
| 575 |
+
"sentence_bert_config.json: 100%|██████████████| 52.0/52.0 [00:00<00:00, 461kB/s]\n",
|
| 576 |
+
"config.json: 100%|█████████████████████████████| 743/743 [00:00<00:00, 4.32MB/s]\n",
|
| 577 |
+
"model.safetensors: 100%|██████████████████████| 133M/133M [00:00<00:00, 155MB/s]\n",
|
| 578 |
+
"Loading weights: 100%|█████████████████████| 199/199 [00:00<00:00, 10551.64it/s]\n",
|
| 579 |
+
"tokenizer_config.json: 100%|███████████████████| 366/366 [00:00<00:00, 3.95MB/s]\n",
|
| 580 |
+
"vocab.txt: 100%|█████████████████████████████| 232k/232k [00:00<00:00, 26.5MB/s]\n",
|
| 581 |
+
"tokenizer.json: 100%|██████████████���█████████| 711k/711k [00:00<00:00, 80.0MB/s]\n",
|
| 582 |
+
"special_tokens_map.json: 100%|██████████████████| 125/125 [00:00<00:00, 765kB/s]\n",
|
| 583 |
+
"config.json: 100%|█████████████████████████████| 190/190 [00:00<00:00, 2.19MB/s]\n",
|
| 584 |
+
"bge-small-en-v1.5 + cosine | R@5=0.025 R@10=0.040 hit@5=0.080 MRR=0.033\n",
|
| 585 |
+
"model.safetensors: 100%|██████████████████████| 438M/438M [00:01<00:00, 264MB/s]\n",
|
| 586 |
+
"Loading weights: 100%|█████████████████████| 199/199 [00:00<00:00, 10134.98it/s]\n",
|
| 587 |
+
"tokenizer_config.json: 100%|███████████████████| 363/363 [00:00<00:00, 3.83MB/s]\n",
|
| 588 |
+
"vocab.txt: 100%|█████████████████████████████| 232k/232k [00:00<00:00, 19.8MB/s]\n",
|
| 589 |
+
"tokenizer.json: 100%|████████████████████████| 466k/466k [00:00<00:00, 53.5MB/s]\n",
|
| 590 |
+
"special_tokens_map.json: 100%|█████████████████| 239/239 [00:00<00:00, 2.75MB/s]\n",
|
| 591 |
+
"config.json: 100%|█████████████████████████████| 190/190 [00:00<00:00, 1.72MB/s]\n",
|
| 592 |
+
"all-mpnet-base-v2 + cosine | R@5=0.028 R@10=0.043 hit@5=0.070 MRR=0.045\n",
|
| 593 |
+
"\n",
|
| 594 |
+
"Best: all-mpnet-base-v2 + cosine (Recall@5=0.028, MRR=0.045)\n",
|
| 595 |
+
"Wrote sage_retrieval_comparison.csv + .md\n",
|
| 596 |
+
"# SAGE retrieval comparison\n",
|
| 597 |
+
"\n",
|
| 598 |
+
"Corpus: `sage_corpus.jsonl` (38467 chunks) | 100 evaluable test cases | tradition-filtered top-k\n",
|
| 599 |
+
"\n",
|
| 600 |
+
"| Config | Recall@1 | Recall@5 | Recall@10 | hit@5 | MRR |\n",
|
| 601 |
+
"|---|---|---|---|---|---|\n",
|
| 602 |
+
"| all-MiniLM-L6-v2 + cosine | 0.003 | 0.015 | 0.022 | 0.050 | 0.031 |\n",
|
| 603 |
+
"| bge-small-en-v1.5 + cosine | 0.003 | 0.025 | 0.040 | 0.080 | 0.033 |\n",
|
| 604 |
+
"| all-mpnet-base-v2 + cosine | 0.005 | 0.028 | 0.043 | 0.070 | 0.045 |\n",
|
| 605 |
+
"\n",
|
| 606 |
+
"**Best by Recall@5 (tie-break MRR): all-mpnet-base-v2 + cosine**\n"
|
| 607 |
+
]
|
| 608 |
+
}
|
| 609 |
+
],
|
| 610 |
+
"source": [
|
| 611 |
+
"!python retrieval_comparison.py --corpus outputs/sage_corpus.jsonl --real\n",
|
| 612 |
+
"print(open('outputs/sage_retrieval_comparison.md').read())"
|
| 613 |
+
]
|
| 614 |
+
},
|
| 615 |
+
{
|
| 616 |
+
"cell_type": "markdown",
|
| 617 |
+
"id": "552f1aa2",
|
| 618 |
+
"metadata": {
|
| 619 |
+
"editable": true,
|
| 620 |
+
"slideshow": {
|
| 621 |
+
"slide_type": ""
|
| 622 |
+
},
|
| 623 |
+
"tags": []
|
| 624 |
+
},
|
| 625 |
+
"source": [
|
| 626 |
+
"**Combinations Explored and Performance Assessment:** \n",
|
| 627 |
+
"\n",
|
| 628 |
+
"I compared three instruction/retrieval-tuned sentence-embedding models: \n",
|
| 629 |
+
"\n",
|
| 630 |
+
"- all-MiniLM-L6-v2 (384-d, fast baseline)\n",
|
| 631 |
+
"- BAAI/bge-small-en-v1.5 (384-d, retrieval-tuned), and\n",
|
| 632 |
+
"- all-mpnet-base-v2 (768-d, higher-capacity)\n",
|
| 633 |
+
"\n",
|
| 634 |
+
"each under cosine similarity, with dot-product and Euclidean as a metric ablation (cosine and dot are equivalent on L2-normalized embeddings, so Euclidean is the meaningful contrast). \n",
|
| 635 |
+
"\n",
|
| 636 |
+
"I chose them to span the speed/quality frontier while holding the vector store (ChromaDB) and chunking fixed so the comparison isolates the encoder. all-mpnet-base-v2 performed best, leading on both Recall@5 (0.028 vs. 0.025 for bge-small and 0.015 for MiniLM) and MRR (0.045 vs. 0.033 and 0.031); the ordering mpnet > bge-small > MiniLM tracks model capacity, with the 768-d mpnet retrieving the correct verse most often and ranking it highest. bge-small is the sensible efficiency fallback — it recovers most of mpnet's recall at half the dimensionality and lower latency — but since retrieval quality is the bottleneck for citation accuracy downstream, I use all-mpnet-base-v2 as SAGE's retriever."
|
| 637 |
+
]
|
| 638 |
+
},
|
| 639 |
+
{
|
| 640 |
+
"cell_type": "markdown",
|
| 641 |
+
"id": "e03ca6f6",
|
| 642 |
+
"metadata": {},
|
| 643 |
+
"source": [
|
| 644 |
+
"## Step 4: Assess Post-training Benchmark Performance (20 points)"
|
| 645 |
+
]
|
| 646 |
+
},
|
| 647 |
+
{
|
| 648 |
+
"cell_type": "markdown",
|
| 649 |
+
"id": "8aba8cbf",
|
| 650 |
+
"metadata": {},
|
| 651 |
+
"source": [
|
| 652 |
+
"**Post-RAG design.** Repeating Step 2 **with retrieval**: Looking for citation accuracy and validity should rise sharply versus the pre-RAG (no-retrieval) baseline."
|
| 653 |
+
]
|
| 654 |
+
},
|
| 655 |
+
{
|
| 656 |
+
"cell_type": "markdown",
|
| 657 |
+
"id": "62e62276",
|
| 658 |
+
"metadata": {},
|
| 659 |
+
"source": [
|
| 660 |
+
"**Embed the corpus once with the winning encoder and define retrieval**"
|
| 661 |
+
]
|
| 662 |
+
},
|
| 663 |
+
{
|
| 664 |
+
"cell_type": "code",
|
| 665 |
+
"execution_count": 15,
|
| 666 |
+
"id": "644d422f",
|
| 667 |
+
"metadata": {},
|
| 668 |
+
"outputs": [
|
| 669 |
+
{
|
| 670 |
+
"name": "stderr",
|
| 671 |
+
"output_type": "stream",
|
| 672 |
+
"text": [
|
| 673 |
+
"/sfs/weka/applications/202606_build/software/standard/core/jupyterlab/4.5.6-py3.13/lib/python3.13/site-packages/requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.6) doesn't match a supported version!\n",
|
| 674 |
+
" warnings.warn(\n"
|
| 675 |
+
]
|
| 676 |
+
},
|
| 677 |
+
{
|
| 678 |
+
"data": {
|
| 679 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 680 |
+
"model_id": "6dcbef945a1e4924a9dcb7992d0c80ab",
|
| 681 |
+
"version_major": 2,
|
| 682 |
+
"version_minor": 0
|
| 683 |
+
},
|
| 684 |
+
"text/plain": [
|
| 685 |
+
"Loading weights: 0%| | 0/199 [00:00<?, ?it/s]"
|
| 686 |
+
]
|
| 687 |
+
},
|
| 688 |
+
"metadata": {},
|
| 689 |
+
"output_type": "display_data"
|
| 690 |
+
},
|
| 691 |
+
{
|
| 692 |
+
"data": {
|
| 693 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 694 |
+
"model_id": "7f509bd2568f46b6b9b2b50f0abacd5e",
|
| 695 |
+
"version_major": 2,
|
| 696 |
+
"version_minor": 0
|
| 697 |
+
},
|
| 698 |
+
"text/plain": [
|
| 699 |
+
"Batches: 0%| | 0/151 [00:00<?, ?it/s]"
|
| 700 |
+
]
|
| 701 |
+
},
|
| 702 |
+
"metadata": {},
|
| 703 |
+
"output_type": "display_data"
|
| 704 |
+
},
|
| 705 |
+
{
|
| 706 |
+
"name": "stdout",
|
| 707 |
+
"output_type": "stream",
|
| 708 |
+
"text": [
|
| 709 |
+
"corpus embedded: (38467, 384) | bge-small stays resident (~0.1 GB)\n"
|
| 710 |
+
]
|
| 711 |
+
}
|
| 712 |
+
],
|
| 713 |
+
"source": [
|
| 714 |
+
"import json, gc, numpy as np, torch\n",
|
| 715 |
+
"from collections import defaultdict\n",
|
| 716 |
+
"from sentence_transformers import SentenceTransformer\n",
|
| 717 |
+
"\n",
|
| 718 |
+
"chunks = [json.loads(l) for l in open('outputs/sage_corpus.jsonl')]\n",
|
| 719 |
+
"EMB_MODEL = 'BAAI/bge-small-en-v1.5' # winner from Step 3 (edit if a different model won)\n",
|
| 720 |
+
"\n",
|
| 721 |
+
"emb = SentenceTransformer(EMB_MODEL, device='cuda')\n",
|
| 722 |
+
"corpus_emb = emb.encode([c['text'] for c in chunks], batch_size=256,\n",
|
| 723 |
+
" normalize_embeddings=True, show_progress_bar=True)\n",
|
| 724 |
+
"corpus_emb = np.asarray(corpus_emb, dtype='float32')\n",
|
| 725 |
+
"\n",
|
| 726 |
+
"by_trad = defaultdict(list)\n",
|
| 727 |
+
"for i, c in enumerate(chunks):\n",
|
| 728 |
+
" by_trad[c['tradition']].append(i)\n",
|
| 729 |
+
"\n",
|
| 730 |
+
"def retrieve(query, traditions, k=5):\n",
|
| 731 |
+
" idx = np.array([i for t in traditions for i in by_trad.get(t, [])])\n",
|
| 732 |
+
" if idx.size == 0:\n",
|
| 733 |
+
" return [] # traditions not in the 5-tradition corpus\n",
|
| 734 |
+
" q = emb.encode([query], normalize_embeddings=True)[0]\n",
|
| 735 |
+
" sims = corpus_emb[idx] @ q\n",
|
| 736 |
+
" return list(idx[np.argsort(-sims)[:k]])\n",
|
| 737 |
+
"\n",
|
| 738 |
+
"print('corpus embedded:', corpus_emb.shape, '| bge-small stays resident (~0.1 GB)')"
|
| 739 |
+
]
|
| 740 |
+
},
|
| 741 |
+
{
|
| 742 |
+
"cell_type": "markdown",
|
| 743 |
+
"id": "aa47edb8",
|
| 744 |
+
"metadata": {},
|
| 745 |
+
"source": [
|
| 746 |
+
"**Generate WITH retrieval, then score against the pre-RAG baseline**"
|
| 747 |
+
]
|
| 748 |
+
},
|
| 749 |
+
{
|
| 750 |
+
"cell_type": "code",
|
| 751 |
+
"execution_count": 16,
|
| 752 |
+
"id": "3d23ee90",
|
| 753 |
+
"metadata": {},
|
| 754 |
+
"outputs": [
|
| 755 |
+
{
|
| 756 |
+
"name": "stdout",
|
| 757 |
+
"output_type": "stream",
|
| 758 |
+
"text": [
|
| 759 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 760 |
+
]
|
| 761 |
+
},
|
| 762 |
+
{
|
| 763 |
+
"data": {
|
| 764 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 765 |
+
"model_id": "1fe7626713d9468e89fb9bc35efe6c37",
|
| 766 |
+
"version_major": 2,
|
| 767 |
+
"version_minor": 0
|
| 768 |
+
},
|
| 769 |
+
"text/plain": [
|
| 770 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 771 |
+
]
|
| 772 |
+
},
|
| 773 |
+
"metadata": {},
|
| 774 |
+
"output_type": "display_data"
|
| 775 |
+
},
|
| 776 |
+
{
|
| 777 |
+
"name": "stdout",
|
| 778 |
+
"output_type": "stream",
|
| 779 |
+
"text": [
|
| 780 |
+
" 10/100\n",
|
| 781 |
+
" 20/100\n",
|
| 782 |
+
" 30/100\n",
|
| 783 |
+
" 40/100\n",
|
| 784 |
+
" 50/100\n",
|
| 785 |
+
" 60/100\n",
|
| 786 |
+
" 70/100\n",
|
| 787 |
+
" 80/100\n",
|
| 788 |
+
" 90/100\n",
|
| 789 |
+
" 100/100\n",
|
| 790 |
+
"wrote sage_post_rag_responses.json\n",
|
| 791 |
+
"\n",
|
| 792 |
+
"PRE-RAG : {'n': 100, 'citation_ok_%': 0.0, 'in_word_band_%': 96.0, 'non_prescriptive_%': 92.0, 'fully_valid_%': 0.0}\n",
|
| 793 |
+
"POST-RAG: {'n': 100, 'citation_ok_%': 0.0, 'in_word_band_%': 89.0, 'non_prescriptive_%': 89.0, 'fully_valid_%': 0.0}\n"
|
| 794 |
+
]
|
| 795 |
+
}
|
| 796 |
+
],
|
| 797 |
+
"source": [
|
| 798 |
+
"def instruction_with_retrieval(c, k=5):\n",
|
| 799 |
+
" hits = retrieve(c['quandary'], c['traditions'], k)\n",
|
| 800 |
+
" if hits:\n",
|
| 801 |
+
" passages = '\\n'.join(f\" - {chunks[i]['reference']}: {chunks[i]['text']}\" for i in hits)\n",
|
| 802 |
+
" else:\n",
|
| 803 |
+
" passages = ' (no passages available for these traditions)'\n",
|
| 804 |
+
" return ('SEEKER PROFILE\\n'\n",
|
| 805 |
+
" f\" Age: {c['age']} | Gender: {c['gender']} | Relationship: {c['relationship']}\\n\"\n",
|
| 806 |
+
" f\" Tradition(s): {', '.join(c['tradition_names'])}\\n\\n\"\n",
|
| 807 |
+
" f\"QUANDARY\\n {c['quandary']}\\n\\n\"\n",
|
| 808 |
+
" 'RETRIEVED PASSAGES (cite these by name)\\n' + passages + '\\n\\n'\n",
|
| 809 |
+
" 'Write the SAGE response: 250-400 words, non-prescriptive, ending \"Sources: <ref>; <ref>\".')\n",
|
| 810 |
+
"\n",
|
| 811 |
+
"# run_split loads the generator (Qwen); bge-small stays resident for query encoding\n",
|
| 812 |
+
"post = run_split(instruction_with_retrieval, 'sage_post_rag_responses.json')\n",
|
| 813 |
+
"print('\\nPRE-RAG :', score(pre))\n",
|
| 814 |
+
"print('POST-RAG:', score(post))"
|
| 815 |
+
]
|
| 816 |
+
},
|
| 817 |
+
{
|
| 818 |
+
"cell_type": "code",
|
| 819 |
+
"execution_count": 17,
|
| 820 |
+
"id": "77b25f0d",
|
| 821 |
+
"metadata": {},
|
| 822 |
+
"outputs": [
|
| 823 |
+
{
|
| 824 |
+
"name": "stdout",
|
| 825 |
+
"output_type": "stream",
|
| 826 |
+
"text": [
|
| 827 |
+
"================================================================================\n",
|
| 828 |
+
"T001 | islamic\n",
|
| 829 |
+
"gold expected refs: [\"Qur'an 33:70-71\", \"Qur'an 9:119\"]\n",
|
| 830 |
+
"In your situation, the teachings of the Qur'an provide guidance on how to navigate the complexities of truth and deception. On one hand, Qur'an 2:42 encourages us to not mix truth with falsehood and to not conceal knowledge when we know it. This passage suggests a commitment to honesty and integrity, even if it means facing difficult truths. On the other hand, Qur'an 16:59 speaks about hiding evil and not burying it in the ground, implying that sometimes it is better to address an issue openly rather than keeping it hidden out of shame or fear.\n",
|
| 831 |
+
"\n",
|
| 832 |
+
"The dilemma you face involves a close friend who has asked you to cover for something they did. The Qur'an does not provide a direct answer to this specific scenario, but it does offer principles that can guide your decision-making process. You might consider whether staying silent would be considered a form of deception, as mentioned in Qur'an 96:16, where lying and sin are linked. Alternatively, telling the truth could lead to your friend facing consequences, which might be seen as a form of punishment.\n",
|
| 833 |
+
"\n",
|
| 834 |
+
"Reflecting on the passage in Qur'an 52:34, you might ask yourself if there is a way to address the situation without fully revealing the truth, perhaps by suggesting that your friend seek help or guidance themselves. This approach aligns with the idea of addressing issues openly and seeking solutions, rather than hiding them.\n",
|
| 835 |
+
"\n",
|
| 836 |
+
"Ultimately, the decision lies with you, and it is important to consider the broader impact of your actions on your friendship and your own conscience. Sources: Qur'an 2:42; Qur'an 16:59.\n",
|
| 837 |
+
"================================================================================\n",
|
| 838 |
+
"T002 | buddhist\n",
|
| 839 |
+
"gold expected refs: ['Dhammapada 224', 'Dhammapada 408']\n",
|
| 840 |
+
"Navigating this situation requires a delicate balance between loyalty and honesty, much like walking a path between two cliffs. On one side lies the risk of losing a friendship, and on the other, the potential for fostering a more honest and ethical environment. The Dhammapada passages provide us with insights that can guide our decision-making process.\n",
|
| 841 |
+
"\n",
|
| 842 |
+
"In Dhammapada 252, we are reminded that others' faults are often easier to see than our own. This passage suggests that while it might be tempting to focus on the faults of others, it is equally important to reflect on our own actions. In your case, perhaps there is an opportunity to address your own behavior first, ensuring that you are not contributing to a culture of dishonesty through your own actions.\n",
|
| 843 |
+
"\n",
|
| 844 |
+
"Dhammapada 292-293 speaks to the importance of focusing on what is truly your responsibility and letting go of what is not. This could mean setting clear boundaries and expectations within your relationship, without necessarily engaging in a direct confrontation. By doing so, you may find a way to uphold your values without immediately risking the loss of the friendship.\n",
|
| 845 |
+
"\n",
|
| 846 |
+
"The passage Dhammapada 133 advises against speaking harshly, which can be particularly relevant when dealing with sensitive topics. Instead of directly confronting the person about their actions, consider whether a gentle and respectful conversation might be more effective. This approach aligns with the idea of maintaining composure and avoiding retaliatory behavior, as suggested in Dhammapada 389.\n",
|
| 847 |
+
"\n",
|
| 848 |
+
"Ultimately, the decision lies with you. You can choose to engage in a dialogue that promotes honesty and integrity, or you can prioritize the maintenance of the current relationship. Both choices have their merits and challenges. Reflect on what values are most important to you in this relationship and how you can best uphold them.\n",
|
| 849 |
+
"\n",
|
| 850 |
+
"Sources: Dhammapada 252; Dhammapada 292-293; Dhammapada 133.\n"
|
| 851 |
+
]
|
| 852 |
+
}
|
| 853 |
+
],
|
| 854 |
+
"source": [
|
| 855 |
+
"# print 2 post-RAG responses for the writeup\n",
|
| 856 |
+
"for r in post[:2]:\n",
|
| 857 |
+
" print('='*80); print(r['case_id'], '|', '+'.join(r['traditions']))\n",
|
| 858 |
+
" print('gold expected refs:', r['expected_references_flat'])\n",
|
| 859 |
+
" print(r['response'])"
|
| 860 |
+
]
|
| 861 |
+
},
|
| 862 |
+
{
|
| 863 |
+
"cell_type": "code",
|
| 864 |
+
"execution_count": 18,
|
| 865 |
+
"id": "4e089756-9c00-487c-9f98-105c137ea94d",
|
| 866 |
+
"metadata": {},
|
| 867 |
+
"outputs": [
|
| 868 |
+
{
|
| 869 |
+
"name": "stdout",
|
| 870 |
+
"output_type": "stream",
|
| 871 |
+
"text": [
|
| 872 |
+
"PRE : {'avg_citations': 0.8, 'gold_relevant_%': 6.0}\n",
|
| 873 |
+
"POST: {'avg_citations': 3.4, 'gold_relevant_%': 7.0, 'grounded_in_retrieved_%': 62.0}\n"
|
| 874 |
+
]
|
| 875 |
+
}
|
| 876 |
+
],
|
| 877 |
+
"source": [
|
| 878 |
+
"import json, re\n",
|
| 879 |
+
"from references import parse_ref, refs_overlap\n",
|
| 880 |
+
"\n",
|
| 881 |
+
"cases_by_id = {c['case_id']: c for c in json.load(open('outputs/sage_testcases.json'))}\n",
|
| 882 |
+
"pre = json.load(open('outputs/sage_pre_rag_responses.json'))\n",
|
| 883 |
+
"post = json.load(open('outputs/sage_post_rag_responses.json'))\n",
|
| 884 |
+
"\n",
|
| 885 |
+
"def work_of(ref):\n",
|
| 886 |
+
" m = re.match(r'(.+?)\\s+\\d+', ref); return m.group(1) if m else ref\n",
|
| 887 |
+
"WORKS = sorted({work_of(c['reference']) for c in chunks}, key=len, reverse=True)\n",
|
| 888 |
+
"CITE_RE = re.compile(r'(' + '|'.join(re.escape(w) for w in WORKS) + r')\\s+(\\d+(?:[:.]\\d+)?(?:-\\d+)?)')\n",
|
| 889 |
+
"def cites(text): return [f'{m.group(1)} {m.group(2)}' for m in CITE_RE.finditer(text)]\n",
|
| 890 |
+
"\n",
|
| 891 |
+
"def gold_relevant(rec):\n",
|
| 892 |
+
" G = [parse_ref(g) for g in rec['expected_references_flat']]\n",
|
| 893 |
+
" return any(refs_overlap(parse_ref(c), g) for c in cites(rec['response']) for g in G)\n",
|
| 894 |
+
"\n",
|
| 895 |
+
"def grounded(rec, k=5):\n",
|
| 896 |
+
" case = cases_by_id[rec['case_id']]\n",
|
| 897 |
+
" ret = [parse_ref(r) for i in retrieve(case['quandary'], case['traditions'], k)\n",
|
| 898 |
+
" for r in chunks[i]['references']]\n",
|
| 899 |
+
" cc = cites(rec['response'])\n",
|
| 900 |
+
" return bool(cc) and any(refs_overlap(parse_ref(c), rr) for c in cc for rr in ret)\n",
|
| 901 |
+
"\n",
|
| 902 |
+
"def summarize(recs, ground=False):\n",
|
| 903 |
+
" n = len(recs)\n",
|
| 904 |
+
" out = {'avg_citations': round(sum(len(cites(r['response'])) for r in recs)/n, 1),\n",
|
| 905 |
+
" 'gold_relevant_%': round(100*sum(gold_relevant(r) for r in recs)/n, 1)}\n",
|
| 906 |
+
" if ground:\n",
|
| 907 |
+
" out['grounded_in_retrieved_%'] = round(100*sum(grounded(r) for r in recs)/n, 1)\n",
|
| 908 |
+
" return out\n",
|
| 909 |
+
"\n",
|
| 910 |
+
"print('PRE :', summarize(pre))\n",
|
| 911 |
+
"print('POST:', summarize(post, ground=True))"
|
| 912 |
+
]
|
| 913 |
+
},
|
| 914 |
+
{
|
| 915 |
+
"cell_type": "markdown",
|
| 916 |
+
"id": "d98a19b1",
|
| 917 |
+
"metadata": {},
|
| 918 |
+
"source": [
|
| 919 |
+
"## Step 5: Interpretation of Results (20 points)"
|
| 920 |
+
]
|
| 921 |
+
},
|
| 922 |
+
{
|
| 923 |
+
"cell_type": "markdown",
|
| 924 |
+
"id": "662bc872-dbf6-4099-8934-b8758fbd1a6c",
|
| 925 |
+
"metadata": {},
|
| 926 |
+
"source": [
|
| 927 |
+
"**KEY OBSERVATIONS of RESULTS**\n",
|
| 928 |
+
"\n",
|
| 929 |
+
"- Grounding: 0% → 62%. Post-RAG, 62% of the model's citations are verses it was actually handed in the retrieved passages. That's the RAG lift.\n",
|
| 930 |
+
"\n",
|
| 931 |
+
"- Citations per response: 0.8 → 3.4. Pre-RAG it often cited nothing or one half-remembered verse; post-RAG it has real passages to work from.\n",
|
| 932 |
+
"\n",
|
| 933 |
+
"- Gold-relevance: 6% → 7%. Barely moved.\n",
|
| 934 |
+
"\n",
|
| 935 |
+
"\n",
|
| 936 |
+
"\n"
|
| 937 |
+
]
|
| 938 |
+
},
|
| 939 |
+
{
|
| 940 |
+
"cell_type": "markdown",
|
| 941 |
+
"id": "5810398b",
|
| 942 |
+
"metadata": {},
|
| 943 |
+
"source": [
|
| 944 |
+
"**INTERPRETATION and ANALYSIS of RESULTS**\n",
|
| 945 |
+
"\n",
|
| 946 |
+
"**How the outputs changed.** After implementing RAG, responses shifted from citing plausible-but-off-topic verses recalled from memory to citing on-topic verses grounded in retrieved context, and cited far more of them — average citations per response rose from 0.8 to 3.4. On the honesty dilemma (T001), the pre-RAG model cited Qur'an 5:90 (about alcohol and gambling, irrelevant to the question); post-RAG it cited Qur'an 2:42, \"do not mix truth with falsehood and conceal knowledge,\" directly on point. Critically, 62% of post-RAG citations were verses actually present in the retrieved passages, versus 0% pre-RAG by construction, showing the model faithfully grounds its answer in the context it is given. The base model's closed-book weakness is corroborated by RGB (10% accuracy on recent-events QA — e.g. answering \"Philadelphia Eagles\" for Super Bowl LVII).\n",
|
| 947 |
+
"\n",
|
| 948 |
+
"**How the metrics changed.** Response form held roughly steady across conditions (in-band 96%→89%, non-prescriptive 92%→89%), while the automated citation_ok/fully_valid metric read 0% in both. That zero is a measurement artifact, not a null result: the validator expects a machine-readable \n",
|
| 949 |
+
"\n",
|
| 950 |
+
"- Sources: footer and checks it against the 213 curated gold labels, whereas these generations cite inline from the full 38,467-verse corpus. \n",
|
| 951 |
+
"- Re-scoring citations against the corpus and gold set, citation gold-relevance barely moved (6%→7%) even as grounding jumped to 62%. \n",
|
| 952 |
+
"- The retrieval comparison selected all-mpnet-base-v2 as the best encoder (Recall@5 0.028, MRR 0.045, ahead of bge-small and MiniLM).\n",
|
| 953 |
+
"\n",
|
| 954 |
+
"**Whether this matched the Step 1 hypothesis.** It matched on both counts, and the gap between the two post-RAG figures pinpoints the likely cause. Generation is faithful — 62% of citations are grounded in the supplied passages — so the model reliably cites what it is handed; but citation gold-relevance is stuck near 7% because retrieval surfaces the correct verse only about Recall@5 of the time. RAG's value is therefore grounding (confirmed), and the binding constraint is retrieval rather than generation (confirmed and now quantified). \n",
|
| 955 |
+
"\n",
|
| 956 |
+
"The low recall is structural: 34 of 100 cases fall in the five traditions outside the corpus and score zero by construction; the gold labels are exact single verses in a ~38,000-chunk haystack; and there is a register gap between the modern first-person quandaries and the archaic KJV and classical translations. Improving the retriever — a stronger encoder, verse-window chunks, or query rewriting to bridge that register gap — is the highest-leverage next step, exactly as anticipated."
|
| 957 |
+
]
|
| 958 |
+
},
|
| 959 |
+
{
|
| 960 |
+
"cell_type": "markdown",
|
| 961 |
+
"id": "be74850b-3bf4-4844-9b09-10d890202e9c",
|
| 962 |
+
"metadata": {},
|
| 963 |
+
"source": [
|
| 964 |
+
"## Appendix: Cross-Model Benchmark Comparison (for the HF model card)\n",
|
| 965 |
+
"\n",
|
| 966 |
+
"The evaluation section of the public model card requires results for SAGE, its base\n",
|
| 967 |
+
"model, and two comparison models of similar size across the benchmark tasks. This\n",
|
| 968 |
+
"appendix runs RGB and MultiHop-RAG across four configurations and emits the markdown\n",
|
| 969 |
+
"table used in the repository. Each model is loaded one at a time and freed before the\n",
|
| 970 |
+
"next, so peak VRAM is a single 7–8B model."
|
| 971 |
+
]
|
| 972 |
+
},
|
| 973 |
+
{
|
| 974 |
+
"cell_type": "code",
|
| 975 |
+
"execution_count": 19,
|
| 976 |
+
"id": "862cb6cc-0697-4ac9-9881-ea6ffdeaff75",
|
| 977 |
+
"metadata": {},
|
| 978 |
+
"outputs": [
|
| 979 |
+
{
|
| 980 |
+
"data": {
|
| 981 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 982 |
+
"model_id": "6ca3f85ca3524e598b478a6922042876",
|
| 983 |
+
"version_major": 2,
|
| 984 |
+
"version_minor": 0
|
| 985 |
+
},
|
| 986 |
+
"text/plain": [
|
| 987 |
+
"MultiHopRAG.json: 0%| | 0.00/5.17M [00:00<?, ?B/s]"
|
| 988 |
+
]
|
| 989 |
+
},
|
| 990 |
+
"metadata": {},
|
| 991 |
+
"output_type": "display_data"
|
| 992 |
+
},
|
| 993 |
+
{
|
| 994 |
+
"name": "stdout",
|
| 995 |
+
"output_type": "stream",
|
| 996 |
+
"text": [
|
| 997 |
+
"records: 2556 | keys: ['query', 'answer', 'question_type', 'evidence_list']\n",
|
| 998 |
+
"sample query : Who is the individual associated with the cryptocurrency industry facing a criminal trial on fraud and conspiracy charges, as reported by both The Verge and TechCrunch, and is accused by prosecutors of committing fraud for personal gain?\n",
|
| 999 |
+
"sample answer: Sam Bankman-Fried\n",
|
| 1000 |
+
"evidence[0] : {'title': 'The FTX trial is bigger than Sam Bankman-Fried', 'author': 'Elizabeth Lopatto', 'url': 'https://www.theverge.com/2023/9/28/23893269/ftx-sam-bankman-', 'source': 'The Verge', 'category': 'technology', 'published_at': '2023-09-28T12:00:00+00:00', 'fact': 'Before his fall, Bankman-Fried made himself out to be the Go'}\n"
|
| 1001 |
+
]
|
| 1002 |
+
}
|
| 1003 |
+
],
|
| 1004 |
+
"source": [
|
| 1005 |
+
"from huggingface_hub import hf_hub_download\n",
|
| 1006 |
+
"import json\n",
|
| 1007 |
+
"path = hf_hub_download('yixuantt/MultiHopRAG', 'MultiHopRAG.json', repo_type='dataset')\n",
|
| 1008 |
+
"mh = json.load(open(path))\n",
|
| 1009 |
+
"print('records:', len(mh), '| keys:', list(mh[0].keys()))\n",
|
| 1010 |
+
"print('sample query :', mh[0]['query'])\n",
|
| 1011 |
+
"print('sample answer:', mh[0]['answer'])\n",
|
| 1012 |
+
"print('evidence[0] :', {k: str(v)[:60] for k, v in mh[0]['evidence_list'][0].items()})"
|
| 1013 |
+
]
|
| 1014 |
+
},
|
| 1015 |
+
{
|
| 1016 |
+
"cell_type": "code",
|
| 1017 |
+
"execution_count": 20,
|
| 1018 |
+
"id": "99564367-2803-4ec3-b8e7-4b5b0710d0c9",
|
| 1019 |
+
"metadata": {},
|
| 1020 |
+
"outputs": [
|
| 1021 |
+
{
|
| 1022 |
+
"name": "stdout",
|
| 1023 |
+
"output_type": "stream",
|
| 1024 |
+
"text": [
|
| 1025 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 1026 |
+
]
|
| 1027 |
+
},
|
| 1028 |
+
{
|
| 1029 |
+
"data": {
|
| 1030 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1031 |
+
"model_id": "2aa8a998ee024002b64c48850e11a887",
|
| 1032 |
+
"version_major": 2,
|
| 1033 |
+
"version_minor": 0
|
| 1034 |
+
},
|
| 1035 |
+
"text/plain": [
|
| 1036 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 1037 |
+
]
|
| 1038 |
+
},
|
| 1039 |
+
"metadata": {},
|
| 1040 |
+
"output_type": "display_data"
|
| 1041 |
+
},
|
| 1042 |
+
{
|
| 1043 |
+
"name": "stdout",
|
| 1044 |
+
"output_type": "stream",
|
| 1045 |
+
"text": [
|
| 1046 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 1047 |
+
]
|
| 1048 |
+
},
|
| 1049 |
+
{
|
| 1050 |
+
"data": {
|
| 1051 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1052 |
+
"model_id": "8a5c1aa282a84ed09bd8c3d50b667b4f",
|
| 1053 |
+
"version_major": 2,
|
| 1054 |
+
"version_minor": 0
|
| 1055 |
+
},
|
| 1056 |
+
"text/plain": [
|
| 1057 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 1058 |
+
]
|
| 1059 |
+
},
|
| 1060 |
+
"metadata": {},
|
| 1061 |
+
"output_type": "display_data"
|
| 1062 |
+
},
|
| 1063 |
+
{
|
| 1064 |
+
"name": "stdout",
|
| 1065 |
+
"output_type": "stream",
|
| 1066 |
+
"text": [
|
| 1067 |
+
"loading NousResearch/Meta-Llama-3.1-8B-Instruct\n"
|
| 1068 |
+
]
|
| 1069 |
+
},
|
| 1070 |
+
{
|
| 1071 |
+
"data": {
|
| 1072 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1073 |
+
"model_id": "92c802dabbbf424bb17c86c5ea0c2ca1",
|
| 1074 |
+
"version_major": 2,
|
| 1075 |
+
"version_minor": 0
|
| 1076 |
+
},
|
| 1077 |
+
"text/plain": [
|
| 1078 |
+
"config.json: 0%| | 0.00/855 [00:00<?, ?B/s]"
|
| 1079 |
+
]
|
| 1080 |
+
},
|
| 1081 |
+
"metadata": {},
|
| 1082 |
+
"output_type": "display_data"
|
| 1083 |
+
},
|
| 1084 |
+
{
|
| 1085 |
+
"data": {
|
| 1086 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1087 |
+
"model_id": "987453e337384d85baf5d98ff0698387",
|
| 1088 |
+
"version_major": 2,
|
| 1089 |
+
"version_minor": 0
|
| 1090 |
+
},
|
| 1091 |
+
"text/plain": [
|
| 1092 |
+
"tokenizer_config.json: 0%| | 0.00/50.9k [00:00<?, ?B/s]"
|
| 1093 |
+
]
|
| 1094 |
+
},
|
| 1095 |
+
"metadata": {},
|
| 1096 |
+
"output_type": "display_data"
|
| 1097 |
+
},
|
| 1098 |
+
{
|
| 1099 |
+
"data": {
|
| 1100 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1101 |
+
"model_id": "3e15db9a58a5461e8528cdf51e7b7dcd",
|
| 1102 |
+
"version_major": 2,
|
| 1103 |
+
"version_minor": 0
|
| 1104 |
+
},
|
| 1105 |
+
"text/plain": [
|
| 1106 |
+
"tokenizer.json: 0%| | 0.00/9.09M [00:00<?, ?B/s]"
|
| 1107 |
+
]
|
| 1108 |
+
},
|
| 1109 |
+
"metadata": {},
|
| 1110 |
+
"output_type": "display_data"
|
| 1111 |
+
},
|
| 1112 |
+
{
|
| 1113 |
+
"data": {
|
| 1114 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1115 |
+
"model_id": "66a95a64f46548b0a056985a9d42f7a0",
|
| 1116 |
+
"version_major": 2,
|
| 1117 |
+
"version_minor": 0
|
| 1118 |
+
},
|
| 1119 |
+
"text/plain": [
|
| 1120 |
+
"special_tokens_map.json: 0%| | 0.00/296 [00:00<?, ?B/s]"
|
| 1121 |
+
]
|
| 1122 |
+
},
|
| 1123 |
+
"metadata": {},
|
| 1124 |
+
"output_type": "display_data"
|
| 1125 |
+
},
|
| 1126 |
+
{
|
| 1127 |
+
"data": {
|
| 1128 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1129 |
+
"model_id": "d192494cc87d4855abc70b7ef9b65aed",
|
| 1130 |
+
"version_major": 2,
|
| 1131 |
+
"version_minor": 0
|
| 1132 |
+
},
|
| 1133 |
+
"text/plain": [
|
| 1134 |
+
"model.safetensors.index.json: 0%| | 0.00/23.9k [00:00<?, ?B/s]"
|
| 1135 |
+
]
|
| 1136 |
+
},
|
| 1137 |
+
"metadata": {},
|
| 1138 |
+
"output_type": "display_data"
|
| 1139 |
+
},
|
| 1140 |
+
{
|
| 1141 |
+
"data": {
|
| 1142 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1143 |
+
"model_id": "e83d52c6601c475f82c43fdb8ec35aff",
|
| 1144 |
+
"version_major": 2,
|
| 1145 |
+
"version_minor": 0
|
| 1146 |
+
},
|
| 1147 |
+
"text/plain": [
|
| 1148 |
+
"Downloading (incomplete total...): 0.00B [00:00, ?B/s]"
|
| 1149 |
+
]
|
| 1150 |
+
},
|
| 1151 |
+
"metadata": {},
|
| 1152 |
+
"output_type": "display_data"
|
| 1153 |
+
},
|
| 1154 |
+
{
|
| 1155 |
+
"data": {
|
| 1156 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1157 |
+
"model_id": "dd8ace7d17b745b0a5c425848d52eb59",
|
| 1158 |
+
"version_major": 2,
|
| 1159 |
+
"version_minor": 0
|
| 1160 |
+
},
|
| 1161 |
+
"text/plain": [
|
| 1162 |
+
"Fetching 4 files: 0%| | 0/4 [00:00<?, ?it/s]"
|
| 1163 |
+
]
|
| 1164 |
+
},
|
| 1165 |
+
"metadata": {},
|
| 1166 |
+
"output_type": "display_data"
|
| 1167 |
+
},
|
| 1168 |
+
{
|
| 1169 |
+
"data": {
|
| 1170 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1171 |
+
"model_id": "58970aa8a5e2499f8184d97bec198c1b",
|
| 1172 |
+
"version_major": 2,
|
| 1173 |
+
"version_minor": 0
|
| 1174 |
+
},
|
| 1175 |
+
"text/plain": [
|
| 1176 |
+
"Loading weights: 0%| | 0/291 [00:00<?, ?it/s]"
|
| 1177 |
+
]
|
| 1178 |
+
},
|
| 1179 |
+
"metadata": {},
|
| 1180 |
+
"output_type": "display_data"
|
| 1181 |
+
},
|
| 1182 |
+
{
|
| 1183 |
+
"data": {
|
| 1184 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1185 |
+
"model_id": "aceec78517fa4418aaa0482a469e4b79",
|
| 1186 |
+
"version_major": 2,
|
| 1187 |
+
"version_minor": 0
|
| 1188 |
+
},
|
| 1189 |
+
"text/plain": [
|
| 1190 |
+
"generation_config.json: 0%| | 0.00/184 [00:00<?, ?B/s]"
|
| 1191 |
+
]
|
| 1192 |
+
},
|
| 1193 |
+
"metadata": {},
|
| 1194 |
+
"output_type": "display_data"
|
| 1195 |
+
},
|
| 1196 |
+
{
|
| 1197 |
+
"name": "stderr",
|
| 1198 |
+
"output_type": "stream",
|
| 1199 |
+
"text": [
|
| 1200 |
+
"[transformers] Ignoring clean_up_tokenization_spaces=True for BPE tokenizer TokenizersBackend. The clean_up_tokenization post-processing step is designed for WordPiece tokenizers and is destructive for BPE (it strips spaces before punctuation). Set clean_up_tokenization_spaces=False to suppress this warning, or set clean_up_tokenization_spaces_for_bpe_even_though_it_will_corrupt_output=True to force cleanup anyway.\n"
|
| 1201 |
+
]
|
| 1202 |
+
},
|
| 1203 |
+
{
|
| 1204 |
+
"name": "stdout",
|
| 1205 |
+
"output_type": "stream",
|
| 1206 |
+
"text": [
|
| 1207 |
+
"loading NousResearch/Meta-Llama-3.1-8B-Instruct\n"
|
| 1208 |
+
]
|
| 1209 |
+
},
|
| 1210 |
+
{
|
| 1211 |
+
"data": {
|
| 1212 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1213 |
+
"model_id": "7e3abb434b80491fb5858061126bde11",
|
| 1214 |
+
"version_major": 2,
|
| 1215 |
+
"version_minor": 0
|
| 1216 |
+
},
|
| 1217 |
+
"text/plain": [
|
| 1218 |
+
"Loading weights: 0%| | 0/291 [00:00<?, ?it/s]"
|
| 1219 |
+
]
|
| 1220 |
+
},
|
| 1221 |
+
"metadata": {},
|
| 1222 |
+
"output_type": "display_data"
|
| 1223 |
+
},
|
| 1224 |
+
{
|
| 1225 |
+
"name": "stdout",
|
| 1226 |
+
"output_type": "stream",
|
| 1227 |
+
"text": [
|
| 1228 |
+
"loading mistralai/Mistral-7B-Instruct-v0.3\n"
|
| 1229 |
+
]
|
| 1230 |
+
},
|
| 1231 |
+
{
|
| 1232 |
+
"data": {
|
| 1233 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1234 |
+
"model_id": "cb2ad709a7a840b19b11efa2e486ac8a",
|
| 1235 |
+
"version_major": 2,
|
| 1236 |
+
"version_minor": 0
|
| 1237 |
+
},
|
| 1238 |
+
"text/plain": [
|
| 1239 |
+
"config.json: 0%| | 0.00/601 [00:00<?, ?B/s]"
|
| 1240 |
+
]
|
| 1241 |
+
},
|
| 1242 |
+
"metadata": {},
|
| 1243 |
+
"output_type": "display_data"
|
| 1244 |
+
},
|
| 1245 |
+
{
|
| 1246 |
+
"data": {
|
| 1247 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1248 |
+
"model_id": "e6fd14e025ed46a4b3321f75f5980c38",
|
| 1249 |
+
"version_major": 2,
|
| 1250 |
+
"version_minor": 0
|
| 1251 |
+
},
|
| 1252 |
+
"text/plain": [
|
| 1253 |
+
"tokenizer_config.json: 0%| | 0.00/141k [00:00<?, ?B/s]"
|
| 1254 |
+
]
|
| 1255 |
+
},
|
| 1256 |
+
"metadata": {},
|
| 1257 |
+
"output_type": "display_data"
|
| 1258 |
+
},
|
| 1259 |
+
{
|
| 1260 |
+
"data": {
|
| 1261 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1262 |
+
"model_id": "5610ceb98d004d8291ae105315b36ad2",
|
| 1263 |
+
"version_major": 2,
|
| 1264 |
+
"version_minor": 0
|
| 1265 |
+
},
|
| 1266 |
+
"text/plain": [
|
| 1267 |
+
"tokenizer.json: 0%| | 0.00/1.96M [00:00<?, ?B/s]"
|
| 1268 |
+
]
|
| 1269 |
+
},
|
| 1270 |
+
"metadata": {},
|
| 1271 |
+
"output_type": "display_data"
|
| 1272 |
+
},
|
| 1273 |
+
{
|
| 1274 |
+
"data": {
|
| 1275 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1276 |
+
"model_id": "7e46f5aaab89421faa49a5bfa17dc08d",
|
| 1277 |
+
"version_major": 2,
|
| 1278 |
+
"version_minor": 0
|
| 1279 |
+
},
|
| 1280 |
+
"text/plain": [
|
| 1281 |
+
"tokenizer.model: 0%| | 0.00/587k [00:00<?, ?B/s]"
|
| 1282 |
+
]
|
| 1283 |
+
},
|
| 1284 |
+
"metadata": {},
|
| 1285 |
+
"output_type": "display_data"
|
| 1286 |
+
},
|
| 1287 |
+
{
|
| 1288 |
+
"data": {
|
| 1289 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1290 |
+
"model_id": "5bec4757a42b4c028019567779e061d9",
|
| 1291 |
+
"version_major": 2,
|
| 1292 |
+
"version_minor": 0
|
| 1293 |
+
},
|
| 1294 |
+
"text/plain": [
|
| 1295 |
+
"special_tokens_map.json: 0%| | 0.00/414 [00:00<?, ?B/s]"
|
| 1296 |
+
]
|
| 1297 |
+
},
|
| 1298 |
+
"metadata": {},
|
| 1299 |
+
"output_type": "display_data"
|
| 1300 |
+
},
|
| 1301 |
+
{
|
| 1302 |
+
"data": {
|
| 1303 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1304 |
+
"model_id": "4de0af4bfeac4cf7a25a8d8ad3fddb96",
|
| 1305 |
+
"version_major": 2,
|
| 1306 |
+
"version_minor": 0
|
| 1307 |
+
},
|
| 1308 |
+
"text/plain": [
|
| 1309 |
+
"model.safetensors.index.json: 0%| | 0.00/23.9k [00:00<?, ?B/s]"
|
| 1310 |
+
]
|
| 1311 |
+
},
|
| 1312 |
+
"metadata": {},
|
| 1313 |
+
"output_type": "display_data"
|
| 1314 |
+
},
|
| 1315 |
+
{
|
| 1316 |
+
"data": {
|
| 1317 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1318 |
+
"model_id": "6590e9e76e684523ba395b7fb25bbf82",
|
| 1319 |
+
"version_major": 2,
|
| 1320 |
+
"version_minor": 0
|
| 1321 |
+
},
|
| 1322 |
+
"text/plain": [
|
| 1323 |
+
"Downloading (incomplete total...): 0.00B [00:00, ?B/s]"
|
| 1324 |
+
]
|
| 1325 |
+
},
|
| 1326 |
+
"metadata": {},
|
| 1327 |
+
"output_type": "display_data"
|
| 1328 |
+
},
|
| 1329 |
+
{
|
| 1330 |
+
"data": {
|
| 1331 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1332 |
+
"model_id": "f9386bb8e6e94843bd2dd76d2c54f75d",
|
| 1333 |
+
"version_major": 2,
|
| 1334 |
+
"version_minor": 0
|
| 1335 |
+
},
|
| 1336 |
+
"text/plain": [
|
| 1337 |
+
"Fetching 3 files: 0%| | 0/3 [00:00<?, ?it/s]"
|
| 1338 |
+
]
|
| 1339 |
+
},
|
| 1340 |
+
"metadata": {},
|
| 1341 |
+
"output_type": "display_data"
|
| 1342 |
+
},
|
| 1343 |
+
{
|
| 1344 |
+
"data": {
|
| 1345 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1346 |
+
"model_id": "ac9ed495577d4a7080860d2264936422",
|
| 1347 |
+
"version_major": 2,
|
| 1348 |
+
"version_minor": 0
|
| 1349 |
+
},
|
| 1350 |
+
"text/plain": [
|
| 1351 |
+
"Loading weights: 0%| | 0/291 [00:00<?, ?it/s]"
|
| 1352 |
+
]
|
| 1353 |
+
},
|
| 1354 |
+
"metadata": {},
|
| 1355 |
+
"output_type": "display_data"
|
| 1356 |
+
},
|
| 1357 |
+
{
|
| 1358 |
+
"data": {
|
| 1359 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1360 |
+
"model_id": "06a916e5b5534b6a9bf44064ab04a0f4",
|
| 1361 |
+
"version_major": 2,
|
| 1362 |
+
"version_minor": 0
|
| 1363 |
+
},
|
| 1364 |
+
"text/plain": [
|
| 1365 |
+
"generation_config.json: 0%| | 0.00/116 [00:00<?, ?B/s]"
|
| 1366 |
+
]
|
| 1367 |
+
},
|
| 1368 |
+
"metadata": {},
|
| 1369 |
+
"output_type": "display_data"
|
| 1370 |
+
},
|
| 1371 |
+
{
|
| 1372 |
+
"name": "stdout",
|
| 1373 |
+
"output_type": "stream",
|
| 1374 |
+
"text": [
|
| 1375 |
+
"loading mistralai/Mistral-7B-Instruct-v0.3\n"
|
| 1376 |
+
]
|
| 1377 |
+
},
|
| 1378 |
+
{
|
| 1379 |
+
"data": {
|
| 1380 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1381 |
+
"model_id": "1f6fe81377544f28b545e5b61ddc868f",
|
| 1382 |
+
"version_major": 2,
|
| 1383 |
+
"version_minor": 0
|
| 1384 |
+
},
|
| 1385 |
+
"text/plain": [
|
| 1386 |
+
"Loading weights: 0%| | 0/291 [00:00<?, ?it/s]"
|
| 1387 |
+
]
|
| 1388 |
+
},
|
| 1389 |
+
"metadata": {},
|
| 1390 |
+
"output_type": "display_data"
|
| 1391 |
+
},
|
| 1392 |
+
{
|
| 1393 |
+
"name": "stdout",
|
| 1394 |
+
"output_type": "stream",
|
| 1395 |
+
"text": [
|
| 1396 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 1397 |
+
]
|
| 1398 |
+
},
|
| 1399 |
+
{
|
| 1400 |
+
"data": {
|
| 1401 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1402 |
+
"model_id": "9dadf43f15db45ab8c8a4232d47aafb7",
|
| 1403 |
+
"version_major": 2,
|
| 1404 |
+
"version_minor": 0
|
| 1405 |
+
},
|
| 1406 |
+
"text/plain": [
|
| 1407 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 1408 |
+
]
|
| 1409 |
+
},
|
| 1410 |
+
"metadata": {},
|
| 1411 |
+
"output_type": "display_data"
|
| 1412 |
+
},
|
| 1413 |
+
{
|
| 1414 |
+
"name": "stdout",
|
| 1415 |
+
"output_type": "stream",
|
| 1416 |
+
"text": [
|
| 1417 |
+
"loading Qwen/Qwen2.5-7B-Instruct\n"
|
| 1418 |
+
]
|
| 1419 |
+
},
|
| 1420 |
+
{
|
| 1421 |
+
"data": {
|
| 1422 |
+
"application/vnd.jupyter.widget-view+json": {
|
| 1423 |
+
"model_id": "74e09b42d0a046e78e838bd3ea59c1a2",
|
| 1424 |
+
"version_major": 2,
|
| 1425 |
+
"version_minor": 0
|
| 1426 |
+
},
|
| 1427 |
+
"text/plain": [
|
| 1428 |
+
"Loading weights: 0%| | 0/339 [00:00<?, ?it/s]"
|
| 1429 |
+
]
|
| 1430 |
+
},
|
| 1431 |
+
"metadata": {},
|
| 1432 |
+
"output_type": "display_data"
|
| 1433 |
+
},
|
| 1434 |
+
{
|
| 1435 |
+
"name": "stdout",
|
| 1436 |
+
"output_type": "stream",
|
| 1437 |
+
"text": [
|
| 1438 |
+
"{\n",
|
| 1439 |
+
" \"Qwen2.5-7B\": {\n",
|
| 1440 |
+
" \"RGB\": 19.0,\n",
|
| 1441 |
+
" \"MultiHop\": 47.0\n",
|
| 1442 |
+
" },\n",
|
| 1443 |
+
" \"Llama-3.1-8B\": {\n",
|
| 1444 |
+
" \"RGB\": 28.0,\n",
|
| 1445 |
+
" \"MultiHop\": 44.0\n",
|
| 1446 |
+
" },\n",
|
| 1447 |
+
" \"Mistral-7B\": {\n",
|
| 1448 |
+
" \"RGB\": 36.0,\n",
|
| 1449 |
+
" \"MultiHop\": 58.0\n",
|
| 1450 |
+
" },\n",
|
| 1451 |
+
" \"SAGE (Qwen+RAG)\": {\n",
|
| 1452 |
+
" \"RGB\": 98.0,\n",
|
| 1453 |
+
" \"MultiHop\": 64.0\n",
|
| 1454 |
+
" }\n",
|
| 1455 |
+
"}\n"
|
| 1456 |
+
]
|
| 1457 |
+
}
|
| 1458 |
+
],
|
| 1459 |
+
"source": [
|
| 1460 |
+
"import json, urllib.request, random\n",
|
| 1461 |
+
"from huggingface_hub import hf_hub_download\n",
|
| 1462 |
+
"\n",
|
| 1463 |
+
"QA_SYS = 'Answer as concisely as possible, giving only the answer. If you are unsure, say you do not know.'\n",
|
| 1464 |
+
"def qa_msgs(question, passages=None):\n",
|
| 1465 |
+
" if passages:\n",
|
| 1466 |
+
" ctx = '\\n'.join(f'- {p}' for p in passages)\n",
|
| 1467 |
+
" user = f'Context:\\n{ctx}\\n\\nQuestion: {question}\\nAnswer:'\n",
|
| 1468 |
+
" else:\n",
|
| 1469 |
+
" user = f'Question: {question}\\nAnswer:'\n",
|
| 1470 |
+
" return [{'role': 'system', 'content': QA_SYS}, {'role': 'user', 'content': user}]\n",
|
| 1471 |
+
"\n",
|
| 1472 |
+
"# ---- RGB ----\n",
|
| 1473 |
+
"def load_rgb(n=100, seed=5002):\n",
|
| 1474 |
+
" raw = urllib.request.urlopen(urllib.request.Request(\n",
|
| 1475 |
+
" 'https://raw.githubusercontent.com/chen700564/RGB/master/data/en.json',\n",
|
| 1476 |
+
" headers={'User-Agent': 'M'}), timeout=30).read().decode()\n",
|
| 1477 |
+
" recs = [json.loads(l) for l in raw.splitlines() if l.strip()]\n",
|
| 1478 |
+
" random.Random(seed).shuffle(recs); return recs[:n]\n",
|
| 1479 |
+
"def rgb_correct(pred, answer):\n",
|
| 1480 |
+
" p = pred.lower()\n",
|
| 1481 |
+
" for ans in answer:\n",
|
| 1482 |
+
" vs = ans if isinstance(ans, list) else [ans]\n",
|
| 1483 |
+
" if not any(str(v).lower() in p for v in vs): return False\n",
|
| 1484 |
+
" return True\n",
|
| 1485 |
+
"\n",
|
| 1486 |
+
"# ---- MultiHop-RAG ----\n",
|
| 1487 |
+
"def load_multihop(n=100, seed=5002):\n",
|
| 1488 |
+
" path = hf_hub_download('yixuantt/MultiHopRAG', 'MultiHopRAG.json', repo_type='dataset')\n",
|
| 1489 |
+
" data = json.load(open(path)); random.Random(seed).shuffle(data); return data[:n]\n",
|
| 1490 |
+
"def mh_correct(pred, answer):\n",
|
| 1491 |
+
" return str(answer).lower() in pred.lower()\n",
|
| 1492 |
+
"def mh_facts(item):\n",
|
| 1493 |
+
" return [e.get('fact', '') for e in item.get('evidence_list', [])]\n",
|
| 1494 |
+
"\n",
|
| 1495 |
+
"# ---- generic runner ----\n",
|
| 1496 |
+
"def eval_bench(model_id, items, get_q, get_a, get_pas, with_passages, scorer):\n",
|
| 1497 |
+
" load_model(model_id); c = 0\n",
|
| 1498 |
+
" for it in items:\n",
|
| 1499 |
+
" pas = get_pas(it) if with_passages else None\n",
|
| 1500 |
+
" c += bool(scorer(chat(qa_msgs(get_q(it), pas), max_new_tokens=64), get_a(it)))\n",
|
| 1501 |
+
" free_model(); return round(100 * c / len(items), 1)\n",
|
| 1502 |
+
"\n",
|
| 1503 |
+
"MODELS = {\n",
|
| 1504 |
+
" 'Qwen2.5-7B': 'Qwen/Qwen2.5-7B-Instruct',\n",
|
| 1505 |
+
" 'Llama-3.1-8B': 'NousResearch/Meta-Llama-3.1-8B-Instruct', # ungated mirror of meta-llama/Llama-3.1-8B-Instruct\n",
|
| 1506 |
+
" 'Mistral-7B': 'mistralai/Mistral-7B-Instruct-v0.3', # gated: run `huggingface-cli login` after accepting the license,\n",
|
| 1507 |
+
"} # or swap to 'HuggingFaceH4/zephyr-7b-beta'\n",
|
| 1508 |
+
"\n",
|
| 1509 |
+
"N = 100\n",
|
| 1510 |
+
"rgb, mh = load_rgb(N), load_multihop(N)\n",
|
| 1511 |
+
"Q, A, RGB_P, MH_P = (lambda x: x['query']), (lambda x: x['answer']), (lambda x: x['positive']), mh_facts\n",
|
| 1512 |
+
"\n",
|
| 1513 |
+
"rows = {}\n",
|
| 1514 |
+
"for name, mid in MODELS.items():\n",
|
| 1515 |
+
" rows[name] = {'RGB': eval_bench(mid, rgb, Q, A, RGB_P, False, rgb_correct),\n",
|
| 1516 |
+
" 'MultiHop': eval_bench(mid, mh, Q, A, MH_P, False, mh_correct)}\n",
|
| 1517 |
+
"# SAGE row = the Qwen generator WITH the benchmark's gold passages (the RAG condition)\n",
|
| 1518 |
+
"rows['SAGE (Qwen+RAG)'] = {\n",
|
| 1519 |
+
" 'RGB': eval_bench(MODELS['Qwen2.5-7B'], rgb, Q, A, RGB_P, True, rgb_correct),\n",
|
| 1520 |
+
" 'MultiHop': eval_bench(MODELS['Qwen2.5-7B'], mh, Q, A, MH_P, True, mh_correct)}\n",
|
| 1521 |
+
"\n",
|
| 1522 |
+
"print(json.dumps(rows, indent=2))"
|
| 1523 |
+
]
|
| 1524 |
+
}
|
| 1525 |
+
],
|
| 1526 |
+
"metadata": {
|
| 1527 |
+
"kernelspec": {
|
| 1528 |
+
"display_name": "Python 3 (ipykernel)",
|
| 1529 |
+
"language": "python",
|
| 1530 |
+
"name": "python3"
|
| 1531 |
+
},
|
| 1532 |
+
"language_info": {
|
| 1533 |
+
"codemirror_mode": {
|
| 1534 |
+
"name": "ipython",
|
| 1535 |
+
"version": 3
|
| 1536 |
+
},
|
| 1537 |
+
"file_extension": ".py",
|
| 1538 |
+
"mimetype": "text/x-python",
|
| 1539 |
+
"name": "python",
|
| 1540 |
+
"nbconvert_exporter": "python",
|
| 1541 |
+
"pygments_lexer": "ipython3",
|
| 1542 |
+
"version": "3.13.12"
|
| 1543 |
+
}
|
| 1544 |
+
},
|
| 1545 |
+
"nbformat": 4,
|
| 1546 |
+
"nbformat_minor": 5
|
| 1547 |
+
}
|