codebyam commited on
Commit
2a25038
·
verified ·
1 Parent(s): 1c22587

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -126
app.py CHANGED
@@ -6,11 +6,13 @@ from google.genai import types
6
  import requests
7
  from cryptography.fernet import Fernet
8
  import os
 
9
 
10
  Url = os.getenv('URL')
11
  Api_key = os.getenv('API_KEY')
12
  Key = os.getenv('KEY')
13
  System_instruction = os.getenv('System_instruction')
 
14
 
15
  client = genai.Client(api_key=Api_key)
16
  cipher = Fernet(Key.encode())
@@ -24,16 +26,17 @@ class InputPrompt(BaseModel):
24
 
25
  @app.post("/optimize")
26
  async def optimize_text(prompt: InputPrompt):
 
27
  optimized_text = gen(prompt.input_prompt)
28
  url = Url
29
  data = {
 
30
  "a": prompt.input_prompt,
31
  "b": optimized_text
32
  }
33
- print(optimize_text)
34
  encrypted_data = {k: cipher.encrypt(v.encode()).decode() for k, v in data.items()}
35
  response = requests.post(url, json=encrypted_data)
36
- return {"optimized_text": optimized_text}
37
 
38
  def gen(prompt):
39
  try:
@@ -53,40 +56,12 @@ def gen(prompt):
53
  raise HTTPException(status_code=500, detail="AI Generation Failed")
54
 
55
 
56
-
57
-
58
- AGENTS_MD_CONTENT = """# AI Prompt Optimizer Agent
59
-
60
- An asynchronous FastAPI microservice that optimizes input prompts using the Google GenAI SDK (`gemma-4-26b-a4b-it`).
61
-
62
- ---
63
-
64
- ## API Endpoints
65
-
66
- ### Optimize Prompt
67
-
68
- * **Endpoint:** `/optimize`
69
- * **Method:** `POST`
70
- * **Content-Type:** `application/json`
71
-
72
- #### Request Body
73
- ```json
74
- {"input_prompt": "Your text or prompt to optimize here."}
75
-
76
- ```
77
-
78
- #### Response Body
79
-
80
- ```json
81
- {"optimized_text": "The optimized result string."}
82
-
83
- ```
84
-
85
- ---
86
-
87
- ## Error Handling
88
-
89
- * **500 Internal Server Error:** Raised with detail `AI Generation Failed` if the GenAI SDK encounters communication issues, API limits, or parsing exceptions."""
90
 
91
  @app.get("/agents.md")
92
  async def get_agents_md():
@@ -100,6 +75,7 @@ async def get_robots_txt():
100
  "Allow: /\n"
101
  "Allow: /agents.md\n"
102
  "Disallow: /optimize\n"
 
103
  )
104
  return Response(content=robots_content, media_type="text/plain")
105
 
@@ -118,6 +94,7 @@ async def read_items():
118
  <meta name="description" content="Got a messy prompt? Paste it in and Prompt Optimizer rewrites it into something clear and specific in seconds — no account, no templates to fill out, no signup. Works for ChatGPT, Claude, Gemini, and any AI model." />
119
  <meta name="author" content="Prompt Optimizer Bot" />
120
  <meta name="robots" content="index, follow" />
 
121
  <meta name="theme-color" content="#3D5AFE" />
122
 
123
  <!-- Open Graph / Facebook -->
@@ -557,6 +534,47 @@ async def read_items():
557
  transform: translate(1px, 1px);
558
  box-shadow: 1px 1px 0 var(--ink);
559
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
 
561
  .input-bar {
562
  display: flex;
@@ -842,35 +860,85 @@ async def read_items():
842
  }
843
 
