paulbricman commited on
Commit
0c40d71
1 Parent(s): 03364a4

feat: backend find rework

Browse files
Files changed (37) hide show
  1. .gitignore +3 -2
  2. assets/SpaceGrotesk.ttf +0 -0
  3. assets/SpaceGrotesk.woff2 +0 -0
  4. assets/find_imag.html +0 -94
  5. assets/find_lang.html +0 -95
  6. assets/footer.html +0 -6
  7. assets/header.html +0 -1
  8. assets/save_imag.html +0 -26
  9. assets/save_lang.html +0 -31
  10. assets/style.css +0 -87
  11. assets/success.html +0 -11
  12. backend/main.py +15 -0
  13. backend/old_main.py +128 -0
  14. backend/responses.py +92 -0
  15. backend/security.py +35 -0
  16. backend/util.py +59 -0
  17. {.streamlit → frontend/.streamlit}/config.toml +5 -0
  18. {components → frontend/components}/__pycache__/auth.cpython-38.pyc +0 -0
  19. {components → frontend/components}/__pycache__/base.cpython-38.pyc +0 -0
  20. {components → frontend/components}/__pycache__/core.cpython-38.pyc +0 -0
  21. {components → frontend/components}/__pycache__/custodian.cpython-38.pyc +0 -0
  22. {components → frontend/components}/__pycache__/header.cpython-38.pyc +0 -0
  23. {components → frontend/components}/__pycache__/inspector.cpython-38.pyc +0 -0
  24. {components → frontend/components}/__pycache__/metadata.cpython-38.pyc +0 -0
  25. {components → frontend/components}/__pycache__/navigator.cpython-38.pyc +0 -0
  26. {components → frontend/components}/__pycache__/ranker.cpython-38.pyc +0 -0
  27. {components → frontend/components}/__pycache__/viewport.cpython-38.pyc +0 -0
  28. {components → frontend/components}/custodian.py +11 -10
  29. {components → frontend/components}/header.py +0 -0
  30. {components → frontend/components}/inspector.py +1 -1
  31. {components → frontend/components}/navigator.py +1 -1
  32. {components → frontend/components}/ranker.py +0 -0
  33. {components → frontend/components}/viewport.py +1 -3
  34. frontend/main.py +65 -0
  35. knowledge.py +0 -10
  36. main.py +0 -23
  37. util.py +39 -2
