Skip to content
This repository was archived by the owner on Nov 11, 2023. It is now read-only.

Commit 3b6092e

Browse files
committed
Actually send the puppet reads
Deploy to hugging face
1 parent dc7f995 commit 3b6092e

File tree

15 files changed

+385
-147
lines changed

15 files changed

+385
-147
lines changed

.github/workflows/cd.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Sync to Hugging Face hub
2+
on:
3+
push:
4+
branches: [main]
5+
6+
# to run this workflow manually from the Actions tab
7+
workflow_dispatch:
8+
9+
jobs:
10+
sync-to-hub:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v3
14+
with:
15+
fetch-depth: 0
16+
lfs: true
17+
- name: Push to hub
18+
env:
19+
HF_TOKEN: ${{ secrets.HF_TOKEN }}
20+
run:
21+
git push https://posix4e:[email protected]/spaces/ttt246/brain main

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
**/*.swp
2+
.vscode

README.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,23 @@
1-
# puppet
1+
---
2+
title: puppet
3+
colorTo: indigo
4+
app_file: backend/backend.py
5+
sdk: gradio
6+
sdk_version: 2.9.1
7+
python_version: 3.11.2
8+
pinned: false
9+
license: mit
10+
---
11+
12+
Fun!
13+
14+
## MVP
15+
16+
- [ ] Run commands on android
17+
- [ ] Fix assist on android
18+
- [ ] Testing
19+
- [ ] Docs
20+
21+
## Todo Soon
22+
23+
- [ ] Other clients (browser extension/watch)

backend/backend.py

Lines changed: 130 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,180 @@
1+
from sqlalchemy import Column, Integer, String, DateTime, create_engine, Table, MetaData
2+
from sqlalchemy.sql import text, select, insert
3+
from sqlalchemy.orm import sessionmaker, Session
4+
from sqlalchemy.ext.declarative import declarative_base
5+
from datetime import datetime
6+
import uuid
17
from fastapi import FastAPI, HTTPException
28
from pydantic import BaseModel
3-
from firebase_admin import credentials, messaging, initialize_app, auth
49
import openai
5-
import asyncio
6-
import gradio as gr
710
from fastapi.middleware.wsgi import WSGIMiddleware
811
from fastapi.staticfiles import StaticFiles
912
import uvicorn
1013
from dotenv import load_dotenv
14+
import requests
15+
from uvicorn import Config, Server
16+
import os
17+
from typing import Optional
18+
import gradio as gr
19+
from enum import Enum
20+
21+
Base = declarative_base()
22+
23+
24+
class User(Base):
25+
__tablename__ = "user_data"
26+
27+
id = Column(Integer, primary_key=True, autoincrement=True)
28+
uuid = Column(String, nullable=False)
29+
openai_key = Column(String)
30+
last_assist = Column(DateTime)
31+
32+
33+
engine = create_engine("sqlite:///users.db")
34+
Base.metadata.create_all(bind=engine)
35+
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
1136

1237
load_dotenv()
38+
app = FastAPI(debug=True)
39+
40+
41+
class EventItem(BaseModel):
42+
uid: str
43+
event: str
44+
1345

46+
@app.post("/send_event")
47+
async def send_event(item: EventItem):
48+
print(f"Received event from {item.uid}:\n{item.event}")
1449

15-
app = FastAPI()
50+
with open(f"{item.uid}_events.txt", "a") as f:
51+
f.write(f"{datetime.now()} - {item.event}\n")
1652

17-
# User credentials will be stored in this dictionary
18-
user_data = {}
53+
return {"message": "Event received"}
1954

2055

2156
class RegisterItem(BaseModel):
22-
apiKey: str
23-
authDomain: str
24-
databaseURL: str
25-
storageBucket: str
57+
openai_key: str
2658

2759

2860
@app.post("/register")
2961
async def register(item: RegisterItem):
30-
# Firebase initialization with user-specific credentials
31-
cred = credentials.Certificate(
32-
{
33-
"apiKey": item.apiKey,
34-
"authDomain": item.authDomain,
35-
"databaseURL": item.databaseURL,
36-
"storageBucket": item.storageBucket,
37-
}
38-
)
39-
firebase_app = initialize_app(cred, name=str(len(user_data)))
40-
# Add the Firebase app and auth details to the user_data dictionary
41-
user_data[str(len(user_data))] = {
42-
"firebase_app": firebase_app,
43-
"authDomain": item.authDomain,
44-
}
45-
return {"uid": str(len(user_data) - 1)} # Return the user ID
62+
db: Session = SessionLocal()
63+
new_user = User(uuid=str(uuid.uuid4()), openai_key=item.openai_key)
64+
db.add(new_user)
65+
db.commit()
66+
db.refresh(new_user)
67+
return {"uid": new_user.uuid}
4668

4769

48-
class ProcessItem(BaseModel):
70+
class AssistItem(BaseModel):
4971
uid: str
5072
prompt: str
73+
version: str
5174

5275

53-
@app.post("/process_request")
54-
async def process_request(item: ProcessItem):
55-
# Get the user's Firebase app from the user_data dictionary
56-
firebase_app = user_data.get(item.uid, {}).get("firebase_app", None)
57-
authDomain = user_data.get(item.uid, {}).get("authDomain", None)
76+
def generate_quick_completion(prompt, gpt_version):
77+
response = openai.Completion.create(
78+
engine=gpt_version, prompt=prompt, max_tokens=1500
79+
)
80+
return response
81+
5882

59-
if not firebase_app or not authDomain:
83+
@app.post("/assist")
84+
async def assist(item: AssistItem):
85+
db: Session = SessionLocal()
86+
user = db.query(User).filter(User.uuid == item.uid).first()
87+
if not user:
6088
raise HTTPException(status_code=400, detail="Invalid uid")
6189

6290
# Call OpenAI
63-
response = openai.Completion.create(
64-
engine="text-davinci-002", prompt=item.prompt, max_tokens=150
65-
)
91+
openai.api_key = user.openai_key
92+
response = generate_quick_completion(item.prompt, item.version)
6693

67-
# The message data that will be sent to the client
68-
message = messaging.Message(
69-
data={
70-
"message": response.choices[0].text.strip(),
71-
},
72-
topic="updates",
73-
app=firebase_app, # Use the user-specific Firebase app
74-
)
94+
# Update the last time assist was called
95+
user.last_assist = datetime.now()
96+
db.commit()
7597

76-
# Send the message asynchronously
77-
asyncio.run(send_notification(message))
98+
return response
7899

79-
return {"message": "Notification sent"}
80100

101+
def assist_interface(uid, prompt, gpt_version):
102+
response = requests.post(
103+
"http://localhost:8000/assist",
104+
json={"uid": uid, "prompt": prompt, "version": gpt_version},
105+
)
106+
return response.text
81107

82-
def send_notification(message):
83-
# Send a message to the devices subscribed to the provided topic.
84-
response = messaging.send(message)
85-
print("Successfully sent message:", response)
86108

109+
def get_user_interface(uid):
110+
db: Session = SessionLocal()
111+
user = db.query(User).filter(User.uuid == uid).first()
112+
if not user:
113+
return {"message": "No user with this uid found"}
114+
return str(user)
87115

88-
def gradio_interface():
89-
def register(apiKey, authDomain, databaseURL, storageBucket):
90-
response = requests.post(
91-
"http://localhost:8000/register",
92-
json={
93-
"apiKey": apiKey,
94-
"authDomain": authDomain,
95-
"databaseURL": databaseURL,
96-
"storageBucket": storageBucket,
97-
},
98-
)
99-
return response.json()
100116

101-
def process_request(uid, prompt):
102-
response = requests.post(
103-
"http://localhost:8000/process_request", json={"uid": uid, "prompt": prompt}
104-
)
105-
return response.json()
117+
def get_assist_interface():
118+
gpt_version_dropdown = gr.inputs.Dropdown(
119+
label="GPT Version",
120+
choices=["text-davinci-002", "text-davinci-003", "text-davinci-004"],
121+
default="text-davinci-002",
122+
)
106123

107-
demo = gr.Interface(
108-
fn=[register, process_request],
124+
return gr.Interface(
125+
fn=assist_interface,
109126
inputs=[
110-
[
111-
gr.inputs.Textbox(label="apiKey"),
112-
gr.inputs.Textbox(label="authDomain"),
113-
gr.inputs.Textbox(label="databaseURL"),
114-
gr.inputs.Textbox(label="storageBucket"),
115-
],
116-
[gr.inputs.Textbox(label="uid"), gr.inputs.Textbox(label="prompt")],
127+
gr.inputs.Textbox(label="UID", type="text"),
128+
gr.inputs.Textbox(label="Prompt", type="text"),
129+
gpt_version_dropdown,
117130
],
118-
outputs="json",
119-
title="API Explorer",
120-
description="Use this tool to make requests to the Register and Process Request APIs",
131+
outputs="text",
132+
title="OpenAI Text Generation",
133+
description="Generate text using OpenAI's GPT-4 model.",
121134
)
122-
return demo
123135

124136

125-
def process_request_interface(uid, prompt):
126-
item = ProcessItem(uid=uid, prompt=prompt)
127-
response = process_request(item)
128-
return response
137+
def get_db_interface():
138+
return gr.Interface(
139+
fn=get_user_interface,
140+
inputs="text",
141+
outputs="text",
142+
title="Get User Details",
143+
description="Get user details from the database",
144+
)
145+
146+
147+
def register_interface(openai_key):
148+
response = requests.post(
149+
"http://localhost:8000/register",
150+
json={"openai_key": openai_key},
151+
)
152+
return response.json()
129153

130154

131-
def get_gradle_interface():
155+
def get_register_interface():
132156
return gr.Interface(
133-
fn=process_request_interface,
134-
inputs=[
135-
gr.inputs.Textbox(label="UID", type="text"),
136-
gr.inputs.Textbox(label="Prompt", type="text"),
137-
],
157+
fn=register_interface,
158+
inputs=[gr.inputs.Textbox(label="OpenAI Key", type="text")],
138159
outputs="text",
139-
title="OpenAI Text Generation",
140-
description="Generate text using OpenAI's GPT-3 model.",
160+
title="Register New User",
161+
description="Register a new user by entering an OpenAI key.",
141162
)
142163

143164

144-
app = gr.mount_gradio_app(app, get_gradle_interface(), path="/")
165+
app = gr.mount_gradio_app(
166+
app,
167+
gr.TabbedInterface(
168+
[
169+
get_assist_interface(),
170+
get_db_interface(),
171+
get_register_interface(),
172+
]
173+
),
174+
path="/",
175+
)
176+
177+
if __name__ == "__main__":
178+
config = Config("backend:app", host="127.0.0.1", port=8000, reload=True)
179+
server = Server(config)
180+
server.run()

backend/crappy_test.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
import uuid
23
from fastapi.testclient import TestClient
34
import pytest
45
import json
@@ -11,11 +12,29 @@ async def test_register():
1112
client = TestClient(backend.app)
1213

1314
data = {
14-
"apiKey": "test-api-key",
15-
"authDomain": "test-auth-domain",
16-
"databaseURL": "test-database-url",
17-
"storageBucket": "test-storage-bucket",
18-
"openai_key": "test-openai-key",
15+
"openai_key": "garbage",
1916
}
20-
with pytest.raises(ValueError):
21-
client.post("/register", json=data)
17+
client.post("/register", json=data)
18+
19+
20+
@pytest.mark.asyncio
21+
async def test_send_event():
22+
client = TestClient(backend.app)
23+
24+
data = {
25+
"uid": str(uuid.uuid4()),
26+
"event": "test event",
27+
}
28+
client.post("/register", json=data)
29+
30+
31+
@pytest.mark.asyncio
32+
async def test_assist():
33+
client = TestClient(backend.app)
34+
35+
data = {
36+
"uid": str(uuid.uuid4()),
37+
"prompt": "test prompt",
38+
"version": "davinci-fake",
39+
}
40+
client.post("/assist", json=data)

backend/requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ pinecone-io
88
pydantic
99
python-dotenv
1010
swagger-ui-bundle
11-
11+
sqlalchemy
1212
pytest-asyncio
1313
pytest
1414
requests

puppet/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,3 @@ local.properties
1111
.idea/assetWizardSettings.xml
1212
.DS_Store
1313
build
14-
local.properties

puppet/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
android:dataExtractionRules="@xml/data_extraction_rules"
1010
android:fullBackupContent="@xml/backup_rules"
1111
android:icon="@mipmap/ic_launcher"
12+
android:networkSecurityConfig="@xml/network_security_config"
1213
android:label="@string/app_name"
1314
android:roundIcon="@mipmap/ic_launcher_round"
1415
android:supportsRtl="true"
@@ -22,6 +23,7 @@
2223
<category android:name="android.intent.category.LAUNCHER" />
2324
</intent-filter>
2425
</activity>
26+
<activity android:name=".SettingsActivity" android:exported="false"/>
2527

2628
<service
2729
android:name=".PuppetAS"

0 commit comments

Comments
 (0)