Skip to content

Commit 3aa2703

Browse files
[IMPORTANT]: Import EduVision Evaluation Function (#1)
* feat: main functionality upload from own repo * fix(#1): private changes, .env
1 parent 56ff77e commit 3aa2703

9 files changed

Lines changed: 141 additions & 33 deletions

File tree

.github/workflows/test-and-deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ jobs:
2323

2424
env:
2525
SCHEMAS_URL: https://raw.githubusercontent.com/lambda-feedback/request-response-schemas/master/
26+
API_CONNECTION: ${{secrets.API_CONNECTION}}
2627

2728
steps:
2829
- name: Checkout

app/docs/dev.md

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,89 @@
1-
# YourFunctionName
2-
*Brief description of what this evaluation function does, from the developer perspective*
1+
# eduVision
2+
Handle all API calls to external services.
3+
4+
For now, we have examples and API structure prepare for the EduVision Proof of Concept Application.
35

46
## Inputs
5-
*Specific input parameters which can be supplied when the `eval` command is supplied to this function.*
7+
8+
- `response` (Any): The answers provided by the student. It can be a ID of the instance, a list of IDs, a list of dictionaries, etc. to handle the response from the API.
9+
- `answer` (Any): The correct answers to compare against the API response.
10+
- `params` (Dict): Important endpoint information to make the API call to EduVision API Server. Storing ````endpoint``` information.
11+
12+
```
13+
{server}/{endpoint}{response}
14+
```
615

716
## Outputs
8-
*Output schema/values for this function*
17+
Return result value is a boolean.
18+
19+
```python
20+
{
21+
"is_correct": true
22+
}
23+
```
924

1025
## Examples
11-
*List of example inputs and outputs for this function, each under a different sub-heading*
26+
For now, we have examples for the EduVision Proof of Concept Application.
1227

13-
### Simple Evaluation
28+
### EduVision Application
29+
30+
There is 2 endpoints to call the API. The first one is to get the list of all the students and the second one is to get the list of all the courses.
31+
32+
#### Resistors
33+
Check how many resistors is recognized with its resistance value.
34+
***Answer value must be dictionary.***
35+
36+
```python
37+
{
38+
"headers": {
39+
"command": "eval"
40+
},
41+
"body": {
42+
"response": "999999",
43+
"answer": [],
44+
"params": {
45+
"api_endpoint": "endpoint/"
46+
}
47+
}
48+
}
49+
```
1450

1551
```python
1652
{
17-
"example": {
18-
"Something": "something"
53+
"headers": {
54+
"command": "eval"
55+
},
56+
"body": {
57+
"response": "999999",
58+
"answer": [
59+
{
60+
"resistance": 1000.0,
61+
},
62+
{
63+
"resistance": 1000.0,
64+
},
65+
],
66+
"params": {
67+
"api_endpoint": "endpoint/"
68+
}
1969
}
2070
}
2171
```
72+
#### Resistance
73+
Check global resistance of the circuit
74+
***Answer value must be float.***
2275

2376
```python
2477
{
25-
"example": {
26-
"Something": "something"
78+
"headers": {
79+
"command": "eval"
80+
},
81+
"body": {
82+
"response": "999999",
83+
"answer": 1000.0,
84+
"params": {
85+
"api_endpoint": "endpoint/"
86+
}
2787
}
2888
}
2989
```

app/docs/user.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
# YourFunctionName
1+
# eduVision
22

3-
Teacher-facing documentation for this function.
3+
Evaluation Function to handle all API calls to external services.
4+
It assumes that response from API is equal to the expected answer.
5+
6+
Function is prepare for EduVision Proof of Concept Application for now.

app/evaluation.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1+
import os
12
from typing import Any, TypedDict
2-
3-
4-
class Params(TypedDict):
5-
pass
6-
3+
import requests
74

85
class Result(TypedDict):
96
is_correct: bool
107

118

12-
def evaluation_function(response: Any, answer: Any, params: Params) -> Result:
9+
def evaluation_function(response: Any, answer: Any, params: Any) -> Result:
1310
"""
1411
Function used to evaluate a student response.
1512
---
@@ -33,4 +30,18 @@ def evaluation_function(response: Any, answer: Any, params: Params) -> Result:
3330
to output the evaluation response.
3431
"""
3532

36-
return Result(is_correct=True)
33+
try:
34+
api_endpoint = params.get("api_endpoint", 'resistance/')
35+
36+
if len(response) != 6:
37+
raise Exception("Connection ID must be 6 characters long")
38+
39+
api_response = requests.get(f"{os.environ["API_CONNECTION"]}/{api_endpoint}{response}")
40+
api_response.raise_for_status()
41+
api_data = api_response.json()
42+
is_correct = api_data == answer
43+
except requests.RequestException as e:
44+
print(f"Error API connection: {e}")
45+
is_correct = False
46+
47+
return Result(is_correct=is_correct)

app/evaluation_tests.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
import os
12
import unittest
3+
from app.utility import initialize_test_connection
24

35
try:
46
from .evaluation import Params, evaluation_function
57
except ImportError:
68
from evaluation import Params, evaluation_function
79

810

11+
912
class TestEvaluationFunction(unittest.TestCase):
1013
"""
1114
TestCase Class used to test the algorithm.
@@ -25,12 +28,13 @@ class TestEvaluationFunction(unittest.TestCase):
2528
as it should.
2629
"""
2730

28-
def test_returns_is_correct_true(self):
29-
response, answer, params = None, None, Params()
31+
def test_connection(self):
32+
id_connection = initialize_test_connection()
33+
34+
response, answer, params = id_connection, 0.0, {"api_endpoint": "resistance/"}
3035
result = evaluation_function(response, answer, params)
3136

3237
self.assertEqual(result.get("is_correct"), True)
3338

34-
3539
if __name__ == "__main__":
3640
unittest.main()

app/preview.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1+
import os
12
from typing import Any, TypedDict
2-
3-
4-
class Params(TypedDict):
5-
pass
6-
3+
import requests
74

85
class Result(TypedDict):
96
preview: Any
107

118

12-
def preview_function(response: Any, params: Params) -> Result:
9+
def preview_function(response: Any, params: Any) -> Result:
1310
"""
1411
Function used to preview a student response.
1512
---
@@ -29,4 +26,14 @@ def preview_function(response: Any, params: Params) -> Result:
2926
The way you wish to structure you code (all in this function, or
3027
split into many) is entirely up to you.
3128
"""
32-
return Result(preview=response)
29+
try:
30+
api_endpoint = params.get("api_endpoint", 'resistance/')
31+
32+
api_response = requests.get(f"{os.environ["API_CONNECTION"]}/{api_endpoint}{response}")
33+
api_response.raise_for_status()
34+
api_data = api_response.json()
35+
except requests.RequestException as e:
36+
print(f"Error API connection: {e}")
37+
api_data = None
38+
39+
return Result(preview=api_data)

app/preview_tests.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import unittest
2+
from app.utility import initialize_test_connection
23

34
try:
4-
from .preview import Params, preview_function
5+
from .preview import preview_function
56
except ImportError:
6-
from preview import Params, preview_function
7+
from preview import preview_function
78

89

910
class TestPreviewFunction(unittest.TestCase):
@@ -25,8 +26,17 @@ class TestPreviewFunction(unittest.TestCase):
2526
as it should.
2627
"""
2728

28-
def test_returns_preview_key(self):
29-
response, params = "test", Params()
29+
def test_api_endpoint_resistance(self):
30+
id_connection = initialize_test_connection()
31+
response, params = id_connection, {"api_endpoint": "resistance/"}
32+
result = preview_function(response, params)
33+
34+
self.assertIn("preview", result)
35+
self.assertIsNotNone(result["preview"])
36+
37+
def test_api_endpoint_resistors(self):
38+
id_connection = initialize_test_connection()
39+
response, params = id_connection, {"api_endpoint": "resistors/"}
3040
result = preview_function(response, params)
3141

3242
self.assertIn("preview", result)

app/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
requests
2+
dotenv

app/utility.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import os
2+
import requests
3+
4+
def initialize_test_connection():
5+
response = requests.post(f"{os.environ["API_CONNECTION"]}/initialize")
6+
if response.status_code == 200:
7+
connection_id = response.json().get("connection_id")
8+
else:
9+
raise Exception("Failed to initialize connection with the API")
10+
return connection_id

0 commit comments

Comments
 (0)