Spaces:
Running
Running
Upload 14 files
Browse files- App.css +38 -0
- App.js +77 -0
- App.test.js +8 -0
- README.md +6 -5
- app.py +760 -0
- gitattributes +35 -0
- index.css +13 -0
- index.js +17 -0
- logo.svg +1 -0
- model_functions.py +688 -0
- package.json +39 -0
- reportWebVitals.js +13 -0
- requirements.txt +11 -0
- setupTests.js +5 -0
App.css
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.App {
|
| 2 |
+
text-align: center;
|
| 3 |
+
}
|
| 4 |
+
|
| 5 |
+
.App-logo {
|
| 6 |
+
height: 40vmin;
|
| 7 |
+
pointer-events: none;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
@media (prefers-reduced-motion: no-preference) {
|
| 11 |
+
.App-logo {
|
| 12 |
+
animation: App-logo-spin infinite 20s linear;
|
| 13 |
+
}
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
.App-header {
|
| 17 |
+
background-color: #282c34;
|
| 18 |
+
min-height: 100vh;
|
| 19 |
+
display: flex;
|
| 20 |
+
flex-direction: column;
|
| 21 |
+
align-items: center;
|
| 22 |
+
justify-content: center;
|
| 23 |
+
font-size: calc(10px + 2vmin);
|
| 24 |
+
color: white;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
.App-link {
|
| 28 |
+
color: #61dafb;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
@keyframes App-logo-spin {
|
| 32 |
+
from {
|
| 33 |
+
transform: rotate(0deg);
|
| 34 |
+
}
|
| 35 |
+
to {
|
| 36 |
+
transform: rotate(360deg);
|
| 37 |
+
}
|
| 38 |
+
}
|
App.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React, { useState } from 'react';
|
| 2 |
+
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
|
| 3 |
+
import { Slider } from '@/components/ui/slider';
|
| 4 |
+
|
| 5 |
+
const ModelComparisonInterface = () => {
|
| 6 |
+
const [temperature, setTemperature] = useState(0.7);
|
| 7 |
+
const [input, setInput] = useState('');
|
| 8 |
+
const [outputs, setOutputs] = useState({
|
| 9 |
+
model1: '',
|
| 10 |
+
model2: ''
|
| 11 |
+
});
|
| 12 |
+
|
| 13 |
+
return (
|
| 14 |
+
<div className="w-full max-w-4xl p-4">
|
| 15 |
+
<Card className="mb-4">
|
| 16 |
+
<CardHeader>
|
| 17 |
+
<CardTitle>Language Model Comparison</CardTitle>
|
| 18 |
+
</CardHeader>
|
| 19 |
+
<CardContent>
|
| 20 |
+
<div className="space-y-4">
|
| 21 |
+
<div>
|
| 22 |
+
<label className="block text-sm font-medium mb-2">
|
| 23 |
+
Input Text
|
| 24 |
+
</label>
|
| 25 |
+
<textarea
|
| 26 |
+
className="w-full h-32 p-2 border rounded"
|
| 27 |
+
value={input}
|
| 28 |
+
onChange={(e) => setInput(e.target.value)}
|
| 29 |
+
placeholder="Enter your text here..."
|
| 30 |
+
/>
|
| 31 |
+
</div>
|
| 32 |
+
|
| 33 |
+
<div>
|
| 34 |
+
<label className="block text-sm font-medium mb-2">
|
| 35 |
+
Temperature: {temperature}
|
| 36 |
+
</label>
|
| 37 |
+
<Slider
|
| 38 |
+
value={[temperature]}
|
| 39 |
+
onValueChange={(value) => setTemperature(value[0])}
|
| 40 |
+
min={0}
|
| 41 |
+
max={1}
|
| 42 |
+
step={0.1}
|
| 43 |
+
className="w-full"
|
| 44 |
+
/>
|
| 45 |
+
</div>
|
| 46 |
+
|
| 47 |
+
<div className="grid grid-cols-2 gap-4">
|
| 48 |
+
<Card>
|
| 49 |
+
<CardHeader>
|
| 50 |
+
<CardTitle>Model 1 Output</CardTitle>
|
| 51 |
+
</CardHeader>
|
| 52 |
+
<CardContent>
|
| 53 |
+
<div className="min-h-32 p-2 border rounded bg-gray-50">
|
| 54 |
+
{outputs.model1 || 'Output will appear here...'}
|
| 55 |
+
</div>
|
| 56 |
+
</CardContent>
|
| 57 |
+
</Card>
|
| 58 |
+
|
| 59 |
+
<Card>
|
| 60 |
+
<CardHeader>
|
| 61 |
+
<CardTitle>Model 2 Output</CardTitle>
|
| 62 |
+
</CardHeader>
|
| 63 |
+
<CardContent>
|
| 64 |
+
<div className="min-h-32 p-2 border rounded bg-gray-50">
|
| 65 |
+
{outputs.model2 || 'Output will appear here...'}
|
| 66 |
+
</div>
|
| 67 |
+
</CardContent>
|
| 68 |
+
</Card>
|
| 69 |
+
</div>
|
| 70 |
+
</div>
|
| 71 |
+
</CardContent>
|
| 72 |
+
</Card>
|
| 73 |
+
</div>
|
| 74 |
+
);
|
| 75 |
+
};
|
| 76 |
+
|
| 77 |
+
export default ModelComparisonInterface;
|
App.test.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { render, screen } from '@testing-library/react';
|
| 2 |
+
import App from './App';
|
| 3 |
+
|
| 4 |
+
test('renders learn react link', () => {
|
| 5 |
+
render(<App />);
|
| 6 |
+
const linkElement = screen.getByText(/learn react/i);
|
| 7 |
+
expect(linkElement).toBeInTheDocument();
|
| 8 |
+
});
|
README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
| 1 |
---
|
| 2 |
-
title: IS41720
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: 5.
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 1 |
---
|
| 2 |
+
title: IS41720 Zone
|
| 3 |
+
emoji: 📉
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: blue
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 5.13.2
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
+
short_description: An interactive space for university students
|
| 11 |
---
|
| 12 |
|
| 13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import openai
|
| 4 |
+
import PyPDF2
|
| 5 |
+
import numpy as np
|
| 6 |
+
import math
|
| 7 |
+
|
| 8 |
+
MODEL_STATUS = {
|
| 9 |
+
'tiktoken': False,
|
| 10 |
+
'transformers': False,
|
| 11 |
+
'torch': False,
|
| 12 |
+
'model_loaded': False,
|
| 13 |
+
'error_messages': []
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
try:
|
| 17 |
+
import tiktoken
|
| 18 |
+
gpt_tokenizer = tiktoken.get_encoding("gpt2")
|
| 19 |
+
MODEL_STATUS['tiktoken'] = True
|
| 20 |
+
except Exception as e:
|
| 21 |
+
MODEL_STATUS['error_messages'].append(f"tiktoken error: {str(e)}")
|
| 22 |
+
gpt_tokenizer = None
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
from transformers import AutoTokenizer, AutoModel
|
| 26 |
+
import torch
|
| 27 |
+
MODEL_STATUS['transformers'] = True
|
| 28 |
+
MODEL_STATUS['torch'] = True
|
| 29 |
+
|
| 30 |
+
# Load lightweight model
|
| 31 |
+
print("Loading model...")
|
| 32 |
+
tokenizer = AutoTokenizer.from_pretrained("prajjwal1/bert-tiny")
|
| 33 |
+
model = AutoModel.from_pretrained("prajjwal1/bert-tiny")
|
| 34 |
+
|
| 35 |
+
MODEL_STATUS['model_loaded'] = True
|
| 36 |
+
print("model loaded successfully!")
|
| 37 |
+
|
| 38 |
+
except Exception as e:
|
| 39 |
+
MODEL_STATUS['error_messages'].append(f"Model loading error: {str(e)}")
|
| 40 |
+
tokenizer = None
|
| 41 |
+
model = None
|
| 42 |
+
|
| 43 |
+
# OpenAI setup
|
| 44 |
+
OPENAI_API_KEY = os.getenv("openAI_TOKEN")
|
| 45 |
+
if OPENAI_API_KEY:
|
| 46 |
+
openai.api_key = OPENAI_API_KEY
|
| 47 |
+
else:
|
| 48 |
+
MODEL_STATUS['error_messages'].append("OpenAI API key not found")
|
| 49 |
+
|
| 50 |
+
import shutil
|
| 51 |
+
import os
|
| 52 |
+
|
| 53 |
+
cache_dir = os.path.expanduser("~/.cache/huggingface")
|
| 54 |
+
if os.path.exists(cache_dir):
|
| 55 |
+
try:
|
| 56 |
+
total_size = sum(
|
| 57 |
+
os.path.getsize(os.path.join(dirpath, filename))
|
| 58 |
+
for dirpath, dirnames, filenames in os.walk(cache_dir)
|
| 59 |
+
for filename in filenames
|
| 60 |
+
) / (1024**3)
|
| 61 |
+
|
| 62 |
+
if total_size > 40:
|
| 63 |
+
shutil.rmtree(cache_dir)
|
| 64 |
+
print(f"Cleared {total_size:.2f}GB cache")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Cache cleanup error: {e}")
|
| 67 |
+
|
| 68 |
+
from model_functions import *
|
| 69 |
+
|
| 70 |
+
def tokenize_text(text):
|
| 71 |
+
if not text.strip():
|
| 72 |
+
return [], 0, "Enter some text to see tokenization"
|
| 73 |
+
|
| 74 |
+
if gpt_tokenizer:
|
| 75 |
+
try:
|
| 76 |
+
tokens = gpt_tokenizer.encode(text)
|
| 77 |
+
token_strings = []
|
| 78 |
+
for token in tokens:
|
| 79 |
+
try:
|
| 80 |
+
decoded = gpt_tokenizer.decode([token])
|
| 81 |
+
token_strings.append(decoded)
|
| 82 |
+
except UnicodeDecodeError:
|
| 83 |
+
token_strings.append(f"<token_{token}>")
|
| 84 |
+
return token_strings, len(tokens), f"Text tokenized successfully → {len(tokens)} tokens"
|
| 85 |
+
except Exception as e:
|
| 86 |
+
return [], 0, f"Tokenization error: {str(e)}"
|
| 87 |
+
else:
|
| 88 |
+
# Fallback: simple whitespace tokenization
|
| 89 |
+
tokens = text.split()
|
| 90 |
+
return tokens, len(tokens), f"Using fallback tokenization → {len(tokens)} tokens (tiktoken unavailable)"
|
| 91 |
+
|
| 92 |
+
def get_next_token_predictions(text):
|
| 93 |
+
"""Get next token predictions using OpenAI API"""
|
| 94 |
+
if not text.strip():
|
| 95 |
+
return "Enter some text to see predictions"
|
| 96 |
+
|
| 97 |
+
if not OPENAI_API_KEY:
|
| 98 |
+
return "OpenAI API key not available - cannot generate predictions"
|
| 99 |
+
|
| 100 |
+
try:
|
| 101 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 102 |
+
response = client.chat.completions.create(
|
| 103 |
+
model="gpt-3.5-turbo",
|
| 104 |
+
messages=[
|
| 105 |
+
{"role": "system", "content": "Complete the following text with the next most likely word. Provide exactly 3 options with their approximate probabilities."},
|
| 106 |
+
{"role": "user", "content": f"Text: '{text}'\n\nNext word options:"}
|
| 107 |
+
],
|
| 108 |
+
temperature=0.1,
|
| 109 |
+
max_tokens=50
|
| 110 |
+
)
|
| 111 |
+
return response.choices[0].message.content
|
| 112 |
+
except Exception as e:
|
| 113 |
+
return f"Error getting predictions: {str(e)}"
|
| 114 |
+
|
| 115 |
+
def merge_subword_tokens(tokens, attention_matrix):
|
| 116 |
+
"""Merge subword tokens back into words for cleaner viz"""
|
| 117 |
+
merged_tokens = []
|
| 118 |
+
merged_attention = []
|
| 119 |
+
current_word = ""
|
| 120 |
+
current_indices = []
|
| 121 |
+
|
| 122 |
+
for i, token in enumerate(tokens):
|
| 123 |
+
if token.startswith('##'):
|
| 124 |
+
current_word += token[2:]
|
| 125 |
+
current_indices.append(i)
|
| 126 |
+
else:
|
| 127 |
+
if current_word:
|
| 128 |
+
merged_tokens.append(current_word)
|
| 129 |
+
merged_attention.append(current_indices)
|
| 130 |
+
current_word = token
|
| 131 |
+
current_indices = [i]
|
| 132 |
+
|
| 133 |
+
if current_word:
|
| 134 |
+
merged_tokens.append(current_word)
|
| 135 |
+
merged_attention.append(current_indices)
|
| 136 |
+
|
| 137 |
+
# Merge attention weights by averaging
|
| 138 |
+
merged_matrix = np.zeros((len(merged_tokens), len(merged_tokens)))
|
| 139 |
+
for i, i_indices in enumerate(merged_attention):
|
| 140 |
+
for j, j_indices in enumerate(merged_attention):
|
| 141 |
+
# Average attention between word groups
|
| 142 |
+
weights = []
|
| 143 |
+
for ii in i_indices:
|
| 144 |
+
for jj in j_indices:
|
| 145 |
+
if ii < attention_matrix.shape[0] and jj < attention_matrix.shape[1]:
|
| 146 |
+
weights.append(attention_matrix[ii, jj])
|
| 147 |
+
if weights:
|
| 148 |
+
merged_matrix[i, j] = np.mean(weights)
|
| 149 |
+
|
| 150 |
+
return merged_tokens, merged_matrix
|
| 151 |
+
|
| 152 |
+
def create_attention_network_svg(text):
|
| 153 |
+
if not text.strip():
|
| 154 |
+
return "Enter text to see attention network"
|
| 155 |
+
|
| 156 |
+
if not MODEL_STATUS['model_loaded']:
|
| 157 |
+
return f"Attention model not available. Errors: {MODEL_STATUS['error_messages']}"
|
| 158 |
+
|
| 159 |
+
try:
|
| 160 |
+
# Tokenize input
|
| 161 |
+
inputs = tokenizer(text, return_tensors="pt", truncation=True, max_length=64)
|
| 162 |
+
tokens = tokenizer.convert_ids_to_tokens(inputs["input_ids"][0])
|
| 163 |
+
|
| 164 |
+
with torch.no_grad():
|
| 165 |
+
outputs = model(**inputs, output_attentions=True)
|
| 166 |
+
|
| 167 |
+
# Remove special tokens
|
| 168 |
+
clean_tokens = []
|
| 169 |
+
clean_indices = []
|
| 170 |
+
for i, token in enumerate(tokens):
|
| 171 |
+
if token not in ['[CLS]', '[SEP]', '[PAD]']:
|
| 172 |
+
clean_tokens.append(token)
|
| 173 |
+
clean_indices.append(i)
|
| 174 |
+
|
| 175 |
+
if len(clean_indices) < 2:
|
| 176 |
+
return "Need at least 2 valid tokens for attention visualisation."
|
| 177 |
+
|
| 178 |
+
# SEARCH for best head: max variance
|
| 179 |
+
best_attention = None
|
| 180 |
+
best_name = ""
|
| 181 |
+
best_tokens = []
|
| 182 |
+
best_variance = -1
|
| 183 |
+
|
| 184 |
+
debug_info = f"Total Layers: {len(outputs.attentions)}\n"
|
| 185 |
+
|
| 186 |
+
for layer_idx, layer_att in enumerate(outputs.attentions):
|
| 187 |
+
num_heads = layer_att.shape[1]
|
| 188 |
+
for head_idx in range(num_heads):
|
| 189 |
+
attn_matrix = layer_att[0, head_idx].numpy()
|
| 190 |
+
trimmed_attention = attn_matrix[np.ix_(clean_indices, clean_indices)]
|
| 191 |
+
variance = np.var(trimmed_attention)
|
| 192 |
+
|
| 193 |
+
debug_info += f"Layer {layer_idx}, Head {head_idx} — Variance: {variance:.5f}\n"
|
| 194 |
+
|
| 195 |
+
if variance > best_variance:
|
| 196 |
+
best_attention = trimmed_attention
|
| 197 |
+
best_name = f"Layer {layer_idx}, Head {head_idx}"
|
| 198 |
+
best_tokens = clean_tokens
|
| 199 |
+
best_variance = variance
|
| 200 |
+
|
| 201 |
+
if best_attention is None:
|
| 202 |
+
return "Could not extract valid attention."
|
| 203 |
+
|
| 204 |
+
# Merge subwords
|
| 205 |
+
merged_tokens, merged_attention = merge_subword_tokens(best_tokens, best_attention)
|
| 206 |
+
n_tokens = len(merged_tokens)
|
| 207 |
+
|
| 208 |
+
if n_tokens < 2:
|
| 209 |
+
return "Too few tokens after merging for attention graph."
|
| 210 |
+
|
| 211 |
+
# SVG dimensions
|
| 212 |
+
width, height = 1000, 500
|
| 213 |
+
margin = 50
|
| 214 |
+
|
| 215 |
+
# Linear positions
|
| 216 |
+
positions = []
|
| 217 |
+
for i in range(n_tokens):
|
| 218 |
+
x = margin + (width - 2*margin) * i / (n_tokens - 1)
|
| 219 |
+
y = height // 2
|
| 220 |
+
positions.append((x, y))
|
| 221 |
+
|
| 222 |
+
# Start SVG
|
| 223 |
+
svg = f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">'
|
| 224 |
+
svg += '<style>.token-text { font-family: Arial; font-size: 14px; text-anchor: middle; font-weight: bold; }'
|
| 225 |
+
svg += '.debug-text { font-family: monospace; font-size: 10px; fill: #666; }</style>'
|
| 226 |
+
|
| 227 |
+
# Choose top-N attention connections
|
| 228 |
+
num_top_connections = 20
|
| 229 |
+
pairs = []
|
| 230 |
+
for i in range(n_tokens):
|
| 231 |
+
for j in range(n_tokens):
|
| 232 |
+
if i != j:
|
| 233 |
+
pairs.append((merged_attention[i, j], i, j))
|
| 234 |
+
pairs.sort(reverse=True)
|
| 235 |
+
top_pairs = pairs[:num_top_connections]
|
| 236 |
+
|
| 237 |
+
# Draw attention arcs
|
| 238 |
+
for weight, i, j in top_pairs:
|
| 239 |
+
x1, y1 = positions[i]
|
| 240 |
+
x2, y2 = positions[j]
|
| 241 |
+
mid_x = (x1 + x2) / 2
|
| 242 |
+
curve_y = y1 - 80 if (i + j) % 2 == 0 else y1 + 80
|
| 243 |
+
|
| 244 |
+
# Color coding
|
| 245 |
+
if weight > 0.08:
|
| 246 |
+
color = "#d32f2f" # red
|
| 247 |
+
opacity = "0.8"
|
| 248 |
+
elif weight > 0.04:
|
| 249 |
+
color = "#ff9800" # orange
|
| 250 |
+
opacity = "0.6"
|
| 251 |
+
else:
|
| 252 |
+
color = "#2196f3" # blue
|
| 253 |
+
opacity = "0.4"
|
| 254 |
+
|
| 255 |
+
thickness = max(2, weight * 10)
|
| 256 |
+
|
| 257 |
+
svg += f'<path d="M {x1},{y1} Q {mid_x},{curve_y} {x2},{y2}" '
|
| 258 |
+
svg += f'stroke="{color}" stroke-width="{thickness}" fill="none" opacity="{opacity}"/>'
|
| 259 |
+
|
| 260 |
+
# Draw nodes
|
| 261 |
+
for i, (token, (x, y)) in enumerate(zip(merged_tokens, positions)):
|
| 262 |
+
svg += f'<circle cx="{x}" cy="{y}" r="25" fill="white" stroke="black" stroke-width="2"/>'
|
| 263 |
+
svg += f'<text x="{x}" y="{y+5}" class="token-text">{token[:10]}</text>'
|
| 264 |
+
|
| 265 |
+
# Legend and info
|
| 266 |
+
svg += f'<text x="20" y="{height - 130}" style="font-family: Arial; font-size: 16px; font-weight: bold;">'
|
| 267 |
+
svg += f'Attention Network - {best_name}</text>'
|
| 268 |
+
svg += f'<text x="20" y="{height - 110}" style="font-family: Arial; font-size: 12px;">'
|
| 269 |
+
svg += f'Red: Strong | Orange: Medium | Blue: Weak | Showing top {num_top_connections} connections</text>'
|
| 270 |
+
|
| 271 |
+
# Debug info (limited lines)
|
| 272 |
+
for i, line in enumerate(debug_info.split('\n')[:8]):
|
| 273 |
+
svg += f'<text x="20" y="{height - 90 + 12*i}" class="debug-text">{line}</text>'
|
| 274 |
+
|
| 275 |
+
svg += '</svg>'
|
| 276 |
+
|
| 277 |
+
return svg
|
| 278 |
+
|
| 279 |
+
except Exception as e:
|
| 280 |
+
return f"Error generating attention network: {str(e)}"
|
| 281 |
+
|
| 282 |
+
|
| 283 |
+
with gr.Blocks() as demo:
|
| 284 |
+
gr.Markdown("# Language Models & Methods Lab Interface")
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
with gr.Tabs() as tabs:
|
| 288 |
+
|
| 289 |
+
# Week 3 Tab
|
| 290 |
+
with gr.Tab("Week 3: Text Processing"):
|
| 291 |
+
gr.Markdown("# How Language Models Process Text")
|
| 292 |
+
gr.Markdown("Explore tokenization, context windows, and attention mechanisms")
|
| 293 |
+
|
| 294 |
+
with gr.Tabs() as week3_tabs:
|
| 295 |
+
with gr.Tab("Tokenization Explorer"):
|
| 296 |
+
gr.Markdown("### See how text gets broken into tokens")
|
| 297 |
+
|
| 298 |
+
with gr.Row():
|
| 299 |
+
token_input = gr.Textbox(
|
| 300 |
+
label="Enter your text",
|
| 301 |
+
placeholder="Type any text to see how it gets tokenized...",
|
| 302 |
+
lines=3,
|
| 303 |
+
value="The quick brown fox jumps over the lazy dog."
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
with gr.Row():
|
| 307 |
+
tokenize_btn = gr.Button("Tokenize Text")
|
| 308 |
+
|
| 309 |
+
with gr.Row():
|
| 310 |
+
token_display = gr.Textbox(label="Tokens", lines=3, interactive=False)
|
| 311 |
+
token_count = gr.Number(label="Token Count", interactive=False)
|
| 312 |
+
|
| 313 |
+
with gr.Row():
|
| 314 |
+
token_info = gr.Textbox(label="Tokenization Info", lines=2, interactive=False)
|
| 315 |
+
|
| 316 |
+
with gr.Tab("Context & Predictions"):
|
| 317 |
+
gr.Markdown("### Next-word predictions and context understanding")
|
| 318 |
+
|
| 319 |
+
with gr.Row():
|
| 320 |
+
context_input = gr.Textbox(
|
| 321 |
+
label="Enter incomplete text",
|
| 322 |
+
placeholder="I went to the bank to",
|
| 323 |
+
lines=2,
|
| 324 |
+
value="I went to the bank to"
|
| 325 |
+
)
|
| 326 |
+
|
| 327 |
+
with gr.Row():
|
| 328 |
+
predict_btn = gr.Button("Get Next Word Predictions")
|
| 329 |
+
|
| 330 |
+
with gr.Row():
|
| 331 |
+
predictions_output = gr.Textbox(label="Most Likely Next Words", lines=5, interactive=False)
|
| 332 |
+
|
| 333 |
+
with gr.Row():
|
| 334 |
+
context_window_info = gr.Textbox(
|
| 335 |
+
label="Context Window Status",
|
| 336 |
+
value="Click 'Get Predictions' to see token usage",
|
| 337 |
+
interactive=False
|
| 338 |
+
)
|
| 339 |
+
|
| 340 |
+
with gr.Tab("Attention Network"):
|
| 341 |
+
gr.Markdown("### Network visualisation of attention patterns")
|
| 342 |
+
gr.Markdown("See how words connect to each other through attention mechanisms")
|
| 343 |
+
|
| 344 |
+
with gr.Row():
|
| 345 |
+
attention_input = gr.Textbox(
|
| 346 |
+
label="Enter a sentence (shorter sentences work better)",
|
| 347 |
+
placeholder="The bank was closed.",
|
| 348 |
+
lines=2,
|
| 349 |
+
value="The bank was closed."
|
| 350 |
+
)
|
| 351 |
+
|
| 352 |
+
with gr.Row():
|
| 353 |
+
analyze_attention_btn = gr.Button("Generate Attention Network")
|
| 354 |
+
|
| 355 |
+
with gr.Row():
|
| 356 |
+
attention_network = gr.HTML(label="Attention Network Visualisation")
|
| 357 |
+
|
| 358 |
+
# Week 3 Event Handlers
|
| 359 |
+
def update_tokenization(text):
|
| 360 |
+
tokens, count, info = tokenize_text(text)
|
| 361 |
+
token_str = " | ".join(tokens) if tokens else ""
|
| 362 |
+
return token_str, count, info
|
| 363 |
+
|
| 364 |
+
def update_predictions_with_context(text):
|
| 365 |
+
if not text.strip():
|
| 366 |
+
return "Enter text to get predictions", "No text to analyze"
|
| 367 |
+
|
| 368 |
+
# Get token count for context window
|
| 369 |
+
_, token_count, _ = tokenize_text(text)
|
| 370 |
+
context_status = f"Current text: {token_count} tokens / 4096 (GPT-3.5 limit) = {token_count/4096*100:.1f}% used"
|
| 371 |
+
|
| 372 |
+
# Get predictions
|
| 373 |
+
predictions = get_next_token_predictions(text)
|
| 374 |
+
|
| 375 |
+
return predictions, context_status
|
| 376 |
+
|
| 377 |
+
def generate_network_visualization(text):
|
| 378 |
+
return create_attention_network_svg(text)
|
| 379 |
+
|
| 380 |
+
# Connect event handlers
|
| 381 |
+
tokenize_btn.click(
|
| 382 |
+
update_tokenization,
|
| 383 |
+
inputs=[token_input],
|
| 384 |
+
outputs=[token_display, token_count, token_info]
|
| 385 |
+
)
|
| 386 |
+
|
| 387 |
+
# Auto-update tokenization as user types
|
| 388 |
+
token_input.change(
|
| 389 |
+
update_tokenization,
|
| 390 |
+
inputs=[token_input],
|
| 391 |
+
outputs=[token_display, token_count, token_info]
|
| 392 |
+
)
|
| 393 |
+
|
| 394 |
+
predict_btn.click(
|
| 395 |
+
update_predictions_with_context,
|
| 396 |
+
inputs=[context_input],
|
| 397 |
+
outputs=[predictions_output, context_window_info]
|
| 398 |
+
)
|
| 399 |
+
|
| 400 |
+
analyze_attention_btn.click(
|
| 401 |
+
generate_network_visualization,
|
| 402 |
+
inputs=[attention_input],
|
| 403 |
+
outputs=[attention_network]
|
| 404 |
+
)
|
| 405 |
+
|
| 406 |
+
# OTHER WEEKS
|
| 407 |
+
|
| 408 |
+
with gr.Tab("Week 4: Controlling Model Behaviour"):
|
| 409 |
+
gr.Markdown("# Controlling Model Behaviour Through Prompting")
|
| 410 |
+
gr.Markdown("Explore how different prompting techniques and parameters affect model outputs")
|
| 411 |
+
|
| 412 |
+
with gr.Tabs() as week4_tabs:
|
| 413 |
+
|
| 414 |
+
with gr.Tab("Temperature Effects"):
|
| 415 |
+
gr.Markdown("### Compare how temperature affects creativity and consistency")
|
| 416 |
+
|
| 417 |
+
with gr.Row():
|
| 418 |
+
temp_input = gr.Textbox(
|
| 419 |
+
label="Enter your prompt",
|
| 420 |
+
placeholder="Type your question or prompt here...",
|
| 421 |
+
lines=3,
|
| 422 |
+
value="Write a creative opening sentence for a story about a robot looking for a friend."
|
| 423 |
+
)
|
| 424 |
+
|
| 425 |
+
with gr.Row():
|
| 426 |
+
temp_slider1 = gr.Slider(
|
| 427 |
+
minimum=0.1,
|
| 428 |
+
maximum=0.4,
|
| 429 |
+
value=0.2,
|
| 430 |
+
step=0.1,
|
| 431 |
+
label="Low Temperature (More Focused & Consistent)"
|
| 432 |
+
)
|
| 433 |
+
temp_slider2 = gr.Slider(
|
| 434 |
+
minimum=0.7,
|
| 435 |
+
maximum=1.0,
|
| 436 |
+
value=0.9,
|
| 437 |
+
step=0.1,
|
| 438 |
+
label="High Temperature (More Creative & Varied)"
|
| 439 |
+
)
|
| 440 |
+
|
| 441 |
+
with gr.Row():
|
| 442 |
+
generate_temp = gr.Button("Generate Both Responses")
|
| 443 |
+
|
| 444 |
+
with gr.Row():
|
| 445 |
+
focused_output = gr.Textbox(
|
| 446 |
+
label="Focused Output (Low Temperature)",
|
| 447 |
+
lines=5
|
| 448 |
+
)
|
| 449 |
+
creative_output = gr.Textbox(
|
| 450 |
+
label="Creative Output (High Temperature)",
|
| 451 |
+
lines=5
|
| 452 |
+
)
|
| 453 |
+
|
| 454 |
+
with gr.Tab("System Prompts"):
|
| 455 |
+
gr.Markdown("### See how system prompts shape model behaviour")
|
| 456 |
+
|
| 457 |
+
with gr.Row():
|
| 458 |
+
system_input = gr.Textbox(
|
| 459 |
+
label="Enter your prompt",
|
| 460 |
+
placeholder="Type your question or prompt here...",
|
| 461 |
+
lines=3,
|
| 462 |
+
value="Explain what a database index is."
|
| 463 |
+
)
|
| 464 |
+
|
| 465 |
+
with gr.Row():
|
| 466 |
+
system_prompt_dropdown = gr.Dropdown(
|
| 467 |
+
choices=[
|
| 468 |
+
"You are a helpful assistant providing accurate, concise answers.",
|
| 469 |
+
"You are a data scientist explaining technical concepts with precision and examples.",
|
| 470 |
+
"You are a creative storyteller who uses vivid metaphors and analogies.",
|
| 471 |
+
"You are a critical reviewer who evaluates information carefully and points out limitations.",
|
| 472 |
+
"You are a friendly teacher explaining concepts to someone learning for the first time."
|
| 473 |
+
],
|
| 474 |
+
label="Choose System Prompt",
|
| 475 |
+
value="You are a helpful assistant providing accurate, concise answers."
|
| 476 |
+
)
|
| 477 |
+
|
| 478 |
+
with gr.Row():
|
| 479 |
+
generate_system = gr.Button("Generate Response")
|
| 480 |
+
|
| 481 |
+
with gr.Row():
|
| 482 |
+
system_output = gr.Textbox(label="Output", lines=6)
|
| 483 |
+
|
| 484 |
+
with gr.Tab("Prompting Techniques"):
|
| 485 |
+
gr.Markdown("""
|
| 486 |
+
### Compare Zero-Shot, Few-Shot, and Chain-of-Thought
|
| 487 |
+
- **Zero-shot:** Direct question without examples
|
| 488 |
+
- **Few-shot:** You should provide similar examples to guide the response
|
| 489 |
+
- **Chain-of-thought:** Asks model to break down reasoning step-by-step
|
| 490 |
+
""")
|
| 491 |
+
|
| 492 |
+
with gr.Row():
|
| 493 |
+
shot_input = gr.Textbox(
|
| 494 |
+
label="Enter your task",
|
| 495 |
+
placeholder="Enter a task that requires reasoning...",
|
| 496 |
+
lines=3,
|
| 497 |
+
value="Classify the sentiment: 'The product works okay but customer service was terrible.'"
|
| 498 |
+
)
|
| 499 |
+
|
| 500 |
+
with gr.Row():
|
| 501 |
+
approach_type = gr.Radio(
|
| 502 |
+
["zero-shot", "few-shot", "chain-of-thought"],
|
| 503 |
+
label="Select Prompting Technique",
|
| 504 |
+
value="zero-shot"
|
| 505 |
+
)
|
| 506 |
+
|
| 507 |
+
with gr.Row():
|
| 508 |
+
generate_shot = gr.Button("Generate Response")
|
| 509 |
+
|
| 510 |
+
with gr.Row():
|
| 511 |
+
shot_output = gr.Textbox(label="Output", lines=8)
|
| 512 |
+
|
| 513 |
+
with gr.Tab("Combining Techniques"):
|
| 514 |
+
gr.Markdown("### Experiment with combining multiple techniques")
|
| 515 |
+
|
| 516 |
+
with gr.Row():
|
| 517 |
+
combo_input = gr.Textbox(
|
| 518 |
+
label="Enter your task",
|
| 519 |
+
placeholder="Enter a complex task...",
|
| 520 |
+
lines=3,
|
| 521 |
+
value="Analyse this review and suggest improvements: 'App crashes sometimes but has good features.'"
|
| 522 |
+
)
|
| 523 |
+
|
| 524 |
+
with gr.Row():
|
| 525 |
+
combo_system = gr.Dropdown(
|
| 526 |
+
choices=[
|
| 527 |
+
"None (default)",
|
| 528 |
+
"You are a product analyst providing structured feedback.",
|
| 529 |
+
"You are a UX researcher focused on user experience.",
|
| 530 |
+
],
|
| 531 |
+
label="System Prompt (optional)",
|
| 532 |
+
value="None (default)"
|
| 533 |
+
)
|
| 534 |
+
|
| 535 |
+
with gr.Row():
|
| 536 |
+
combo_examples = gr.Checkbox(
|
| 537 |
+
label="Include few-shot examples",
|
| 538 |
+
value=False
|
| 539 |
+
)
|
| 540 |
+
combo_cot = gr.Checkbox(
|
| 541 |
+
label="Use chain-of-thought reasoning",
|
| 542 |
+
value=False
|
| 543 |
+
)
|
| 544 |
+
|
| 545 |
+
with gr.Row():
|
| 546 |
+
combo_temp = gr.Slider(
|
| 547 |
+
minimum=0.1,
|
| 548 |
+
maximum=1.0,
|
| 549 |
+
value=0.5,
|
| 550 |
+
step=0.1,
|
| 551 |
+
label="Temperature"
|
| 552 |
+
)
|
| 553 |
+
|
| 554 |
+
with gr.Row():
|
| 555 |
+
generate_combo = gr.Button("Generate Response")
|
| 556 |
+
|
| 557 |
+
with gr.Row():
|
| 558 |
+
combo_output = gr.Textbox(label="Output", lines=8)
|
| 559 |
+
combo_info = gr.Textbox(label="Techniques Applied", lines=4)
|
| 560 |
+
|
| 561 |
+
generate_temp.click(
|
| 562 |
+
lambda x, t1, t2: [
|
| 563 |
+
generate_with_temperature(x, t1),
|
| 564 |
+
generate_with_temperature(x, t2)
|
| 565 |
+
],
|
| 566 |
+
inputs=[temp_input, temp_slider1, temp_slider2],
|
| 567 |
+
outputs=[focused_output, creative_output]
|
| 568 |
+
)
|
| 569 |
+
|
| 570 |
+
generate_system.click(
|
| 571 |
+
generate_with_system_prompt,
|
| 572 |
+
inputs=[system_input, system_prompt_dropdown],
|
| 573 |
+
outputs=system_output
|
| 574 |
+
)
|
| 575 |
+
|
| 576 |
+
generate_shot.click(
|
| 577 |
+
generate_with_examples,
|
| 578 |
+
inputs=[shot_input, approach_type],
|
| 579 |
+
outputs=shot_output
|
| 580 |
+
)
|
| 581 |
+
|
| 582 |
+
generate_combo.click(
|
| 583 |
+
generate_combined_techniques,
|
| 584 |
+
inputs=[combo_input, combo_system, combo_examples, combo_cot, combo_temp],
|
| 585 |
+
outputs=[combo_output, combo_info]
|
| 586 |
+
)
|
| 587 |
+
|
| 588 |
+
with gr.Tab("Week 5: Advanced Prompting"):
|
| 589 |
+
gr.Markdown("# Advanced Prompt Engineering Techniques")
|
| 590 |
+
gr.Markdown("Explore sophisticated prompting strategies and visualise reasoning patterns")
|
| 591 |
+
|
| 592 |
+
with gr.Tabs() as week5_tabs:
|
| 593 |
+
|
| 594 |
+
with gr.Tab("Tree of Thought Explorer"):
|
| 595 |
+
gr.Markdown("""
|
| 596 |
+
### Visualise Multi-Path Reasoning
|
| 597 |
+
The model will break down your problem into multiple approaches, evaluate each one, and select the best path.
|
| 598 |
+
""")
|
| 599 |
+
|
| 600 |
+
with gr.Row():
|
| 601 |
+
tot_input = gr.Textbox(
|
| 602 |
+
label="Enter a problem to solve",
|
| 603 |
+
placeholder="e.g., How can we improve user engagement on a mobile app?",
|
| 604 |
+
lines=3,
|
| 605 |
+
value="How should a startup decide between building a mobile app or a web application first?"
|
| 606 |
+
)
|
| 607 |
+
|
| 608 |
+
with gr.Row():
|
| 609 |
+
generate_tot = gr.Button("Generate Tree of Thought", variant="primary")
|
| 610 |
+
|
| 611 |
+
with gr.Row():
|
| 612 |
+
tot_output = gr.Textbox(
|
| 613 |
+
label="Reasoning Process",
|
| 614 |
+
lines=12
|
| 615 |
+
)
|
| 616 |
+
|
| 617 |
+
with gr.Row():
|
| 618 |
+
tot_visualization = gr.HTML(
|
| 619 |
+
label="Tree Visualisation"
|
| 620 |
+
)
|
| 621 |
+
|
| 622 |
+
with gr.Tab("Self-Consistency Testing"):
|
| 623 |
+
gr.Markdown("""
|
| 624 |
+
### Test Response Consistency
|
| 625 |
+
Run the same prompt multiple times to identify consistent patterns and areas of uncertainty.
|
| 626 |
+
""")
|
| 627 |
+
|
| 628 |
+
with gr.Row():
|
| 629 |
+
consistency_input = gr.Textbox(
|
| 630 |
+
label="Enter your prompt",
|
| 631 |
+
placeholder="Ask a question that requires reasoning...",
|
| 632 |
+
lines=3,
|
| 633 |
+
value="What are the three most important factors in choosing a database system?"
|
| 634 |
+
)
|
| 635 |
+
|
| 636 |
+
with gr.Row():
|
| 637 |
+
num_runs = gr.Slider(
|
| 638 |
+
minimum=3,
|
| 639 |
+
maximum=5,
|
| 640 |
+
value=3,
|
| 641 |
+
step=1,
|
| 642 |
+
label="Number of generations"
|
| 643 |
+
)
|
| 644 |
+
consistency_temp = gr.Slider(
|
| 645 |
+
minimum=0.3,
|
| 646 |
+
maximum=0.9,
|
| 647 |
+
value=0.7,
|
| 648 |
+
step=0.1,
|
| 649 |
+
label="Temperature"
|
| 650 |
+
)
|
| 651 |
+
|
| 652 |
+
with gr.Row():
|
| 653 |
+
generate_consistency = gr.Button("Generate Multiple Responses", variant="primary")
|
| 654 |
+
|
| 655 |
+
with gr.Row():
|
| 656 |
+
consistency_analysis = gr.Textbox(
|
| 657 |
+
label="Analysis Guide",
|
| 658 |
+
lines=4
|
| 659 |
+
)
|
| 660 |
+
|
| 661 |
+
with gr.Row():
|
| 662 |
+
consistency_output1 = gr.Textbox(label="Response 1", lines=5)
|
| 663 |
+
consistency_output2 = gr.Textbox(label="Response 2", lines=5)
|
| 664 |
+
|
| 665 |
+
with gr.Row():
|
| 666 |
+
consistency_output3 = gr.Textbox(label="Response 3", lines=5)
|
| 667 |
+
consistency_output4 = gr.Textbox(label="Response 4 (if selected)", lines=5, visible=True)
|
| 668 |
+
|
| 669 |
+
with gr.Row():
|
| 670 |
+
consistency_output5 = gr.Textbox(label="Response 5 (if selected)", lines=5, visible=True)
|
| 671 |
+
|
| 672 |
+
with gr.Tab("Prompt Structure Comparison"):
|
| 673 |
+
gr.Markdown("""
|
| 674 |
+
### Compare Structural Strategies
|
| 675 |
+
Test how different prompt structures affect model attention and output quality.
|
| 676 |
+
""")
|
| 677 |
+
|
| 678 |
+
with gr.Row():
|
| 679 |
+
structure_input = gr.Textbox(
|
| 680 |
+
label="Enter your task",
|
| 681 |
+
placeholder="Enter a task or question...",
|
| 682 |
+
lines=3,
|
| 683 |
+
value=""
|
| 684 |
+
)
|
| 685 |
+
|
| 686 |
+
with gr.Row():
|
| 687 |
+
gr.Markdown("### Select ONE structure to test:")
|
| 688 |
+
|
| 689 |
+
with gr.Row():
|
| 690 |
+
structure_radio = gr.Radio(
|
| 691 |
+
choices=[
|
| 692 |
+
"Baseline (no special structure)",
|
| 693 |
+
"Front-loading (critical instruction first)",
|
| 694 |
+
"Delimiter strategy (section separation)",
|
| 695 |
+
"Sandwich technique (instruction at start and end)"
|
| 696 |
+
],
|
| 697 |
+
label="Prompt Structure",
|
| 698 |
+
value="Baseline (no special structure)"
|
| 699 |
+
)
|
| 700 |
+
|
| 701 |
+
with gr.Row():
|
| 702 |
+
generate_structure = gr.Button("Generate Response", variant="primary")
|
| 703 |
+
|
| 704 |
+
with gr.Row():
|
| 705 |
+
structure_output = gr.Textbox(
|
| 706 |
+
label="Response",
|
| 707 |
+
lines=8
|
| 708 |
+
)
|
| 709 |
+
structure_info = gr.Textbox(
|
| 710 |
+
label="Structure Information",
|
| 711 |
+
lines=8
|
| 712 |
+
)
|
| 713 |
+
|
| 714 |
+
# Week 5 Event Handlers
|
| 715 |
+
def handle_tot(task):
|
| 716 |
+
text_output, svg_output = generate_tot_response(task)
|
| 717 |
+
return text_output, svg_output
|
| 718 |
+
|
| 719 |
+
def handle_consistency(prompt, runs, temp):
|
| 720 |
+
responses, analysis = generate_self_consistency(prompt, int(runs), temp)
|
| 721 |
+
while len(responses) < 5:
|
| 722 |
+
responses.append("")
|
| 723 |
+
return analysis, responses[0], responses[1], responses[2], responses[3], responses[4]
|
| 724 |
+
|
| 725 |
+
def handle_structure(task, structure_choice):
|
| 726 |
+
use_frontload = "Front-loading" in structure_choice
|
| 727 |
+
use_delimiters = "Delimiter" in structure_choice
|
| 728 |
+
use_sandwich = "Sandwich" in structure_choice
|
| 729 |
+
|
| 730 |
+
output, info = compare_prompt_structures(task, use_frontload, use_delimiters, use_sandwich)
|
| 731 |
+
return output, info
|
| 732 |
+
|
| 733 |
+
generate_tot.click(
|
| 734 |
+
handle_tot,
|
| 735 |
+
inputs=[tot_input],
|
| 736 |
+
outputs=[tot_output, tot_visualization]
|
| 737 |
+
)
|
| 738 |
+
|
| 739 |
+
generate_consistency.click(
|
| 740 |
+
handle_consistency,
|
| 741 |
+
inputs=[consistency_input, num_runs, consistency_temp],
|
| 742 |
+
outputs=[consistency_analysis, consistency_output1, consistency_output2,
|
| 743 |
+
consistency_output3, consistency_output4, consistency_output5]
|
| 744 |
+
)
|
| 745 |
+
|
| 746 |
+
generate_structure.click(
|
| 747 |
+
handle_structure,
|
| 748 |
+
inputs=[structure_input, structure_radio],
|
| 749 |
+
outputs=[structure_output, structure_info]
|
| 750 |
+
)
|
| 751 |
+
|
| 752 |
+
# with gr.Tab("Week 8: Error Detection"):
|
| 753 |
+
# # Week 8 content here
|
| 754 |
+
# pass
|
| 755 |
+
|
| 756 |
+
# with gr.Tab("Assignment 1"):
|
| 757 |
+
# # Assignment content here
|
| 758 |
+
# pass
|
| 759 |
+
|
| 760 |
+
demo.launch()
|
gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
index.css
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
body {
|
| 2 |
+
margin: 0;
|
| 3 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
| 4 |
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
| 5 |
+
sans-serif;
|
| 6 |
+
-webkit-font-smoothing: antialiased;
|
| 7 |
+
-moz-osx-font-smoothing: grayscale;
|
| 8 |
+
}
|
| 9 |
+
|
| 10 |
+
code {
|
| 11 |
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
| 12 |
+
monospace;
|
| 13 |
+
}
|
index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import React from 'react';
|
| 2 |
+
import ReactDOM from 'react-dom/client';
|
| 3 |
+
import './index.css';
|
| 4 |
+
import App from './App';
|
| 5 |
+
import reportWebVitals from './reportWebVitals';
|
| 6 |
+
|
| 7 |
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
| 8 |
+
root.render(
|
| 9 |
+
<React.StrictMode>
|
| 10 |
+
<App />
|
| 11 |
+
</React.StrictMode>
|
| 12 |
+
);
|
| 13 |
+
|
| 14 |
+
// If you want to start measuring performance in your app, pass a function
|
| 15 |
+
// to log results (for example: reportWebVitals(console.log))
|
| 16 |
+
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
| 17 |
+
reportWebVitals();
|
logo.svg
ADDED
|
|
model_functions.py
ADDED
|
@@ -0,0 +1,688 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import openai
|
| 3 |
+
import PyPDF2
|
| 4 |
+
import pypdfium2
|
| 5 |
+
from io import BytesIO
|
| 6 |
+
|
| 7 |
+
OPENAI_API_KEY = os.getenv("openAI_TOKEN")
|
| 8 |
+
openai.api_key = OPENAI_API_KEY
|
| 9 |
+
|
| 10 |
+
def generate_combined_techniques(task, system_prompt, use_examples, use_cot, temperature):
|
| 11 |
+
"""Combine multiple prompting techniques"""
|
| 12 |
+
if not OPENAI_API_KEY:
|
| 13 |
+
return "OpenAI API key not available", "Error"
|
| 14 |
+
|
| 15 |
+
try:
|
| 16 |
+
# Build the user message based on selected techniques
|
| 17 |
+
user_message = task
|
| 18 |
+
techniques_used = []
|
| 19 |
+
|
| 20 |
+
# Add few-shot examples if selected
|
| 21 |
+
if use_examples:
|
| 22 |
+
user_message = """Here are some examples:
|
| 23 |
+
|
| 24 |
+
Example 1:
|
| 25 |
+
Input: "The restaurant was clean but the food was cold."
|
| 26 |
+
Analysis: Mixed sentiment - positive about cleanliness, negative about food quality.
|
| 27 |
+
|
| 28 |
+
Example 2:
|
| 29 |
+
Input: "Great service and amazing atmosphere!"
|
| 30 |
+
Analysis: Positive sentiment - praise for both service and atmosphere.
|
| 31 |
+
|
| 32 |
+
Now for your task:
|
| 33 |
+
""" + task
|
| 34 |
+
techniques_used.append("Few-shot examples")
|
| 35 |
+
|
| 36 |
+
# Add chain-of-thought if selected
|
| 37 |
+
if use_cot:
|
| 38 |
+
user_message += "\n\nThink through this step by step before providing your final answer."
|
| 39 |
+
techniques_used.append("Chain-of-thought reasoning")
|
| 40 |
+
|
| 41 |
+
# Set up system prompt
|
| 42 |
+
messages = []
|
| 43 |
+
if system_prompt != "None (default)":
|
| 44 |
+
messages.append({"role": "system", "content": system_prompt})
|
| 45 |
+
techniques_used.append(f"System prompt: {system_prompt[:50]}...")
|
| 46 |
+
|
| 47 |
+
messages.append({"role": "user", "content": user_message})
|
| 48 |
+
|
| 49 |
+
# Add temperature to techniques info
|
| 50 |
+
techniques_used.append(f"Temperature: {temperature}")
|
| 51 |
+
|
| 52 |
+
# Generate response
|
| 53 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 54 |
+
response = client.chat.completions.create(
|
| 55 |
+
model="gpt-3.5-turbo",
|
| 56 |
+
messages=messages,
|
| 57 |
+
temperature=temperature,
|
| 58 |
+
max_tokens=300
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
techniques_info = "Techniques applied:\n" + "\n".join(f"• {t}" for t in techniques_used)
|
| 62 |
+
|
| 63 |
+
return response.choices[0].message.content, techniques_info
|
| 64 |
+
|
| 65 |
+
except Exception as e:
|
| 66 |
+
return f"Error: {str(e)}", "Error occurred"
|
| 67 |
+
|
| 68 |
+
def generate_with_temperature(input_text, temperature):
|
| 69 |
+
try:
|
| 70 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 71 |
+
|
| 72 |
+
if temperature <= 0.4:
|
| 73 |
+
system_content = "You are a precise and factual assistant. Stick to clear, accurate information without elaboration or creativity."
|
| 74 |
+
else:
|
| 75 |
+
system_content = "You are a creative and imaginative assistant. Feel free to be original, elaborate, and think outside the box."
|
| 76 |
+
|
| 77 |
+
response = openai_client.chat.completions.create(
|
| 78 |
+
model="gpt-3.5-turbo",
|
| 79 |
+
messages=[
|
| 80 |
+
{"role": "system", "content": system_content},
|
| 81 |
+
{"role": "user", "content": input_text}
|
| 82 |
+
],
|
| 83 |
+
temperature=float(temperature),
|
| 84 |
+
max_tokens=300
|
| 85 |
+
)
|
| 86 |
+
return response.choices[0].message.content
|
| 87 |
+
except Exception as e:
|
| 88 |
+
return f"Error: {str(e)}"
|
| 89 |
+
|
| 90 |
+
def generate_with_system_prompt(input_text, system_prompt):
|
| 91 |
+
try:
|
| 92 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 93 |
+
response = openai_client.chat.completions.create(
|
| 94 |
+
model="gpt-3.5-turbo",
|
| 95 |
+
messages=[
|
| 96 |
+
{"role": "system", "content": system_prompt},
|
| 97 |
+
{"role": "user", "content": input_text}
|
| 98 |
+
],
|
| 99 |
+
temperature=0.7,
|
| 100 |
+
max_tokens=300
|
| 101 |
+
)
|
| 102 |
+
return response.choices[0].message.content
|
| 103 |
+
except Exception as e:
|
| 104 |
+
return f"Error: {str(e)}"
|
| 105 |
+
|
| 106 |
+
def generate_with_examples(input_text, approach_type):
|
| 107 |
+
try:
|
| 108 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 109 |
+
|
| 110 |
+
if approach_type == "few-shot":
|
| 111 |
+
system_content = "You are a helpful assistant. Before answering the question, consider similar examples you know about."
|
| 112 |
+
elif approach_type == "chain-of-thought":
|
| 113 |
+
system_content = "You are a helpful assistant. Break down your thinking process step by step."
|
| 114 |
+
else:
|
| 115 |
+
system_content = "You are a helpful assistant. Answer directly."
|
| 116 |
+
|
| 117 |
+
messages = [
|
| 118 |
+
{"role": "system", "content": system_content},
|
| 119 |
+
{"role": "user", "content": input_text}
|
| 120 |
+
]
|
| 121 |
+
|
| 122 |
+
response = openai_client.chat.completions.create(
|
| 123 |
+
model="gpt-3.5-turbo",
|
| 124 |
+
messages=messages,
|
| 125 |
+
temperature=0.7,
|
| 126 |
+
max_tokens=300
|
| 127 |
+
)
|
| 128 |
+
return response.choices[0].message.content
|
| 129 |
+
except Exception as e:
|
| 130 |
+
return f"Error: {str(e)}"
|
| 131 |
+
|
| 132 |
+
def perform_classification(text, task_type):
|
| 133 |
+
try:
|
| 134 |
+
if not text.strip():
|
| 135 |
+
return "Error: No text provided for classification"
|
| 136 |
+
|
| 137 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 138 |
+
if task_type == "Sentiment Analysis":
|
| 139 |
+
system_content = "You are a sentiment analyzer. Analyze the sentiment of the text and categorize it as positive, negative, or neutral. Also provide a confidence score as a percentage."
|
| 140 |
+
else: # Text Classification
|
| 141 |
+
system_content = "You are a text classifier. Determine the most appropriate category for this text (e.g., news, technical, personal, business, etc.) and explain why. Also provide a confidence score as a percentage."
|
| 142 |
+
|
| 143 |
+
response = openai_client.chat.completions.create(
|
| 144 |
+
model="gpt-3.5-turbo",
|
| 145 |
+
messages=[
|
| 146 |
+
{"role": "system", "content": system_content},
|
| 147 |
+
{"role": "user", "content": text}
|
| 148 |
+
],
|
| 149 |
+
temperature=0.3
|
| 150 |
+
)
|
| 151 |
+
return response.choices[0].message.content
|
| 152 |
+
except Exception as e:
|
| 153 |
+
return f"Error in classification: {str(e)}"
|
| 154 |
+
|
| 155 |
+
def perform_ner(text):
|
| 156 |
+
try:
|
| 157 |
+
if not text.strip():
|
| 158 |
+
return "Error: No text provided for NER"
|
| 159 |
+
|
| 160 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 161 |
+
system_content = """You are an entity recognition system. Identify and list all named entities in the text, categorized by type:
|
| 162 |
+
- PERSON (people names)
|
| 163 |
+
- ORG (organizations)
|
| 164 |
+
- LOC (locations)
|
| 165 |
+
- DATE (dates and times)
|
| 166 |
+
- NUMBER (quantities)
|
| 167 |
+
Format your response as a clear list with categories."""
|
| 168 |
+
|
| 169 |
+
response = openai_client.chat.completions.create(
|
| 170 |
+
model="gpt-3.5-turbo",
|
| 171 |
+
messages=[
|
| 172 |
+
{"role": "system", "content": system_content},
|
| 173 |
+
{"role": "user", "content": text}
|
| 174 |
+
],
|
| 175 |
+
temperature=0.3
|
| 176 |
+
)
|
| 177 |
+
return response.choices[0].message.content
|
| 178 |
+
except Exception as e:
|
| 179 |
+
return f"Error in NER: {str(e)}"
|
| 180 |
+
|
| 181 |
+
def perform_summarization(text):
|
| 182 |
+
try:
|
| 183 |
+
if not text.strip():
|
| 184 |
+
return "Error: No text provided for summarization"
|
| 185 |
+
|
| 186 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 187 |
+
system_content = "You are a text summarizer. Provide both a brief (2-3 sentences) and a detailed (paragraph) summary of the text. Indicate the type of summary provided."
|
| 188 |
+
|
| 189 |
+
response = openai_client.chat.completions.create(
|
| 190 |
+
model="gpt-3.5-turbo",
|
| 191 |
+
messages=[
|
| 192 |
+
{"role": "system", "content": system_content},
|
| 193 |
+
{"role": "user", "content": text}
|
| 194 |
+
],
|
| 195 |
+
temperature=0.3
|
| 196 |
+
)
|
| 197 |
+
return response.choices[0].message.content
|
| 198 |
+
except Exception as e:
|
| 199 |
+
return f"Error in summarization: {str(e)}"
|
| 200 |
+
|
| 201 |
+
|
| 202 |
+
from io import BytesIO
|
| 203 |
+
import PyPDF2
|
| 204 |
+
|
| 205 |
+
def process_uploaded_file(file_bytes):
|
| 206 |
+
"""Process uploaded PDF or TXT from raw binary bytes and return the text content."""
|
| 207 |
+
try:
|
| 208 |
+
if file_bytes is None:
|
| 209 |
+
return "Error: No file provided"
|
| 210 |
+
|
| 211 |
+
# Convert bytes to BytesIO (file-like object)
|
| 212 |
+
file_obj = BytesIO(file_bytes)
|
| 213 |
+
|
| 214 |
+
# Try reading as a PDF using PyPDF2
|
| 215 |
+
try:
|
| 216 |
+
pdf_reader = PyPDF2.PdfReader(file_obj)
|
| 217 |
+
if len(pdf_reader.pages) == 0:
|
| 218 |
+
return "Error: PDF contains no pages."
|
| 219 |
+
|
| 220 |
+
text = ""
|
| 221 |
+
for page_num in range(len(pdf_reader.pages)):
|
| 222 |
+
page = pdf_reader.pages[page_num]
|
| 223 |
+
extracted_text = page.extract_text()
|
| 224 |
+
if extracted_text:
|
| 225 |
+
text += extracted_text.strip() + "\n"
|
| 226 |
+
|
| 227 |
+
return text if text.strip() else "Error: PDF pages found, but no text could be extracted."
|
| 228 |
+
except Exception as pdf_error:
|
| 229 |
+
return f"Error reading PDF with PyPDF2: {str(pdf_error)}"
|
| 230 |
+
|
| 231 |
+
except Exception as e:
|
| 232 |
+
return f"Error processing file: {str(e)}"
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
def handle_classification(text_input, file_input, task_type):
|
| 237 |
+
try:
|
| 238 |
+
# Enforce either-or input
|
| 239 |
+
if text_input and file_input:
|
| 240 |
+
return "Error: Provide either text input or file upload, not both."
|
| 241 |
+
if not text_input and not file_input:
|
| 242 |
+
return "Error: Please provide either text or a file."
|
| 243 |
+
|
| 244 |
+
if file_input is not None:
|
| 245 |
+
text = process_uploaded_file(file_input) # Pass raw bytes
|
| 246 |
+
if text.startswith("Error"):
|
| 247 |
+
return text
|
| 248 |
+
else:
|
| 249 |
+
text = text_input.strip()
|
| 250 |
+
|
| 251 |
+
if not task_type:
|
| 252 |
+
return "Error: Please select a task type."
|
| 253 |
+
|
| 254 |
+
return perform_classification(text, task_type)
|
| 255 |
+
|
| 256 |
+
except Exception as e:
|
| 257 |
+
return f"Error in classification handler: {str(e)}"
|
| 258 |
+
|
| 259 |
+
def handle_ner(text_input, file_input):
|
| 260 |
+
if text_input and file_input:
|
| 261 |
+
return "Error: Provide either text or file upload, not both."
|
| 262 |
+
if not text_input and not file_input:
|
| 263 |
+
return "Error: Please provide either text or a file."
|
| 264 |
+
|
| 265 |
+
text = process_uploaded_file(file_input) if file_input else text_input.strip()
|
| 266 |
+
return perform_ner(text)
|
| 267 |
+
|
| 268 |
+
def handle_summarization(text_input, file_input):
|
| 269 |
+
if text_input and file_input:
|
| 270 |
+
return "Error: Provide either text or file upload, not both."
|
| 271 |
+
if not text_input and not file_input:
|
| 272 |
+
return "Error: Please provide either text or a file."
|
| 273 |
+
|
| 274 |
+
text = process_uploaded_file(file_input) if file_input else text_input.strip()
|
| 275 |
+
return perform_summarization(text)
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def handle_assignment_task(text_input, file_input, task_type, temperature, system_prompt):
|
| 279 |
+
try:
|
| 280 |
+
# Process input (either direct text or file)
|
| 281 |
+
if file_input is not None:
|
| 282 |
+
text = process_uploaded_file(file_input)
|
| 283 |
+
if text.startswith("Error"):
|
| 284 |
+
return text
|
| 285 |
+
else:
|
| 286 |
+
text = text_input
|
| 287 |
+
|
| 288 |
+
if not text or not text.strip():
|
| 289 |
+
return "Error: Please enter text or upload a file"
|
| 290 |
+
|
| 291 |
+
# Route to appropriate task handler based on task_type
|
| 292 |
+
if task_type == "Sentiment Analysis":
|
| 293 |
+
return perform_sentiment_analysis(text, temperature, system_prompt)
|
| 294 |
+
else: # Summarization
|
| 295 |
+
return perform_summarization(text, temperature, system_prompt)
|
| 296 |
+
|
| 297 |
+
except Exception as e:
|
| 298 |
+
return f"Error in task handling: {str(e)}"
|
| 299 |
+
|
| 300 |
+
def perform_sentiment_analysis(text, temperature, system_prompt):
|
| 301 |
+
try:
|
| 302 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 303 |
+
|
| 304 |
+
# Base system content on temperature
|
| 305 |
+
if temperature <= 0.4:
|
| 306 |
+
base_content = "You are a precise assistant. Stick to clear, short, accurate information without elaboration or creativity."
|
| 307 |
+
else:
|
| 308 |
+
base_content = "You are an elaborate assistant. Feel free to be original, elaborate, and think outside the box."
|
| 309 |
+
|
| 310 |
+
# Modify based on system prompt
|
| 311 |
+
if system_prompt == "None: Default (no specific role)":
|
| 312 |
+
system_content = base_content + " Analyze the sentiment of the text and categorize it as positive, negative, or neutral. Also provide a confidence score as a percentage."
|
| 313 |
+
elif system_prompt == "Prompt 1: Professional Analyst providing precise analysis":
|
| 314 |
+
system_content = base_content + " As a professional analyst, provide a detailed sentiment analysis with clear categorization and evidence from the text. Include confidence scores and explain your reasoning."
|
| 315 |
+
else: # Prompt 2
|
| 316 |
+
system_content = base_content + " As a creative interpreter, provide an insightful analysis of the emotional nuances and underlying sentiment in the text. Consider subtle tones and contextual clues."
|
| 317 |
+
|
| 318 |
+
response = openai_client.chat.completions.create(
|
| 319 |
+
model="gpt-3.5-turbo",
|
| 320 |
+
messages=[
|
| 321 |
+
{"role": "system", "content": system_content},
|
| 322 |
+
{"role": "user", "content": text}
|
| 323 |
+
],
|
| 324 |
+
temperature=float(temperature)
|
| 325 |
+
)
|
| 326 |
+
return response.choices[0].message.content
|
| 327 |
+
except Exception as e:
|
| 328 |
+
return f"Error in sentiment analysis: {str(e)}"
|
| 329 |
+
|
| 330 |
+
def perform_summarization(text, temperature, system_prompt):
|
| 331 |
+
try:
|
| 332 |
+
openai_client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 333 |
+
|
| 334 |
+
# Base system content on temperature
|
| 335 |
+
if temperature <= 0.4:
|
| 336 |
+
base_content = "You are a precise assistant. Stick to clear, short, accurate information without elaboration or creativity."
|
| 337 |
+
else:
|
| 338 |
+
base_content = "You are an elaborate assistant. Feel free to be original, elaborate, and think outside the box."
|
| 339 |
+
|
| 340 |
+
# Modify based on system prompt
|
| 341 |
+
if system_prompt == "None: Default (no specific role)":
|
| 342 |
+
system_content = base_content + " Summarize the text clearly and concisely."
|
| 343 |
+
elif system_prompt == "Prompt 1: Professional Analyst providing precise analysis":
|
| 344 |
+
system_content = base_content + " As a professional analyst, provide a precise and structured summary focusing on key points and main arguments."
|
| 345 |
+
else: # Prompt 2
|
| 346 |
+
system_content = base_content + " As a creative interpreter, provide an engaging summary that captures both the content and the style of the original text."
|
| 347 |
+
|
| 348 |
+
response = openai_client.chat.completions.create(
|
| 349 |
+
model="gpt-3.5-turbo",
|
| 350 |
+
messages=[
|
| 351 |
+
{"role": "system", "content": system_content},
|
| 352 |
+
{"role": "user", "content": text}
|
| 353 |
+
],
|
| 354 |
+
temperature=float(temperature)
|
| 355 |
+
)
|
| 356 |
+
return response.choices[0].message.content
|
| 357 |
+
except Exception as e:
|
| 358 |
+
return f"Error in summarization: {str(e)}"
|
| 359 |
+
|
| 360 |
+
def generate_error_response(prompt_key):
|
| 361 |
+
"""Return pre-written responses with deliberate errors"""
|
| 362 |
+
|
| 363 |
+
error_responses = {
|
| 364 |
+
"Explain the basic rules of chess":
|
| 365 |
+
"Chess is played on an 8×8 board with 16 pieces per player. Each player has 1 king, 1 queen, 2 rooks, 2 knights, 2 bishops, and 8 pawns. The goal is to checkmate the opponent's king. \n\nPawns move forward one square but capture diagonally. They can move two squares on their first move. Knights move in an L-shape, jumping over other pieces. Bishops move diagonally any number of squares. Rooks move horizontally or vertically any number of squares. The queen can move like a rook or bishop. The king moves exactly three squares in any direction. \n\nCastling is a special move involving the king and rook. En passant is a special pawn capture. When a pawn reaches the opposite end of the board, it can be promoted to any piece except a king.",
|
| 366 |
+
|
| 367 |
+
"List the planets in our solar system in order from the sun":
|
| 368 |
+
"The planets in our solar system, in order from the sun, are: \n\n1. Mercury - the smallest planet \n2. Venus - the hottest planet \n3. Earth - our home planet \n4. Mars - the red planet \n5. Neptune - known for its great dark spot \n6. Jupiter - the largest planet \n7. Saturn - known for its rings \n8. Uranus - tilted on its side \n\nPluto was formerly considered the ninth planet but was reclassified as a dwarf planet in 2006.",
|
| 369 |
+
|
| 370 |
+
"Describe the three branches of the US government":
|
| 371 |
+
"The U.S. government consists of three branches, designed to provide checks and balances: \n\n1. The Legislative Branch (Congress): Made up of the Senate and House of Representatives. The Senate has 50 members, two from each state, serving 6-year terms. The House has 435 members with 2-year terms, allocated based on state population. Congress makes laws, declares war, and approves treaties. \n\n2. The Executive Branch: Led by the President, who serves as both head of state and head of government for a 4-year term, with a maximum of two terms. The President enforces laws, commands the military, and conducts foreign policy. \n\n3. The Judicial Branch: Consists of the Supreme Court and lower federal courts. The Supreme Court has 8 justices who serve for life. They interpret laws and determine if they violate the Constitution.",
|
| 372 |
+
|
| 373 |
+
"Explain how to convert Celsius to Fahrenheit":
|
| 374 |
+
"To convert a temperature from Celsius to Fahrenheit, you use the following formula: \n\nF = C × 1.8 + 32 \n\nFor example, let's convert 20°C to Fahrenheit: \nF = 20 × 1.8 + 32 \nF = 36 + 32 \nF = 68 \n\nSo 20°C equals 68°F. \n\nAnother example: to convert 30°C to Fahrenheit: \nF = 30 × 1.8 + 32 \nF = 54 + 32 \nF = 76 \n\nSo 30°C equals 76°F.",
|
| 375 |
+
|
| 376 |
+
"List the primary colors in art":
|
| 377 |
+
"In art, the primary colors are red, yellow, green, and blue. These are colors that cannot be created by mixing other colors together. \n\nFrom these primary colors, you can create secondary colors: \n- Red + Yellow = Orange \n- Yellow + Green = Yellow-green \n- Green + Blue = Cyan \n- Blue + Red = Purple \n\nBy mixing primary and secondary colors, you can create all other colors in the visible spectrum. The primary colors form the foundation of color theory and are essential for artists to understand when mixing paints."
|
| 378 |
+
}
|
| 379 |
+
|
| 380 |
+
return error_responses.get(
|
| 381 |
+
prompt_key,
|
| 382 |
+
"Sorry, no pre-written example is available for this prompt."
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
def generate_tot_response(task):
|
| 386 |
+
"""Generate a Tree of Thought structured response"""
|
| 387 |
+
if not OPENAI_API_KEY:
|
| 388 |
+
return "OpenAI API key not available", ""
|
| 389 |
+
|
| 390 |
+
try:
|
| 391 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 392 |
+
|
| 393 |
+
prompt = f"""Solve this problem using Tree of Thought reasoning. Structure your response EXACTLY as follows:
|
| 394 |
+
|
| 395 |
+
PROBLEM: {task}
|
| 396 |
+
|
| 397 |
+
STEP 1: [Break down the problem]
|
| 398 |
+
|
| 399 |
+
BRANCH A: [First approach]
|
| 400 |
+
EVALUATION A: [Score 1-10 and brief assessment]
|
| 401 |
+
|
| 402 |
+
BRANCH B: [Second approach]
|
| 403 |
+
EVALUATION B: [Score 1-10 and brief assessment]
|
| 404 |
+
|
| 405 |
+
BRANCH C: [Third approach]
|
| 406 |
+
EVALUATION C: [Score 1-10 and brief assessment]
|
| 407 |
+
|
| 408 |
+
SELECTED: [A, B, or C]
|
| 409 |
+
REASONING: [Why you selected this branch]
|
| 410 |
+
|
| 411 |
+
Be concise and follow this format exactly."""
|
| 412 |
+
|
| 413 |
+
response = client.chat.completions.create(
|
| 414 |
+
model="gpt-3.5-turbo",
|
| 415 |
+
messages=[
|
| 416 |
+
{"role": "system", "content": "You are a systematic problem solver who breaks down problems into multiple approaches and evaluates them."},
|
| 417 |
+
{"role": "user", "content": prompt}
|
| 418 |
+
],
|
| 419 |
+
temperature=0.7,
|
| 420 |
+
max_tokens=500
|
| 421 |
+
)
|
| 422 |
+
|
| 423 |
+
return response.choices[0].message.content, parse_tot_to_svg(response.choices[0].message.content)
|
| 424 |
+
|
| 425 |
+
except Exception as e:
|
| 426 |
+
return f"Error: {str(e)}", ""
|
| 427 |
+
|
| 428 |
+
def parse_tot_to_svg(tot_response):
|
| 429 |
+
"""Parse ToT response and create SVG tree visualization"""
|
| 430 |
+
try:
|
| 431 |
+
lines = tot_response.strip().split('\n')
|
| 432 |
+
|
| 433 |
+
# Extract information
|
| 434 |
+
branches = {'A': {}, 'B': {}, 'C': {}}
|
| 435 |
+
selected = None
|
| 436 |
+
|
| 437 |
+
for line in lines:
|
| 438 |
+
line = line.strip()
|
| 439 |
+
if line.startswith('BRANCH A:'):
|
| 440 |
+
branches['A']['text'] = line.replace('BRANCH A:', '').strip()[:70]
|
| 441 |
+
elif line.startswith('EVALUATION A:'):
|
| 442 |
+
eval_text = line.replace('EVALUATION A:', '').strip()
|
| 443 |
+
branches['A']['eval'] = eval_text[:30]
|
| 444 |
+
# Extract score if present
|
| 445 |
+
import re
|
| 446 |
+
score_match = re.search(r'(\d+)/10|(\d+)', eval_text)
|
| 447 |
+
branches['A']['score'] = int(score_match.group(1) or score_match.group(2)) if score_match else 5
|
| 448 |
+
elif line.startswith('BRANCH B:'):
|
| 449 |
+
branches['B']['text'] = line.replace('BRANCH B:', '').strip()[:40]
|
| 450 |
+
elif line.startswith('EVALUATION B:'):
|
| 451 |
+
eval_text = line.replace('EVALUATION B:', '').strip()
|
| 452 |
+
branches['B']['eval'] = eval_text[:30]
|
| 453 |
+
score_match = re.search(r'(\d+)/10|(\d+)', eval_text)
|
| 454 |
+
branches['B']['score'] = int(score_match.group(1) or score_match.group(2)) if score_match else 5
|
| 455 |
+
elif line.startswith('BRANCH C:'):
|
| 456 |
+
branches['C']['text'] = line.replace('BRANCH C:', '').strip()[:40]
|
| 457 |
+
elif line.startswith('EVALUATION C:'):
|
| 458 |
+
eval_text = line.replace('EVALUATION C:', '').strip()
|
| 459 |
+
branches['C']['eval'] = eval_text[:30]
|
| 460 |
+
score_match = re.search(r'(\d+)/10|(\d+)', eval_text)
|
| 461 |
+
branches['C']['score'] = int(score_match.group(1) or score_match.group(2)) if score_match else 5
|
| 462 |
+
elif line.startswith('SELECTED:'):
|
| 463 |
+
selected_text = line.replace('SELECTED:', '').strip().upper()
|
| 464 |
+
if 'A' in selected_text:
|
| 465 |
+
selected = 'A'
|
| 466 |
+
elif 'B' in selected_text:
|
| 467 |
+
selected = 'B'
|
| 468 |
+
elif 'C' in selected_text:
|
| 469 |
+
selected = 'C'
|
| 470 |
+
|
| 471 |
+
# Create SVG
|
| 472 |
+
width, height = 800, 500
|
| 473 |
+
svg = f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">'
|
| 474 |
+
svg += '<style>.branch-text { font-family: Arial; font-size: 12px; } .score-text { font-family: Arial; font-size: 14px; font-weight: bold; }</style>'
|
| 475 |
+
|
| 476 |
+
# Root node (problem)
|
| 477 |
+
root_x, root_y = width // 2, 80
|
| 478 |
+
svg += f'<circle cx="{root_x}" cy="{root_y}" r="30" fill="#2196f3" stroke="black" stroke-width="2"/>'
|
| 479 |
+
svg += f'<text x="{root_x}" y="{root_y+5}" text-anchor="middle" fill="white" font-weight="bold">Problem</text>'
|
| 480 |
+
|
| 481 |
+
# Branch positions
|
| 482 |
+
branch_y = 250
|
| 483 |
+
branch_positions = {
|
| 484 |
+
'A': (width * 0.2, branch_y),
|
| 485 |
+
'B': (width * 0.5, branch_y),
|
| 486 |
+
'C': (width * 0.8, branch_y)
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
# Draw branches
|
| 490 |
+
for branch_id, (bx, by) in branch_positions.items():
|
| 491 |
+
branch_data = branches.get(branch_id, {})
|
| 492 |
+
|
| 493 |
+
# Determine color based on selection and score
|
| 494 |
+
if branch_id == selected:
|
| 495 |
+
color = "#4caf50" # Green for selected
|
| 496 |
+
stroke_width = "3"
|
| 497 |
+
else:
|
| 498 |
+
score = branch_data.get('score', 5)
|
| 499 |
+
if score >= 7:
|
| 500 |
+
color = "#ff9800" # Orange for good but not selected
|
| 501 |
+
else:
|
| 502 |
+
color = "#9e9e9e" # Grey for lower scores
|
| 503 |
+
stroke_width = "2"
|
| 504 |
+
|
| 505 |
+
# Draw connecting line
|
| 506 |
+
svg += f'<line x1="{root_x}" y1="{root_y+30}" x2="{bx}" y2="{by-60}" stroke="{color}" stroke-width="{stroke_width}"/>'
|
| 507 |
+
|
| 508 |
+
# Draw branch node
|
| 509 |
+
svg += f'<rect x="{bx-70}" y="{by-60}" width="140" height="100" fill="white" stroke="{color}" stroke-width="{stroke_width}" rx="10"/>'
|
| 510 |
+
|
| 511 |
+
# Branch label
|
| 512 |
+
svg += f'<text x="{bx}" y="{by-40}" text-anchor="middle" class="score-text" fill="{color}">Branch {branch_id}</text>'
|
| 513 |
+
|
| 514 |
+
# Branch text (wrapped)
|
| 515 |
+
branch_text = branch_data.get('text', 'No data')
|
| 516 |
+
words = branch_text.split()
|
| 517 |
+
line1 = ' '.join(words[:4])
|
| 518 |
+
line2 = ' '.join(words[4:8]) if len(words) > 4 else ''
|
| 519 |
+
|
| 520 |
+
svg += f'<text x="{bx}" y="{by-20}" text-anchor="middle" class="branch-text">{line1}</text>'
|
| 521 |
+
if line2:
|
| 522 |
+
svg += f'<text x="{bx}" y="{by-5}" text-anchor="middle" class="branch-text">{line2}</text>'
|
| 523 |
+
|
| 524 |
+
# Score
|
| 525 |
+
score = branch_data.get('score', '?')
|
| 526 |
+
svg += f'<text x="{bx}" y="{by+25}" text-anchor="middle" class="score-text" fill="{color}">Score: {score}/10</text>'
|
| 527 |
+
|
| 528 |
+
# Legend
|
| 529 |
+
svg += f'<text x="20" y="{height-30}" style="font-family: Arial; font-size: 14px; font-weight: bold;">Legend:</text>'
|
| 530 |
+
svg += f'<circle cx="35" cy="{height-10}" r="8" fill="#4caf50"/>'
|
| 531 |
+
svg += f'<text x="50" y="{height-5}" style="font-family: Arial; font-size: 12px;">Selected Path</text>'
|
| 532 |
+
svg += f'<circle cx="170" cy="{height-10}" r="8" fill="#ff9800"/>'
|
| 533 |
+
svg += f'<text x="185" y="{height-5}" style="font-family: Arial; font-size: 12px;">Alternative Path</text>'
|
| 534 |
+
|
| 535 |
+
svg += '</svg>'
|
| 536 |
+
|
| 537 |
+
return svg
|
| 538 |
+
|
| 539 |
+
except Exception as e:
|
| 540 |
+
return f'<p>Error creating visualization: {str(e)}</p>'
|
| 541 |
+
|
| 542 |
+
def generate_self_consistency(prompt, num_runs, temperature):
|
| 543 |
+
"""Generate multiple responses for self-consistency testing"""
|
| 544 |
+
if not OPENAI_API_KEY:
|
| 545 |
+
return ["OpenAI API key not available"] * num_runs, "Error"
|
| 546 |
+
|
| 547 |
+
try:
|
| 548 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 549 |
+
responses = []
|
| 550 |
+
|
| 551 |
+
for i in range(num_runs):
|
| 552 |
+
response = client.chat.completions.create(
|
| 553 |
+
model="gpt-3.5-turbo",
|
| 554 |
+
messages=[{"role": "user", "content": prompt}],
|
| 555 |
+
temperature=temperature,
|
| 556 |
+
max_tokens=200
|
| 557 |
+
)
|
| 558 |
+
responses.append(response.choices[0].message.content)
|
| 559 |
+
|
| 560 |
+
analysis = f"Generated {num_runs} responses at temperature {temperature}\n\n"
|
| 561 |
+
analysis += "Look for:\n"
|
| 562 |
+
analysis += "• Common themes or facts across all responses\n"
|
| 563 |
+
analysis += "• Areas where responses disagree\n"
|
| 564 |
+
analysis += "• Variation in phrasing vs. variation in content\n"
|
| 565 |
+
|
| 566 |
+
return responses, analysis
|
| 567 |
+
|
| 568 |
+
except Exception as e:
|
| 569 |
+
return [f"Error: {str(e)}"] * num_runs, "Error occurred"
|
| 570 |
+
|
| 571 |
+
def compare_prompt_structures(task, use_frontload, use_delimiters, use_sandwich):
|
| 572 |
+
"""Compare different prompt structure strategies"""
|
| 573 |
+
if not OPENAI_API_KEY:
|
| 574 |
+
return "OpenAI API key not available", "Error"
|
| 575 |
+
|
| 576 |
+
try:
|
| 577 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 578 |
+
|
| 579 |
+
# Build prompt based on selected strategies
|
| 580 |
+
if use_sandwich:
|
| 581 |
+
prompt = f"IMPORTANT: {task}\n\n"
|
| 582 |
+
prompt += "Consider the following context and examples:\n"
|
| 583 |
+
prompt += "[Context would go here]\n\n"
|
| 584 |
+
prompt += f"REMINDER: {task}"
|
| 585 |
+
structure = "Sandwich technique: Key instruction at start and end"
|
| 586 |
+
elif use_frontload:
|
| 587 |
+
prompt = f"CRITICAL INSTRUCTION: {task}\n\nProvide your response below:"
|
| 588 |
+
structure = "Front-loading: Important instruction placed first"
|
| 589 |
+
elif use_delimiters:
|
| 590 |
+
prompt = f"### INSTRUCTION ###\n{task}\n\n### RESPONSE ###\n"
|
| 591 |
+
structure = "Delimiter strategy: Clear section separation"
|
| 592 |
+
else:
|
| 593 |
+
prompt = task
|
| 594 |
+
structure = "Baseline: Simple prompt without structure"
|
| 595 |
+
|
| 596 |
+
response = client.chat.completions.create(
|
| 597 |
+
model="gpt-3.5-turbo",
|
| 598 |
+
messages=[{"role": "user", "content": prompt}],
|
| 599 |
+
temperature=0.7,
|
| 600 |
+
max_tokens=300
|
| 601 |
+
)
|
| 602 |
+
|
| 603 |
+
info = f"Structure used: {structure}\n\nPrompt length: {len(prompt)} characters"
|
| 604 |
+
|
| 605 |
+
return response.choices[0].message.content, info
|
| 606 |
+
|
| 607 |
+
except Exception as e:
|
| 608 |
+
return f"Error: {str(e)}", "Error occurred"
|
| 609 |
+
|
| 610 |
+
def handle_assignment_experiment(text, file, task, strategy, role, temperature):
|
| 611 |
+
"""Handle assignment experiments with different prompting strategies"""
|
| 612 |
+
if not OPENAI_API_KEY:
|
| 613 |
+
return "OpenAI API key not available", "Error"
|
| 614 |
+
|
| 615 |
+
# Get text content
|
| 616 |
+
if file:
|
| 617 |
+
content = extract_text_from_file(file)
|
| 618 |
+
elif text:
|
| 619 |
+
content = text
|
| 620 |
+
else:
|
| 621 |
+
return "Please provide text or upload a file", "Error"
|
| 622 |
+
|
| 623 |
+
if not content.strip():
|
| 624 |
+
return "No text content found", "Error"
|
| 625 |
+
|
| 626 |
+
try:
|
| 627 |
+
client = openai.OpenAI(api_key=OPENAI_API_KEY)
|
| 628 |
+
|
| 629 |
+
messages = []
|
| 630 |
+
strategy_description = []
|
| 631 |
+
|
| 632 |
+
if "role-based" in strategy.lower() or "combined" in strategy.lower():
|
| 633 |
+
if role == "Technical analyst":
|
| 634 |
+
system_prompt = "You are a technical analyst providing precise, systematic analysis."
|
| 635 |
+
messages.append({"role": "system", "content": system_prompt})
|
| 636 |
+
strategy_description.append(f"System role: {role}")
|
| 637 |
+
elif role == "Creative assistant":
|
| 638 |
+
system_prompt = "You are a creative assistant providing thoughtful, engaging analysis."
|
| 639 |
+
messages.append({"role": "system", "content": system_prompt})
|
| 640 |
+
strategy_description.append(f"System role: {role}")
|
| 641 |
+
|
| 642 |
+
if task == "Sentiment Analysis":
|
| 643 |
+
user_message = f"Analyse the sentiment of the following text:\n\n{content}"
|
| 644 |
+
else: # Summarisation
|
| 645 |
+
user_message = f"Summarise the following text:\n\n{content}"
|
| 646 |
+
|
| 647 |
+
if "chain-of-thought" in strategy.lower() or "combined" in strategy.lower():
|
| 648 |
+
user_message += "\n\nThink through this step-by-step before providing your final answer."
|
| 649 |
+
strategy_description.append("Chain-of-thought reasoning")
|
| 650 |
+
|
| 651 |
+
if "direct" in strategy.lower():
|
| 652 |
+
strategy_description.append("Direct approach (no special technique)")
|
| 653 |
+
|
| 654 |
+
messages.append({"role": "user", "content": user_message})
|
| 655 |
+
|
| 656 |
+
strategy_description.append(f"Temperature: {temperature}")
|
| 657 |
+
|
| 658 |
+
# Generate response
|
| 659 |
+
response = client.chat.completions.create(
|
| 660 |
+
model="gpt-3.5-turbo",
|
| 661 |
+
messages=messages,
|
| 662 |
+
temperature=temperature,
|
| 663 |
+
max_tokens=800
|
| 664 |
+
)
|
| 665 |
+
|
| 666 |
+
output = response.choices[0].message.content
|
| 667 |
+
info = "Strategy applied:\n" + "\n".join(f"• {item}" for item in strategy_description)
|
| 668 |
+
|
| 669 |
+
return output, info
|
| 670 |
+
|
| 671 |
+
except Exception as e:
|
| 672 |
+
return f"Error: {str(e)}", "Error occurred"
|
| 673 |
+
|
| 674 |
+
def extract_text_from_file(file):
|
| 675 |
+
"""Extract text from uploaded file (TXT or PDF)"""
|
| 676 |
+
try:
|
| 677 |
+
if file.name.endswith('.txt'):
|
| 678 |
+
return file.read().decode('utf-8')
|
| 679 |
+
elif file.name.endswith('.pdf'):
|
| 680 |
+
pdf_reader = PyPDF2.PdfReader(file)
|
| 681 |
+
text = ""
|
| 682 |
+
for page in pdf_reader.pages:
|
| 683 |
+
text += page.extract_text()
|
| 684 |
+
return text
|
| 685 |
+
else:
|
| 686 |
+
return ""
|
| 687 |
+
except Exception as e:
|
| 688 |
+
return f"Error reading file: {str(e)}"
|
package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "my-app",
|
| 3 |
+
"version": "0.1.0",
|
| 4 |
+
"private": true,
|
| 5 |
+
"dependencies": {
|
| 6 |
+
"@radix-ui/react-slider": "^1.2.2",
|
| 7 |
+
"@shadcn/ui": "^0.0.4",
|
| 8 |
+
"classnames": "^2.5.1",
|
| 9 |
+
"cra-template": "1.2.0",
|
| 10 |
+
"react": "^19.0.0",
|
| 11 |
+
"react-dom": "^19.0.0",
|
| 12 |
+
"react-scripts": "5.0.1",
|
| 13 |
+
"web-vitals": "^4.2.4"
|
| 14 |
+
},
|
| 15 |
+
"scripts": {
|
| 16 |
+
"start": "react-scripts start",
|
| 17 |
+
"build": "react-scripts build",
|
| 18 |
+
"test": "react-scripts test",
|
| 19 |
+
"eject": "react-scripts eject"
|
| 20 |
+
},
|
| 21 |
+
"eslintConfig": {
|
| 22 |
+
"extends": [
|
| 23 |
+
"react-app",
|
| 24 |
+
"react-app/jest"
|
| 25 |
+
]
|
| 26 |
+
},
|
| 27 |
+
"browserslist": {
|
| 28 |
+
"production": [
|
| 29 |
+
">0.2%",
|
| 30 |
+
"not dead",
|
| 31 |
+
"not op_mini all"
|
| 32 |
+
],
|
| 33 |
+
"development": [
|
| 34 |
+
"last 1 chrome version",
|
| 35 |
+
"last 1 firefox version",
|
| 36 |
+
"last 1 safari version"
|
| 37 |
+
]
|
| 38 |
+
}
|
| 39 |
+
}
|
reportWebVitals.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const reportWebVitals = onPerfEntry => {
|
| 2 |
+
if (onPerfEntry && onPerfEntry instanceof Function) {
|
| 3 |
+
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
| 4 |
+
getCLS(onPerfEntry);
|
| 5 |
+
getFID(onPerfEntry);
|
| 6 |
+
getFCP(onPerfEntry);
|
| 7 |
+
getLCP(onPerfEntry);
|
| 8 |
+
getTTFB(onPerfEntry);
|
| 9 |
+
});
|
| 10 |
+
}
|
| 11 |
+
};
|
| 12 |
+
|
| 13 |
+
export default reportWebVitals;
|
requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
openai
|
| 3 |
+
huggingface_hub
|
| 4 |
+
transformers
|
| 5 |
+
torch
|
| 6 |
+
accelerate
|
| 7 |
+
PyPDF2
|
| 8 |
+
pypdfium2==4.20.0
|
| 9 |
+
tiktoken
|
| 10 |
+
transformers
|
| 11 |
+
torch
|
setupTests.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
| 2 |
+
// allows you to do things like:
|
| 3 |
+
// expect(element).toHaveTextContent(/react/i)
|
| 4 |
+
// learn more: https://github.com/testing-library/jest-dom
|
| 5 |
+
import '@testing-library/jest-dom';
|