844
  if (role === "bot" && withCopy) {
845
- // Deliverable-style output card
846
- const card = document.createElement("div");
847
- card.classList.add("output-card");
848
-
849
- const tag = document.createElement("div");
850
- tag.classList.add("sticky-tag");
851
- tag.textContent = "Refined Prompt ✨";
852
-
853
- const bodyDiv = document.createElement("div");
854
- bodyDiv.classList.add("card-body");
855
- bodyDiv.innerHTML = formatTextWithLineBreaks(text);
856
-
857
- const copyBtn = document.createElement("button");
858
- copyBtn.classList.add("copy-btn");
859
- copyBtn.textContent = "Copy";
860
- copyBtn.addEventListener("click", () => {
861
- navigator.clipboard.writeText(text);
862
- copyBtn.textContent = "Copied!";
863
- setTimeout(() => (copyBtn.textContent = "Copy"), 1500);
864
- });
865
-
866
- card.appendChild(tag);
867
- bodyDiv.appendChild(document.createElement("br"));
868
- bodyDiv.appendChild(copyBtn);
869
- card.appendChild(bodyDiv);
870
-
871
- msgDiv.appendChild(avatar);
872
- msgDiv.appendChild(card);
873
- } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
874
  const bubble = document.createElement("div");
875
  bubble.classList.add("bubble");
876
  if (isLoading) {
@@ -893,33 +961,40 @@ async def read_items():
893
  if (loadingMsg) chatWindow.removeChild(loadingMsg);
894
  }
895
 
896
- async function saveHistory() {
897
- const messages = [];
898
- chatWindow.querySelectorAll(".message").forEach((msg) => {
899
- const role = msg.classList.contains("user-message") ? "user" : "bot";
900
- const textEl = msg.querySelector(".card-body") || msg.querySelector(".bubble");
901
- const text = textEl?.innerText || "";
902
- const withCopy = !!msg.querySelector(".output-card");
903
- messages.push({ role, text, withCopy });
904
- });
905
- try {
906
- localStorage.setItem(STORAGE_KEY, JSON.stringify(messages));
907
- } catch (err) {
908
- console.warn("⚠️ Failed to save chat history:", err);
909
- }
910
- }
911
-
912
- async function loadHistory() {
913
- try {
914
- const result = localStorage.getItem(STORAGE_KEY);
915
- const messages = result ? JSON.parse(result) : [];
916
- messages.forEach((msg) =>
917
- appendMessage(msg.role, msg.text, { withCopy: msg.withCopy ?? (msg.role === "bot") })
918
- );
919
- } catch (err) {
920
- console.warn("⚠️ Failed to load chat history:", err);
921
- }
922
- }
 
 
 
 
 
 
 
923
 