.gitignore CHANGED
@@ -1,3 +1,4 @@
1
  __pycache__/*
2
- conceptarium/*
3
- records/custodian.json
 
1
  __pycache__/*
2
+ backend/__pycache__/*
3
+ knowledge/*
4
+ backend/records.json
assets/SpaceGrotesk.ttf DELETED
Binary file (137 kB)
assets/SpaceGrotesk.woff2 DELETED
Binary file (42.7 kB)
assets/find_imag.html DELETED
@@ -1,94 +0,0 @@
1
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
2
- <link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen"/>
3
- <script src="//code.jquery.com/jquery-1.10.2.js"></script>
4
-
5
- <div class="board" style="position: fixed; top: 33%;">
6
- <script> $(function(){$("#header").load("/assets/header.html");}); </script>
7
- <div id="header"></div>
8
- <form action="/find/imag/html" method="POST" enctype="multipart/form-data">
9
- <div class="card">
10
- <div class="card-body">Find thoughts by imagery.</div>
11
- </div>
12
- <br />
13
- <div class="card">
14
- <div class="card-body">
15
- <input type="file" id="file" name="file" accept="image/*" required />
16
- </div>
17
- </div>
18
- <br />
19
- <div
20
- class="card"
21
- style="background-color: var(--background-color); border: 0"
22
- >
23
- <details>
24
- <summary style="color: var(--accent-color)">
25
- Customize search parameters...
26
- </summary>
27
- <table>
28
- <tr>
29
- <td
30
- style="color: var(--accent-color); font-weight: bold"
31
- title="Relatedness indicates how important it is for thoughts to be semantically close to the query."
32
- >
33
- <li>relatedness</li>
34
- </td>
35
- <td style="width: 10%">
36
- <input
37
- type="number"
38
- style="color: var(--accent-color)"
39
- value="1"
40
- step="0.01"
41
- id="relatedness"
42
- name="relatedness"
43
- />
44
- </td>
45
- </tr>
46
- <tr>
47
- <td
48
- style="color: var(--accent-color); font-weight: bold"
49
- title="Serendipity indicates how important it is for thoughts to have low activation."
50
- >
51
- <li>serendipity</li>
52
- </td>
53
- <td>
54
- <input
55
- type="number"
56
- style="color: var(--accent-color)"
57
- value="0"
58
- step="0.01"
59
- id="serendipity"
60
- name="serendipity"
61
- />
62
- </td>
63
- </tr>
64
- <tr>
65
- <td
66
- style="color: var(--accent-color); font-weight: bold"
67
- title="Noise indicates how much randomness there should be in the results."
68
- >
69
- <li>noise</li>
70
- </td>
71
- <td>
72
- <input
73
- type="number"
74
- style="color: var(--accent-color)"
75
- value="0.01"
76
- step="0.01"
77
- id="noise"
78
- name="noise"
79
- /><br />
80
- </td>
81
- </tr>
82
- </table>
83
- </details>
84
- </div>
85
- <br />
86
- <br />
87
- <div>
88
- <input class="button" type="submit" value="find" />
89
- </div>
90
- </form>
91
- </div>
92
-
93
- <script> $(function(){$("#footer").load("/assets/footer.html");}); </script>
94
- <div id="footer"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/find_lang.html DELETED
@@ -1,95 +0,0 @@
1
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
2
- <link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen"/>
3
- <script src="//code.jquery.com/jquery-1.10.2.js"></script>
4
-
5
-
6
- <div class="board" style="position: fixed; top: 33%;">
7
- <script> $(function(){$("#header").load("/assets/header.html");}); </script>
8
- <div id="header"></div>
9
- <form action="/find/lang/html" method="GET">
10
- <div class="card">
11
- <div class="card-body">Find thoughts by language.</div>
12
- </div>
13
- <br />
14
- <div class="card">
15
- <input
16
- name="content"
17
- id="content"
18
- class="card-body card-image"
19
- placeholder="Write your query here..."
20
- required
21
- ></input>
22
- </div>
23
- <br/>
24
- <div class="card" style="background-color: var(--background-color); border: 0;">
25
- <details>
26
- <summary style="color: var(--accent-color);">Customize search parameters...</summary>
27
- <table>
28
- <tr>
29
- <td
30
- style="color: var(--accent-color); font-weight: bold"
31
- title="Relatedness indicates how important it is for thoughts to be semantically close to the query."
32
- >
33
- <li>relatedness</li>
34
- </td>
35
- <td style="width: 10%">
36
- <input
37
- type="number"
38
- style="color: var(--accent-color)"
39
- value="1"
40
- step="0.01"
41
- id="relatedness"
42
- name="relatedness"
43
- />
44
- </td>
45
- </tr>
46
- <tr>
47
- <td
48
- style="color: var(--accent-color); font-weight: bold"
49
- title="Serendipity indicates how important it is for thoughts to have low activation."
50
- >
51
- <li>serendipity</li>
52
- </td>
53
- <td>
54
- <input
55
- type="number"
56
- style="color: var(--accent-color)"
57
- value="0"
58
- step="0.01"
59
- id="serendipity"
60
- name="serendipity"
61
- />
62
- </td>
63
- </tr>
64
- <tr>
65
- <td
66
- style="color: var(--accent-color); font-weight: bold"
67
- title="Noise indicates how much randomness there should be in the results."
68
- >
69
- <li>noise</li>
70
- </td>
71
- <td>
72
- <input
73
- type="number"
74
- style="color: var(--accent-color)"
75
- value="0.01"
76
- step="0.01"
77
- id="noise"
78
- name="noise"
79
- /><br />
80
- </td>
81
- </tr>
82
- </table>
83
- </details>
84
-
85
- </div>
86
- <br />
87
- <br />
88
- <div>
89
- <input type="submit" value="find" class="button" />
90
- </div>
91
- </form>
92
- </div>
93
-
94
- <script> $(function(){$("#footer").load("/assets/footer.html");}); </script>
95
- <div id="footer"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/footer.html DELETED
@@ -1,6 +0,0 @@
1
- <div style="position:fixed; bottom:0; height:auto; margin-top:40px;
2
- width:100%; text-align:center; padding-bottom: 1rem;">
3
- <a href="https://paulbricman.com/contact"><input type="submit" value="send feedback" class="button" /></a>&nbsp
4
- <a href="https://github.com/paulbricman/conceptarium#further-reading"><input type="submit" value="learn more" class="button" /></a>&nbsp
5
- <a href="https://github.com/sponsors/paulbricman"><input type="submit" value="support 🤍" class="button" /></a>
6
- </div>
 
 
 
 
 
 
assets/header.html DELETED
@@ -1 +0,0 @@
1
- <div class="header"><h2>🌿&nbspconceptarium.</h2></div>
 
assets/save_imag.html DELETED
@@ -1,26 +0,0 @@
1
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
2
- <link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen"/>
3
- <script src="//code.jquery.com/jquery-1.10.2.js"></script>
4
-
5
- <div class="board" style="position: fixed; top: 33%;">
6
- <script> $(function(){$("#header").load("/assets/header.html");}); </script>
7
- <div id="header"></div>
8
- <form action="/save/imag" method="POST" enctype="multipart/form-data">
9
- <div class="card">
10
- <div class="card-body">Save a thought expressed through imagery.</div>
11
- </div>
12
- <br />
13
- <div class="card">
14
- <div class="card-body">
15
- <input type="file" id="file" name="file" accept="image/*" required />
16
- </div>
17
- </div>
18
- <br /><br />
19
- <div>
20
- <input type="submit" value="save" class="button" />
21
- </div>
22
- </form>
23
- </div>
24
-
25
- <script> $(function(){$("#footer").load("/assets/footer.html");}); </script>
26
- <div id="footer"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/save_lang.html DELETED
@@ -1,31 +0,0 @@
1
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
2
- <link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen"/>
3
- <script src="//code.jquery.com/jquery-1.10.2.js"></script>
4
-
5
- <div class="board" style="position: fixed; top: 33%;">
6
- <script> $(function(){$("#header").load("/assets/header.html");}); </script>
7
- <div id="header"></div>
8
- <form action="/save/lang" method="GET">
9
- <div class="board">
10
- <div class="card">
11
- <div class="card-body">Save a thought expressed in language.</div>
12
- </div>
13
- <br />
14
- <div class="card">
15
- <textarea
16
- name="content"
17
- id="content"
18
- class="card-body card-image"
19
- required
20
- ></textarea>
21
- </div>
22
- <br /><br />
23
- <div>
24
- <input type="submit" value="save" class="button" />
25
- </div>
26
- </div>
27
- </form>
28
- </div>
29
-
30
- <script> $(function(){$("#footer").load("/assets/footer.html");}); </script>
31
- <div id="footer"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/style.css DELETED
@@ -1,87 +0,0 @@
1
- :root {
2
- --accent-color: #474539;
3
- --link-color: #228b22;
4
- --text-color: #fffffd;
5
- --background-color: #fffffd;
6
- }
7
-
8
- @font-face {
9
- font-family: "Space Grotesk";
10
- src: url("/assets/SpaceGrotesk.ttf") format('truetype'),
11
- url("/assets/SpaceGrotesk.woff2") format('woff2');
12
- }
13
-
14
- * {
15
- box-sizing: border-box;
16
- font-family: "Space Grotesk";
17
- }
18
-
19
- .board {
20
- font-size: 16;
21
- width: 100%;
22
- text-align: center;
23
- margin-bottom: 10px;
24
- }
25
-
26
- .header {
27
- color: var(--accent-color);
28
- text-align: center;
29
- }
30
-
31
- .header h2 {
32
- font-weight: bold;
33
- margin: 20px;
34
- font-size: 3rem;
35
- color: var(--accent-color);
36
- }
37
-
38
- body {
39
- background-color: var(--text-color);
40
- }
41
-
42
- .card-image {
43
- width: 100%;
44
- }
45
-
46
- .button {
47
- width: fit-content;
48
- border: 4px solid;
49
- border-color: var(--link-color);
50
- border-radius: 4px;
51
- background-color: var(--link-color);
52
- color: var(--text-color);
53
- font-weight: bold;
54
- padding-left: 10px;
55
- padding-right: 10px;
56
- }
57
-
58
- .card {
59
- box-sizing: border-box;
60
- border: 4px solid;
61
- border-color: var(--accent-color);
62
- background-color: var(--accent-color);
63
- display: inline-block;
64
- margin: 10px;
65
- margin-bottom: 0px;
66
- width: 40rem;
67
- color: var(--text-color);
68
- font-weight: bold;
69
- text-align: left;
70
- }
71
-
72
- @media only screen and (max-width: 1200px) {
73
- .card {
74
- width: calc(100% - 40px);
75
- margin: 20px;
76
- margin-bottom: 0px;
77
- font-size: 1.5rem !important;
78
- }
79
-
80
- .button {
81
- font-size: 1.5rem !important;
82
- }
83
-
84
- .header h2 {
85
- font-size: 3rem !important;
86
- }
87
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
assets/success.html DELETED
@@ -1,11 +0,0 @@
1
- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"/>
2
- <link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen"/>
3
- <script src="//code.jquery.com/jquery-1.10.2.js"></script>
4
-
5
- <div class="board" style="position: fixed; top: 33%;">
6
- <script> $(function(){$("#header").load("/assets/header.html");}); </script>
7
- <div id="header"></div>
8
- <div class="card">
9
- <div class="card-body">Thought saved successfully.</div>
10
- </div>
11
- </div>
 
 
 
 
 
 
 
 
 
 
 
backend/main.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from security import auth
3
+ from util import find
4
+ from sentence_transformers import SentenceTransformer
5
+
6
+
7
+ app = FastAPI()
8
+ encoder_model = SentenceTransformer('clip-ViT-B-32')
9
+
10
+
11
+ @app.get('/find')
12
+ async def find_handler(query: str, token: str):
13
+ auth_result = auth(token)
14
+ results = find('text', query, auth_result, encoder_model)
15
+ return results
backend/old_main.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, File, BackgroundTasks
2
+ from fastapi.datastructures import UploadFile
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import HTMLResponse, PlainTextResponse, FileResponse
5
+ import secrets
6
+ from pathlib import Path
7
+ from typing import Optional
8
+ from PIL import Image
9
+ import io
10
+
11
+ from fastapi.old_util import *
12
+ from responses import *
13
+
14
+ app = FastAPI()
15
+ model = load_model()
16
+ init()
17
+
18
+ app.mount('/conceptarium', StaticFiles(directory='conceptarium'))
19
+ app.mount('/assets', StaticFiles(directory='assets'))
20
+
21
+
22
+ @app.get('/save/lang/form')
23
+ async def save_language_form():
24
+ return HTMLResponse(save_lang_form_response())
25
+
26
+
27
+ @app.get('/save/imag/form')
28
+ async def save_imagery_form():
29
+ return HTMLResponse(save_imag_form_response())
30
+
31
+
32
+ @app.get('/save/lang')
33
+ async def save_language(content: str, background_tasks: BackgroundTasks):
34
+ if len(content) > 0:
35
+ filename = 'conceptarium/' + secrets.token_urlsafe(8) + '.txt'
36
+ open(filename, 'w').write(content)
37
+ background_tasks.add_task(save, Thought(filename, content, model))
38
+ return HTMLResponse(save_success_response())
39
+
40
+
41
+ @app.post('/save/imag')
42
+ async def save_imagery(file: UploadFile = File(...)):
43
+ content = await file.read()
44
+ image = Image.open(io.BytesIO(content)).convert('RGB')
45
+ filename = 'conceptarium/' + secrets.token_urlsafe(8) + '.jpg'
46
+ image.save(filename, quality=50)
47
+ save(Thought(filename, content, model))
48
+ return HTMLResponse(save_success_response())
49
+
50
+
51
+ @app.get('/find/lang/form')
52
+ async def find_by_language_form():
53
+ return HTMLResponse(find_lang_form_response())
54
+
55
+
56
+ @app.get('/find/lang/html')
57
+ async def find_by_language_return_html(content: str, relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
58
+ thoughts = find(content, model, relatedness,
59
+ serendipity, noise, silent, top_k)
60
+ return HTMLResponse(html_response(thoughts))
61
+
62
+
63
+ @app.get('/find/lang/text')
64
+ async def find_by_language_return_plaintext(content: str, relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
65
+ thoughts = find(content, model, relatedness,
66
+ serendipity, noise, silent, top_k)
67
+ return PlainTextResponse(plaintext_response(thoughts))
68
+
69
+
70
+ @app.get('/find/lang/file')
71
+ async def find_by_language_return_file(content: str, relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
72
+ thoughts = find(content, model, relatedness,
73
+ serendipity, noise, silent, top_k)
74
+ return FileResponse(file_response(thoughts))
75
+
76
+
77
+ @app.get('/find/lang/json')
78
+ async def find_by_language_return_json(content: str, relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
79
+ thoughts = find(content, model, relatedness,
80
+ serendipity, noise, silent, top_k)
81
+ return json_response(thoughts)
82
+
83
+
84
+ @app.get('/find/imag/form')
85
+ async def find_by_imagery_form():
86
+ return HTMLResponse(find_imag_form_response())
87
+
88
+
89
+ @app.post('/find/imag/html')
90
+ async def find_by_imagery_return_html(file: UploadFile = File(...), relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
91
+ content = await file.read()
92
+ thoughts = find(content, model, relatedness,
93
+ serendipity, noise, silent, top_k)
94
+ return HTMLResponse(html_response(thoughts))
95
+
96
+
97
+ @app.post('/find/imag/text')
98
+ async def find_by_imagery_return_plaintext(file: UploadFile = File(...), relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
99
+ content = await file.read()
100
+ thoughts = find(content, model, relatedness,
101
+ serendipity, noise, silent, top_k)
102
+ return PlainTextResponse(plaintext_response(thoughts))
103
+
104
+
105
+ @app.post('/find/imag/file')
106
+ async def find_by_imagery_return_file(file: UploadFile = File(...), relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
107
+ content = await file.read()
108
+ thoughts = find(content, model, relatedness,
109
+ serendipity, noise, silent, top_k)
110
+ return FileResponse(file_response(thoughts))
111
+
112
+
113
+ @app.post('/find/imag/json')
114
+ async def find_by_imagery_return_json(file: UploadFile = File(...), relatedness: Optional[float] = 1, serendipity: Optional[float] = 0, noise: Optional[float] = 0.01, silent: Optional[bool] = False, top_k: Optional[int] = 50):
115
+ content = await file.read()
116
+ thoughts = find(content, model, relatedness,
117
+ serendipity, noise, silent, top_k)
118
+ return json_response(thoughts)
119
+
120
+
121
+ @app.get('/rset/embs')
122
+ async def reset_embeddings_handle():
123
+ reset_embeddings(model)
124
+
125
+
126
+ @app.get('/dump')
127
+ async def dump_conceptarium():
128
+ return FileResponse(archive_response(), filename='conceptarium.zip')
backend/responses.py ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi.old_util import get_doc_paths
2
+ from zipfile import ZipFile
3
+ import numpy as np
4
+ import time
5
+
6
+
7
+ def html_response(thoughts):
8
+ html = '<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">'
9
+ html += '<link rel="stylesheet" type="text/css" href="/assets/style.css" media="screen" />'
10
+ html += '<script src="//code.jquery.com/jquery-1.10.2.js"></script>'
11
+ html += '<script> $(function(){$("#header").load("/assets/header.html");}); </script>'
12
+ html += '<div id="header""></div><div class="board">'
13
+
14
+ for thought in thoughts:
15
+ html += '<div class="card">'
16
+ if thought.modality == 'language':
17
+ content = open(thought.filename, 'r').read()
18
+ html += '<div class="card-body">' + content + '</div>'
19
+ else:
20
+ html += '<img class="card-img" src=\"/' + \
21
+ thought.filename + '\">'
22
+ html += '</div><br/>'
23
+
24
+ html += '</div>'
25
+ return html
26
+
27
+
28
+ def save_success_response():
29
+ return open('assets/success.html').read()
30
+
31
+
32
+ def save_lang_form_response():
33
+ return open('assets/save_lang.html').read()
34
+
35
+
36
+ def save_imag_form_response():
37
+ return open('assets/save_imag.html').read()
38
+
39
+
40
+ def find_lang_form_response():
41
+ return open('assets/find_lang.html').read()
42
+
43
+
44
+ def find_imag_form_response():
45
+ return open('assets/find_imag.html').read()
46
+
47
+
48
+ def archive_response():
49
+ paths = get_doc_paths('conceptarium')
50
+ with ZipFile('conceptarium.zip', 'w') as zip:
51
+ for path in paths:
52
+ zip.write(path)
53
+
54
+ return 'conceptarium.zip'
55
+
56
+
57
+ def plaintext_response(thoughts):
58
+ plaintext = ''
59
+
60
+ for thought in thoughts:
61
+ if thought.modality == 'language':
62
+ content = open(thought.filename, 'r').read()
63
+ plaintext += '\"' + content + '\"\n'
64
+
65
+ return plaintext
66
+
67
+
68
+ def file_response(thoughts):
69
+ for thought in thoughts:
70
+ if thought.modality == 'imagery':
71
+ return thought.filename
72
+
73
+
74
+ def json_response(thoughts):
75
+ response_json = []
76
+
77
+ for thought in thoughts:
78
+ thought_json = {
79
+ 'timestamp': thought.timestamp,
80
+ 'interest': thought.interest,
81
+ 'activation': np.log(thought.interest / (1 - 0.9)) - 0.9 * np.log((time.time() - thought.timestamp) / (3600 * 24) + 0.1),
82
+ 'modality': thought.modality,
83
+ 'embedding': thought.embedding.tolist(),
84
+ }
85
+
86
+ if thought.modality == 'language':
87
+ thought_json['content'] = open(thought.filename, 'r').read()
88
+ else:
89
+ thought_json['filename'] = '/' + thought.filename
90
+
91
+ response_json += [thought_json]
92
+ return response_json
backend/security.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pathlib import Path
2
+ import json
3
+ import bcrypt
4
+
5
+
6
+ def auth(token):
7
+ path = Path('records.json')
8
+
9
+ if not path.exists():
10
+ salt = bcrypt.gensalt()
11
+ hashed_token = bcrypt.hashpw(token.encode(
12
+ 'utf8'), salt).decode('utf8')
13
+
14
+ records = {
15
+ 'custodian_hashed_token': hashed_token,
16
+ 'custodian_hashed_token_salt': salt.decode('utf8')
17
+ }
18
+ json.dump(records, open(path, 'w'))
19
+
20
+ return {
21
+ 'custodian': True
22
+ }
23
+ else:
24
+ records = json.load(open(path))
25
+ hashed_token = bcrypt.hashpw(token.encode(
26
+ 'utf-8'), records['custodian_hashed_token_salt'].encode('utf8')).decode('utf8')
27
+
28
+ if records['custodian_hashed_token'] == hashed_token:
29
+ return {
30
+ 'custodian': True
31
+ }
32
+ else:
33
+ return {
34
+ 'custodian': False
35
+ }
backend/util.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ from pathlib import Path
3
+ from PIL import Image
4
+ import io
5
+ from sentence_transformers import util
6
+ import torch
7
+ import base64
8
+
9
+
10
+ def find(modality, query, auth_result, encoder_model):
11
+ authorized_thoughts = get_authorized_thoughts(auth_result)
12
+
13
+ if len(authorized_thoughts) == 0:
14
+ return []
15
+
16
+ query_embedding = torch.Tensor([embed(modality, query, encoder_model)])
17
+ print('query_embedding.size()', query_embedding.size())
18
+ corpus_embeddings = torch.Tensor(
19
+ [e['embedding'] for e in authorized_thoughts])
20
+ results = util.semantic_search(
21
+ query_embedding, corpus_embeddings, top_k=10 ** 10)
22
+
23
+ for e in results[0]:
24
+ authorized_thoughts[e['corpus_id']]['relatedness'] = e['score']
25
+ authorized_thoughts[e['corpus_id']]['content'] = get_content(
26
+ authorized_thoughts[e['corpus_id']])
27
+ authorized_thoughts[e['corpus_id']].pop('filename', None)
28
+
29
+ return authorized_thoughts
30
+
31
+
32
+ def get_authorized_thoughts(auth_result):
33
+ metadata_path = Path('..') / 'knowledge' / 'base' / 'metadata.json'
34
+
35
+ if auth_result['custodian'] == True:
36
+ return json.load(open(metadata_path))
37
+ else:
38
+ return []
39
+
40
+
41
+ def embed(modality, content, encoder_model):
42
+ if modality == 'text':
43
+ return encoder_model.encode(content)
44
+ elif modality == 'image':
45
+ return encoder_model.encode(Image.open(io.BytesIO(content)))
46
+
47
+
48
+ def get_content(thought, json_friendly=False):
49
+ knowledge_base_path = Path('..') / 'knowledge' / 'base'
50
+
51
+ if thought['modality'] == 'text':
52
+ content = open(knowledge_base_path / thought['filename']).read()
53
+ elif thought['modality'] == 'image':
54
+ content = open(knowledge_base_path / thought['filename'], 'rb').read()
55
+
56
+ if json_friendly:
57
+ content = base64.encodebytes(content).decode('utf8')
58
+
59
+ return content
{.streamlit → frontend/.streamlit}/config.toml RENAMED
@@ -2,3 +2,8 @@
2
  base="light"
3
  primaryColor="#228b22"
4
  font="monospace"
 
 
 
 
 
2
  base="light"
3
  primaryColor="#228b22"
4
  font="monospace"
5
+
6
+ [server]
7
+ enableCORS = false
8
+ enableXsrfProtection = false
9
+ headless = true
{components → frontend/components}/__pycache__/auth.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/base.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/core.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/custodian.cpython-38.pyc RENAMED
Binary files a/components/__pycache__/custodian.cpython-38.pyc and b/frontend/components/__pycache__/custodian.cpython-38.pyc differ
{components → frontend/components}/__pycache__/header.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/inspector.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/metadata.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/navigator.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/ranker.cpython-38.pyc RENAMED
File without changes
{components → frontend/components}/__pycache__/viewport.cpython-38.pyc RENAMED
Binary files a/components/__pycache__/viewport.cpython-38.pyc and b/frontend/components/__pycache__/viewport.cpython-38.pyc differ
{components → frontend/components}/custodian.py RENAMED
@@ -9,11 +9,12 @@ def paint():
9
  st.markdown('#### 📜 custodian')
10
 
11
  if not os.path.exists('records/custodian.json'):
12
- st.warning('This appears to be a fresh conceptarium instance. Please create a custodian account.')
13
-
 
14
  username = st.text_input('Username')
15
  password = st.text_input('Password', type='password')
16
-
17
  if st.button('create account'):
18
  password = stauth.hasher([password]).generate()[0]
19
  token = stauth.hasher([password + 'token']).generate()[0]
@@ -24,13 +25,13 @@ def paint():
24
  }, open('records/custodian.json', 'w'))
25
  st.balloons()
26
  else:
27
- st.warning('If you\'re the custodian of this conceptarium, please log into your account to access your stored thoughts.')
 
28
  custodian = json.load(open('records/custodian.json'))
29
- authenticator = stauth.authenticate([custodian['username']], [custodian['username']] , [custodian['password']],
30
- 'custodian_cookie', 'conceptarium', cookie_expiry_days=30)
31
- name, authentication_status = authenticator.login('login', 'sidebar')
32
-
33
- print(name, authentication_status)
34
 
35
  if st.session_state['authentication_status']:
36
  st.markdown('')
@@ -39,4 +40,4 @@ def paint():
39
  elif st.session_state['authentication_status'] == False:
40
  st.error('Username/password is incorrect')
41
  elif st.session_state['authentication_status'] == None:
42
- st.warning('Please enter your username and password')
9
  st.markdown('#### 📜 custodian')
10
 
11
  if not os.path.exists('records/custodian.json'):
12
+ st.warning(
13
+ 'This appears to be a fresh conceptarium instance. Please create a custodian account.')
14
+
15
  username = st.text_input('Username')
16
  password = st.text_input('Password', type='password')
17
+
18
  if st.button('create account'):
19
  password = stauth.hasher([password]).generate()[0]
20
  token = stauth.hasher([password + 'token']).generate()[0]
25
  }, open('records/custodian.json', 'w'))
26
  st.balloons()
27
  else:
28
+ st.warning(
29
+ 'If you\'re the custodian of this conceptarium, please log into your account to access your stored thoughts.')
30
  custodian = json.load(open('records/custodian.json'))
31
+ authenticator = stauth.authenticate([custodian['username']], [custodian['username']], [custodian['password']],
32
+ 'custodian_cookie', 'conceptarium', cookie_expiry_days=30)
33
+ name, authentication_status = authenticator.login(
34
+ 'login', 'sidebar')
 
35
 
36
  if st.session_state['authentication_status']:
37
  st.markdown('')
40
  elif st.session_state['authentication_status'] == False:
41
  st.error('Username/password is incorrect')
42
  elif st.session_state['authentication_status'] == None:
43
+ st.warning('Please enter your username and password')
{components → frontend/components}/header.py RENAMED
File without changes
{components → frontend/components}/inspector.py RENAMED
@@ -1,5 +1,5 @@
1
  import streamlit as st
2
- import knowledge
3
  from datetime import datetime
4
  import numpy as np
5
  import time
1
  import streamlit as st
2
+ import knowledge.knowledge as knowledge
3
  from datetime import datetime
4
  import numpy as np
5
  import time
{components → frontend/components}/navigator.py RENAMED
@@ -3,7 +3,7 @@ from sentence_transformers import SentenceTransformer
3
  import io
4
  from PIL import Image
5
  import torch
6
- import knowledge
7
 
8
 
9
  def get_name():
3
  import io
4
  from PIL import Image
5
  import torch
6
+ import knowledge.knowledge as knowledge
7
 
8
 
9
  def get_name():
{components → frontend/components}/ranker.py RENAMED
File without changes
{components → frontend/components}/viewport.py RENAMED
@@ -1,5 +1,5 @@
1
  import streamlit as st
2
- import knowledge
3
  from sentence_transformers import util
4
  import torch
5
  import numpy as np
@@ -17,8 +17,6 @@ def load_thoughts():
17
  imagery_centroid = torch.mean(torch.stack(
18
  [e.embedding for e in thoughts if e.modality == 'imagery']), -2)
19
 
20
- print(imagery_centroid - langauge_centroid)
21
-
22
  for thought_idx, thought in enumerate(thoughts):
23
  if thought.modality == 'imagery':
24
  thoughts[thought_idx].embedding += langauge_centroid - \
1
  import streamlit as st
2
+ import knowledge.knowledge as knowledge
3
  from sentence_transformers import util
4
  import torch
5
  import numpy as np
17
  imagery_centroid = torch.mean(torch.stack(
18
  [e.embedding for e in thoughts if e.modality == 'imagery']), -2)
19
 
 
 
20
  for thought_idx, thought in enumerate(thoughts):
21
  if thought.modality == 'imagery':
22
  thoughts[thought_idx].embedding += langauge_centroid - \
frontend/main.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from components import custodian, header, inspector, navigator, viewport, ranker
3
+ import uvicorn
4
+
5
+
6
+ st.set_page_config(
7
+ page_title='💡 conceptarium',
8
+ layout='wide',
9
+ menu_items={
10
+ 'About': 'hello world'
11
+ })
12
+
13
+
14
+ # if not hasattr(st, 'already_started_server'):
15
+ # # Hack the fact that Python modules (like st) only load once to
16
+ # # keep track of whether this file already ran.
17
+ # st.already_started_server = True
18
+
19
+ # st.write('''
20
+ # The first time this script executes it will run forever because it's
21
+ # running a Flask server.
22
+
23
+ # Just close this browser tab and open a new one to see your Streamlit
24
+ # app.
25
+ # ''')
26
+
27
+ # from flask import Flask
28
+
29
+ # app = Flask(__name__)
30
+
31
+ # @app.route('/foo')
32
+ # def serve_foo():
33
+ # return 'This page is served via Flask!' + str(st.session_state['authentication_status'])
34
+
35
+ # app.run(port=8888)
36
+
37
+ # # from fastapi import FastAPI
38
+
39
+ # # app = FastAPI()
40
+
41
+ # # @app.get("/")
42
+ # # async def root():
43
+ # # return {"message": "Hello World"}
44
+
45
+ # # print('running next')
46
+ # # uvicorn.run(app, port=8888)
47
+ # # print('ran')
48
+
49
+
50
+ custodian.paint()
51
+ header.paint()
52
+
53
+ cols = st.columns(5)
54
+
55
+ for component in [navigator, ranker]:
56
+ with cols[0]:
57
+ with st.expander(component.get_name(), True):
58
+ component.paint()
59
+
60
+ for component in [inspector]:
61
+ with cols[-1]:
62
+ with st.expander(component.get_name(), True):
63
+ component.paint()
64
+
65
+ viewport.paint(cols[1:-1])
knowledge.py DELETED
@@ -1,10 +0,0 @@
1
- import streamlit as st
2
- import pickle
3
-
4
-
5
- def load():
6
- if st.session_state['authentication_status']:
7
- thoughts = pickle.load(open('conceptarium/metadata.pickle', 'rb'))
8
- return thoughts
9
- else:
10
- return []
 
 
 
 
 
 
 
 
 
 
main.py DELETED
@@ -1,23 +0,0 @@
1
- import streamlit as st
2
- from components import custodian, header, inspector, navigator, viewport, ranker
3
-
4
- st.set_page_config(
5
- page_title='💡 conceptarium',
6
- layout='wide')
7
-
8
- custodian.paint()
9
- header.paint()
10
-
11
- cols = st.columns(5)
12
-
13
- for component in [navigator, ranker]:
14
- with cols[0]:
15
- with st.expander(component.get_name(), True):
16
- component.paint()
17
-
18
- for component in [inspector]:
19
- with cols[-1]:
20
- with st.expander(component.get_name(), True):
21
- component.paint()
22
-
23
- viewport.paint(cols[1:-1])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
util.py CHANGED
@@ -123,9 +123,46 @@ class Thought:
123
  self.interest = 1
124
  self.embedding = embed(content, model)
125
 
126
-
127
  def get_content(self):
128
  if self.modality == 'language':
129
  return open(self.filename).read()
130
  elif self.modality == 'imagery':
131
- return open(self.filename, 'rb').read()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  self.interest = 1
124
  self.embedding = embed(content, model)
125
 
 
126
  def get_content(self):
127
  if self.modality == 'language':
128
  return open(self.filename).read()
129
  elif self.modality == 'imagery':
130
+ return open(self.filename, 'rb').read()
131
+
132
+
133
+ '''
134
+ import json
135
+ thoughts = json.load(open('knowledge/base/metadata.json', 'rb'))
136
+
137
+ from datetime import datetime
138
+ new_thoughts = []
139
+ for thought in thoughts:
140
+ new_thought = {}
141
+ new_thought['filename'] = thought.filename
142
+ new_thought['modality'] = thought.modality
143
+ new_thought['timestamp'] = thought.timestamp
144
+ new_thought['interest'] = thought.interest
145
+ new_thought['embedding'] = thought.embedding
146
+ new_thoughts += [new_thought]
147
+
148
+ for e_idx, e in enumerate(new_thoughts):
149
+ if e['modality'] == 'language':
150
+ new_thoughts[e_idx]['modality'] = 'text'
151
+ elif e['modality'] == 'imagery':
152
+ new_thoughts[e_idx]['modality'] = 'image'
153
+ else:
154
+ print(e['modality'])
155
+
156
+ for e_idx, e in enumerate(new_thoughts):
157
+ new_thoughts[e_idx]['embedding'] = e['embedding'].tolist()
158
+
159
+ for e_idx, e in enumerate(new_thoughts):
160
+ new_thoughts[e_idx]['embedding'] = [round(f, 6) for f in e['embedding']]
161
+
162
+ for e_idx, e in enumerate(new_thoughts):
163
+ new_thoughts[e_idx]['filename'] = e['filename'].split('/')[-1]
164
+
165
+ new_thoughts[0]
166
+
167
+ json.dump(new_thoughts, open('knowledge/base/metadata.json', 'wb'))
168
+ '''