diff options
author | Nate Buttke <nate-web@riseup.net> | 2023-07-27 17:29:36 -0700 |
---|---|---|
committer | Nate Buttke <nate-web@riseup.net> | 2023-07-27 17:29:36 -0700 |
commit | db824e067d17eba3469a49dffb04566aed3449b2 (patch) | |
tree | 3cedc59cf4824f1774e2f9b9148857cedea1ab68 | |
parent | ad9ebbe7c78c2cf7c717d7898534371d59f325d9 (diff) |
add frontend components with my fixes. still messy.
-rw-r--r-- | frontend/index.html | 132 | ||||
-rw-r--r-- | frontend/jsmain.js | 0 | ||||
-rw-r--r-- | frontend/style.css | 138 | ||||
-rw-r--r-- | server.py | 135 |
4 files changed, 405 insertions, 0 deletions
diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..47060ab --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,132 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="preconnect" href="https://fonts.googleapis.com"> + <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> + <link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;400;900&display=swap" rel="stylesheet"> + + <script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js"></script> + <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.0/dist/semantic.min.css"> + <script src="https://cdn.jsdelivr.net/npm/fomantic-ui@2.9.0/dist/semantic.min.js"></script> + + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flexboxgrid@6.3.1/dist/flexboxgrid.min.css"> + <!-- <link rel="icon" type="image/x-icon" href="./assets/logo.ico"> --> + <link rel="stylesheet" + href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark-reasonable.min.css"> + <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script> + + <link href="./style.css" rel="stylesheet"> + <title>talktoANYcode</title> + </head> + <body> + <div id="main-content" class="row center-xs"> + <div id="spinny"> + <div class="ui active inverted dimmer"> + <div class="ui large text loader" id="loader">Querying...</div> + </div> + <p></p> + <p></p> + <p></p> + </div> + <div class="col-xs-12 col-md-12 center-xs"> + <a href="/" style="text-decoration: none;"> + <h1 id="jumbo-title">talkto<span style="color:tomato">ANY</span>code</h1> + </a> + </div> + <div class="row center-xs col-xs-12" id="qa"> + <div class="ui action input col-xs-8" > + <input type="text" placeholder="Talk to Code!" id="talk-text" style="font-size: 20px;"> + <button class="ui red button" id="talk-button">Search</button> + <button class="ui red button" id="talk-button-2">Explain</button> + </div> + </div> + <div id="main-title"></div> + <div class="row center-xs col-xs-12" id="main"> + + </div> + <div class="col-xs-12 center-xs footie"> + <p> + <a class="col-xs-12 ui white label" href="https://git.nategb.xyz/talk-to-any-code.git/" target="_blank"> + <i class="key icon"></i> + git.nategb.xyz/talk-to-any-code.git/ + </a> + <span style="color:white">forked from</span> + <a class="col-xs-12 ui white label" href="https://github.com/nuwandavek/talktocode" target="_blank"> + <i class="github icon"></i> + nuwandavek/talktocode + </a> + </p> + </div> + </div> + <script> + res = {{payload|tojson}}; + + console.log(res); + text = "" + if (res['loctype'] == "folder"){ + text+="<div class='code'>" + res['text'].forEach((a)=>{ + text += "<div><a href='/?path="+a[0]+"'>"+a[0]+"</a><div>" + }) + text+="<div>" + + } + else if(res['loctype'] == "file"){ + leftClass = "language-go" + res['text'].forEach((a, i)=>{ + text += '<div class="col-xs-5 code" id="code-'+i+'"><pre><code class="language-go">'+a[0]+'</code></pre></div>' + text += '<div class="col-xs-5 summary" id="summary-"'+i+'><p>'+a[1]+'</p></div>' + }) + } + else{ + text = ""; + } + $("#main").html(text); + $("#main-title").html(res['parents'] + "/" + res['current']); + hljs.highlightAll(); + + $("#talk-button").click(()=>{ + query = $("#talk-text").val() + console.log(query); + $("#spinny").show(); + + fetch('/answer?q='+query, {method: "GET"}) + .then((response) => response.json()) + .then((data) => { + console.log(data); + $("#spinny").hide(); + text = "" + data.forEach((a, i)=>{ + text += '<div class="col-xs-5 code" id="code-'+i+'"><pre><code class="language-go">'+a['blob']+'</code></pre></div>' + text += '<div class="col-xs-5 summary" id="summary-"'+i+'><p>'+a['summary']+'</p></div>' + }) + $("#main").html(text); + $("#main-title").html(""); + hljs.highlightAll(); + + }); + }) + + $("#talk-button-2").click(()=>{ + query = $("#talk-text").val() + console.log(query); + $("#spinny").show(); + + fetch('/explain?q='+query, {method: "GET"}) + .then((response) => response.json()) + .then((data) => { + console.log(data); + $("#spinny").hide(); + $("#main").html('<div class="col-xs-5 code"><pre><code class="language-plaintext">'+data+'</code></pre></div>'); + $("#main-title").html(""); + hljs.highlightAll(); + + }); + }) + + </script> + <script src="./jsmain.js"></script> + </body> +</html> diff --git a/frontend/jsmain.js b/frontend/jsmain.js new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/frontend/jsmain.js diff --git a/frontend/style.css b/frontend/style.css new file mode 100644 index 0000000..8417106 --- /dev/null +++ b/frontend/style.css @@ -0,0 +1,138 @@ +html { + font-size: 16px; +} + +#main-content { + text-align: center; + min-height: 100vh; +} + + +#jumbo-title { + font-weight: 900; + font-size: 10rem; + font-family: 'Inter' !important; + color: #2d3436; +} + +#top-bar { + padding: 1rem 2rem 1rem 2rem; + border-bottom: #eee 1px solid; + margin-bottom: 2rem; +} + +.top-xs { + align-content: start !important; +} + + +.normal-font { + font-size: 1rem !important; + color: #fff !important; + font-family: 'Inter' !important; +} + +.normal-font-light { + font-size: 1rem !important; + color: #2d3436 !important; + font-family: 'Inter' !important; +} + +.fat-font { + font-weight: 900; +} + +code { + background-color: #2a3b4d; + border-radius: 2px; + padding: 1px; +} + +.ui.button { + /* padding: 0.5rem !important; */ + font-size: 1rem !important; + margin-left: 0.5rem !important; +} + +.footie{ + border-radius: 5px; + background: #2d3436; + padding: 2rem; +} + +#transcription-result{ + border-radius: 5px; + border: 1px solid #ddd; + min-height: 10rem; + margin: 1rem 0.5rem 1rem 0.5rem; + padding: 1rem; + text-align: left; +} + +#spinny { + position: absolute; + z-index: 10; + width: 100%; + height: 100%; + display: none; +} + +#transcription-title { + text-align: center; + text-transform: uppercase; + letter-spacing: 1rem; + font-weight: 900; +} + +.divider{ + color: #fff !important; +} + +#all-inputs{ + padding: 1rem; + border: 1px solid #2d3436;; + border-radius: 5px; + background: #2d3436;; +} + +audio{ + border: 1px solid #424e51; + border-radius: 5px; +} + +#blinker { + color: #db2828; + margin: 1rem; + display: none; +} + +.blink { + animation: blinker 1s infinite alternate; +} + +.code, .summary{ + text-align: left; + min-height: 500px; + width: 100%; + display: inline-block; + background: #282c34; + padding: 20px; + color: #fff; + margin: 5px; + border-radius: 5px; + font-size: 16px;; +} + +#main-title{ + background-color: #eee; + color: red; + font-size: 25px !important; + padding: 10px; + margin: 10px; + border-radius: 5px;; +} + +@keyframes blinker { +from { opacity: 1; } +to { opacity: 0; } +}
\ No newline at end of file diff --git a/server.py b/server.py new file mode 100644 index 0000000..05e726f --- /dev/null +++ b/server.py @@ -0,0 +1,135 @@ +from flask import Flask, request, Response, jsonify, render_template +import pandas as pd +from collections import defaultdict +import os +import openai +from openai.embeddings_utils import get_embedding, cosine_similarity +openai.api_key = os.getenv('OPENAI_KEY') +import numpy as np + +app = Flask(__name__, template_folder="./frontend", static_folder="./frontend", static_url_path="") + + + +def search_code(df, query, n=4): + query_embedding = get_embedding( + query, + engine="text-embedding-ada-002" + ) + #df["similarity"] = df.summary_embeddings.apply(lambda x: cosine_similarity(x, query_embedding)) + df["similarity"] = df.embedding_summary.apply(lambda x: cosine_similarity(x, query_embedding)) + # df["similarity"] = df.embeddings.apply(lambda x: cosine_similarity(x, query_embedding)) + results = ( + df.sort_values("similarity", ascending=False) + ) + return results.head(n) + + +def generate_answer(question): + results = search_code(df, question, n=4) + prompt = '' + for i in range(3): + prompt += results.iloc[i]["summary"] + "\n" + results.iloc[i]["blob"] + "\n" + prompt += "\n" + "Answer the following question using the code context given above, and show an example with 'Example'\nQ: " + question + "\nA: " + response = openai.Completion.create( + model="text-davinci-003", + # model="code-davinci-002", + prompt=prompt, + temperature=0.7, + max_tokens=1000, + top_p=1.0, + frequency_penalty=0.0, + presence_penalty=0.0, + stop=["\"\"\""] + ) + return response["choices"][0]["text"] + +# The above two functions should already work with the Go version. + +def get_code_structure(df): + kids_structure = defaultdict(list) + parents_structure = {} + for path in list(df['file_path'].unique()): + t = path.split("/") + for e in range(len(t)): + # if we know it's a dir name, record the next path component as a + # child of the current dir. + if e < len(t) - 1: + kids_structure[t[e]].append(t[e+1]) + else: + kids_structure[t[e]] = ["file"] + if e == 0: + parents_structure[t[e]] = "./" + else: + parents_structure[t[e]] = "/".join(t[:e]) + + for k, v in kids_structure.items(): + kids_structure[k] = list(set(v)) + return dict(kids_structure), parents_structure + + +# Nate: these are from the original project. My own csv is below +#df = pd.read_csv("./frontend/data/embedded_summarized.csv") +#df = pd.read_csv("./frontend/data/withsummary2.csv") + +# My line +df=pd.read_csv("./frontend/data/test_with_summary_and_embeddings.csv", converters={'embedding_summary': pd.eval}) + +# need to do funny stuff to read in the data frame correctly from csv. that's +# why the eval() is below. and pd.eval is above. + +#df['summary_embeddings'] = df['summary_embeddings'].apply(lambda x: eval(x)) +#df['embeddings'] = df['embeddings'].apply(lambda x: eval(x)) + +filetypes = ['go'] + + +# messed this area up for debugging +@app.route('/') +def home(): + stub = request.args.get('path', 'dirserver').strip() + kids_structure, parents_structure = get_code_structure(df) + print('kids_structure', kids_structure) + print('parents_structure', parents_structure) + print('stub', stub) + if stub not in kids_structure: + loctype = "nan" + text = [["Path not available!"], [""]] + elif any([stub.endswith(x) for x in filetypes]): + loctype = "file" + fullpath = f"{parents_structure[stub]}/{stub}" + print(fullpath) + text = [[x, y] for x, y in zip( + list(df[df['file_path'] == fullpath]['source']), + list(df[df['file_path'] == fullpath]['summary']) + )] + else: + loctype = "folder" + text = [[x, ""] for x in kids_structure[stub]] + res = { + 'parents': parents_structure[stub], + 'loctype': loctype, + 'text': text, + 'current': stub + } + return render_template('index.html', payload=res) + + +@app.route('/answer') +def answer(): + q = request.args.get('q', '').strip() + a = search_code(df, q) + res = [{'blob': x['blob'], 'summary': x['summary']} for x in a.to_dict('records')] + + return jsonify(res) + +@app.route('/explain') +def explain(): + q = request.args.get('q', '').strip() + a = generate_answer(q) + return jsonify(a) + + +if __name__ == '__main__': + app.run(port=5001, debug=True) + #app.run(host="0.0.0.0", port=5001, debug=True) |