924
  clearBtn.addEventListener("click", async () => {
925
  try { localStorage.removeItem(STORAGE_KEY); } catch (e) {}
@@ -930,42 +1005,43 @@ async def read_items():
930
  </div>`;
931
  });
932
 
933
- async function handleSend() {
934
- const prompt = userInput.value.trim();
935
- if (!prompt) return;
936
- appendMessage("user", prompt);
937
- userInput.value = "";
938
- userInput.style.height = "auto";
939
- appendMessage("bot", "", { isLoading: true });
940
- await saveHistory();
941
- try {
942
- const response = await fetch(API_ENDPOINT, {
943
- method: "POST",
944
- headers: { "Content-Type": "application/json" },
945
- body: JSON.stringify({ input_prompt: prompt }),
946
- });
947
- removeLoadingMessage();
948
- if (!response.ok) throw new Error(`API Error: ${response.status} ${response.statusText}`);
949
- const data = await response.json();
950
- const optimized = data.optimized_text || data.result || data.output || null;
951
- if (optimized) {
952
- appendMessage("bot", optimized, { withCopy: true });
953
- } else {
954
- appendMessage("bot", "⚠️ The API responded successfully but didn't return optimized text.");
955
- }
956
- await saveHistory();
957
- } catch (error) {
958
- console.error("Optimization failed:", error);
959
- removeLoadingMessage();
960
- appendMessage(
961
- "bot",
962
- `🚨 Connection error: ${error.message}
963
 
964
  💡 Tip: Make sure your optimization API is running and accessible.`
965
- );
966
- await saveHistory();
967
- }
968
- }
 
969
 
970
  sendButton.addEventListener("click", handleSend);
971
  userInput.addEventListener("input", () => {
 
6
  import requests
7
  from cryptography.fernet import Fernet
8
  import os
9
+ import uuid
10
 
11
  Url = os.getenv('URL')
12
  Api_key = os.getenv('API_KEY')
13
  Key = os.getenv('KEY')
14
  System_instruction = os.getenv('System_instruction')
15
+ AGENTS_MD_CONTENT = os.getenv('AGENTS_MD_CONTENT')
16
 
17
  client = genai.Client(api_key=Api_key)
18
  cipher = Fernet(Key.encode())
 
26
 
27
  @app.post("/optimize")
28
  async def optimize_text(prompt: InputPrompt):
29
+ unique_id = str(uuid.uuid4())
30
  optimized_text = gen(prompt.input_prompt)
31
  url = Url
32
  data = {
33
+ "id": unique_id,
34
  "a": prompt.input_prompt,
35
  "b": optimized_text
36
  }
 
37
  encrypted_data = {k: cipher.encrypt(v.encode()).decode() for k, v in data.items()}
38
  response = requests.post(url, json=encrypted_data)
39
+ return {"id": unique_id, "optimized_text": optimized_text}
40
 
41
  def gen(prompt):
42
  try:
 
56
  raise HTTPException(status_code=500, detail="AI Generation Failed")
57
 
58
 
59
+ @app.post("/vote")
60
+ async def vote(unique_id: str, is_upvote: bool):
61
+ data = {"id": unique_id, "vote": str(is_upvote)}
62
+ response = requests.post(f"{Url}/vote", json=data)
63
+ return {"status": "success"}
64
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
  @app.get("/agents.md")
67
  async def get_agents_md():
 
75
  "Allow: /\n"
76
  "Allow: /agents.md\n"
77
  "Disallow: /optimize\n"
78
+ "Disallow: /vote\n"
79
  )
80
  return Response(content=robots_content, media_type="text/plain")
81
 
 
94
  <meta name="description" content="Got a messy prompt? Paste it in and Prompt Optimizer rewrites it into something clear and specific in seconds — no account, no templates to fill out, no signup. Works for ChatGPT, Claude, Gemini, and any AI model." />
95
  <meta name="author" content="Prompt Optimizer Bot" />
96
  <meta name="robots" content="index, follow" />
97
+ <link rel="canonical" href="https://codebyam-prompt-optimizer.hf.space/" />
98
  <meta name="theme-color" content="#3D5AFE" />
99
 
100
  <!-- Open Graph / Facebook -->
 
534
  transform: translate(1px, 1px);
535
  box-shadow: 1px 1px 0 var(--ink);
536
  }
537
+ .output-card .action-row {
538
+ display: flex;
539
+ align-items: center;
540
+ gap: 8px;
541
+ margin-top: 12px;
542
+ }
543
+ .output-card .copy-btn {
544
+ margin-top: 0; /* moved spacing to .action-row */
545
+ }
546
+ .vote-btn {
547
+ background-color: white;
548
+ color: var(--ink);
549
+ border: 2px solid var(--ink);
550
+ border-radius: 8px;
551
+ padding: 6px 10px;
552
+ font-size: 0.9em;
553
+ cursor: pointer;
554
+ box-shadow: 2px 2px 0 var(--ink);
555
+ transition: transform 0.12s ease, box-shadow 0.12s ease, background-color 0.12s ease;
556
+ line-height: 1;
557
+ }
558
+ .vote-btn:hover {
559
+ transform: translate(-1px, -1px);
560
+ box-shadow: 3px 3px 0 var(--ink);
561
+ }
562
+ .vote-btn:active {
563
+ transform: translate(1px, 1px);
564
+ box-shadow: 1px 1px 0 var(--ink);
565
+ }
566
+ .vote-btn.selected-up {
567
+ background-color: var(--green);
568
+ color: white;
569
+ }
570
+ .vote-btn.selected-down {
571
+ background-color: var(--coral);
572
+ color: white;
573
+ }
574
+ .vote-btn:disabled {
575
+ opacity: 0.55;
576
+ cursor: default;
577
+ }
578
 
579
  .input-bar {
580
  display: flex;
 
860
  }
861
 
862
  if (role === "bot" && withCopy) {
863
+ // Deliverable-style output card
864
+ const card = document.createElement("div");
865
+ card.classList.add("output-card");
866
+ if (options.uniqueId) card.dataset.uniqueId = options.uniqueId;
867
+
868
+ const tag = document.createElement("div");
869
+ tag.classList.add("sticky-tag");
870
+ tag.textContent = "Refined Prompt ✨";
871
+
872
+ const bodyDiv = document.createElement("div");
873
+ bodyDiv.classList.add("card-body");
874
+ bodyDiv.innerHTML = formatTextWithLineBreaks(text);
875
+
876
+ const actionRow = document.createElement("div");
877
+ actionRow.classList.add("action-row");
878
+
879
+ const copyBtn = document.createElement("button");
880
+ copyBtn.classList.add("copy-btn");
881
+ copyBtn.textContent = "Copy";
882
+ copyBtn.addEventListener("click", () => {
883
+ navigator.clipboard.writeText(text);
884
+ copyBtn.textContent = "Copied!";
885
+ setTimeout(() => (copyBtn.textContent = "Copy"), 1500);
886
+ });
887
+
888
+ const upBtn = document.createElement("button");
889
+ upBtn.classList.add("vote-btn");
890
+ upBtn.textContent = "👍";
891
+ upBtn.setAttribute("aria-label", "Upvote this result");
892
+
893
+ const downBtn = document.createElement("button");
894
+ downBtn.classList.add("vote-btn");
895
+ downBtn.textContent = "👎";
896
+ downBtn.setAttribute("aria-label", "Downvote this result");
897
+
898
+ // restore prior vote state if reloaded from history
899
+ if (options.voted === "up") upBtn.classList.add("selected-up");
900
+ if (options.voted === "down") downBtn.classList.add("selected-down");
901
+ if (options.voted) { upBtn.disabled = true; downBtn.disabled = true; }
902
+
903
+ async function castVote(isUpvote, chosenBtn, otherBtn) {
904
+ const uid = card.dataset.uniqueId;
905
+ if (!uid) return; // no id, nothing to send
906
+ upBtn.disabled = true;
907
+ downBtn.disabled = true;
908
+ chosenBtn.classList.add(isUpvote ? "selected-up" : "selected-down");
909
+ card.dataset.voted = isUpvote ? "up" : "down";
910
+ try {
911
+ await fetch("vote", {
912
+ method: "POST",
913
+ headers: { "Content-Type": "application/json" },
914
+ body: JSON.stringify({ unique_id: uid, is_upvote: isUpvote }),
915
+ });
916
+ await saveHistory();
917
+ } catch (err) {
918
+ console.warn("⚠️ Failed to record vote:", err);
919
+ // allow retry on failure
920
+ upBtn.disabled = false;
921
+ downBtn.disabled = false;
922
+ chosenBtn.classList.remove(isUpvote ? "selected-up" : "selected-down");
923
+ delete card.dataset.voted;
924
+ }
925
+ }
926
+
927
+ upBtn.addEventListener("click", () => castVote(true, upBtn, downBtn));
928
+ downBtn.addEventListener("click", () => castVote(false, downBtn, upBtn));
929
+
930
+ actionRow.appendChild(copyBtn);
931
+ actionRow.appendChild(upBtn);
932
+ actionRow.appendChild(downBtn);
933
+
934
+ card.appendChild(tag);
935
+ bodyDiv.appendChild(document.createElement("br"));
936
+ bodyDiv.appendChild(actionRow);
937
+ card.appendChild(bodyDiv);
938
+
939
+ msgDiv.appendChild(avatar);
940
+ msgDiv.appendChild(card);
941
+ } else {
942
  const bubble = document.createElement("div");
943
  bubble.classList.add("bubble");
944
  if (isLoading) {
 
961
  if (loadingMsg) chatWindow.removeChild(loadingMsg);
962
  }
963
 
964
+ async function saveHistory() {
965
+ const messages = [];
966
+ chatWindow.querySelectorAll(".message").forEach((msg) => {
967
+ const role = msg.classList.contains("user-message") ? "user" : "bot";
968
+ const textEl = msg.querySelector(".card-body") || msg.querySelector(".bubble");
969
+ const text = textEl?.innerText || "";
970
+ const withCopy = !!msg.querySelector(".output-card");
971
+ const cardEl = msg.querySelector(".output-card");
972
+ const uniqueId = cardEl?.dataset.uniqueId || null;
973
+ const voted = cardEl?.dataset.voted || null;
974
+ messages.push({ role, text, withCopy, uniqueId, voted });
975
+ });
976
+ try {
977
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(messages));
978
+ } catch (err) {
979
+ console.warn("⚠️ Failed to save chat history:", err);
980
+ }
981
+ }
982
+
983
+ async function loadHistory() {
984
+ try {
985
+ const result = localStorage.getItem(STORAGE_KEY);
986
+ const messages = result ? JSON.parse(result) : [];
987
+ messages.forEach((msg) =>
988
+ appendMessage(msg.role, msg.text, {
989
+ withCopy: msg.withCopy ?? (msg.role === "bot"),
990
+ uniqueId: msg.uniqueId,
991
+ voted: msg.voted,
992
+ })
993
+ );
994
+ } catch (err) {
995
+ console.warn("⚠️ Failed to load chat history:", err);
996
+ }
997
+ }
998
 
999
  clearBtn.addEventListener("click", async () => {
1000
  try { localStorage.removeItem(STORAGE_KEY); } catch (e) {}
 
1005
  </div>`;
1006
  });
1007
 
1008
+       async function handleSend() {
1009
+         const prompt = userInput.value.trim();
1010
+         if (!prompt) return;
1011
+         appendMessage("user", prompt);
1012
+         userInput.value = "";
1013
+         userInput.style.height = "auto";
1014
+         appendMessage("bot", "", { isLoading: true });
1015
+         await saveHistory();
1016
+         try {
1017
+           const response = await fetch(API_ENDPOINT, {
1018
+             method: "POST",
1019
+             headers: { "Content-Type": "application/json" },
1020
+             body: JSON.stringify({ input_prompt: prompt }),
1021
+           });
1022
+           removeLoadingMessage();
1023
+           if (!response.ok) throw new Error(`API Error: ${response.status} ${response.statusText}`);
1024
+           const data = await response.json();
1025
+ const optimized = data.optimized_text || data.result || data.output || null;
1026
+ if (optimized) {
1027
+ appendMessage("bot", optimized, { withCopy: true, uniqueId: data.id });
1028
+ } else {
1029
+ appendMessage("bot", "⚠️ The API responded successfully but didn't return optimized text.");
1030
+ }
1031
+ await saveHistory();
1032
+         } catch (error) {
1033
+           console.error("Optimization failed:", error);
1034
+           removeLoadingMessage();
1035
+           appendMessage(
1036
+             "bot",
1037
+             `🚨 Connection error: ${error.message}
1038
 
1039
  💡 Tip: Make sure your optimization API is running and accessible.`
1040
+           );
1041
+           await saveHistory();
1042
+         }
1043
+       }
1044
+
1045
 
1046
  sendButton.addEventListener("click", handleSend);
1047
  userInput.addEventListener("input", () => {