Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/bengoldfeder17_highfive.json
T

1 line
9.3 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "bengoldfeder17/highfive", "files": {"api.py": {"ac4e116dac69c334bec8d193a370ccb4b8aebd93": {"t": 1785674483.1426873, "n": 8333, "h": "e9e40f2db918ab4b", "c": "#!/home/highfive/Downloads/highfive/Downloads/bin/python3.11\nimport os\nimport sys\nimport time\nimport threading\nimport base64\nimport io\n\nimport numpy as np\nimport RPi.GPIO as GPIO\nimport pygame\nfrom picamera2 import Picamera2\nfrom PIL import Image\nimport openai\n\n# ─── 0) OpenAI QuickStart setup ──────────────────────────────────────────\nOPENAI_KEY = input(\"Enter your OpenAI Project API key (must start with sk-proj-): \").strip()\nif not OPENAI_KEY.startswith(\"sk-proj-\"):\n print(\"[ERROR] This script only accepts project-scoped API keys (sk-proj-...).\")\n sys.exit(1)\n\nOPENAI_PROJECT = input(\"Enter your OpenAI project ID: \").strip()\n\n# Set API key and project ID as custom header\nopenai.api_key = OPENAI_KEY\nopenai._custom_headers = {\n \"OpenAI-Project\": OPENAI_PROJECT\n}\n\n# ─── 1) Categories & bin mapping ───────────────────────────────────────────\nCLASS_NAMES = [\"biodegradable\", \"cardboard\", \"glass\", \"metal\", \"paper\", \"plastic\", \"trash\"]\nRECYCLE_SET = {\"cardboard\", \"glass\", \"metal\", \"paper\",\"recycling\"}\nTRASH_SET = {\"biodegradable\", \"plastic\", \"trash\"}\n\n# ─── 2) Constants ──────────────────────────────────────────────────────────\nITEM_WEIGHT = 0.125 # lbs per detected item\nDIFF_THRESH = 5 # pixel‐difference threshold\nPAUSE_BEFORE = 2 # seconds to wait once motion detected\nBIN_CAP = 10.0 # default capacity (gallons)\n\n# ─── 3) GPIO & motor setup ────────────────────────────────────────────────\nIN1, IN2, ENA = 23, 24, 5\nGPIO.setmode(GPIO.BCM)\nGPIO.setup(IN1, GPIO.OUT)\nGPIO.setup(IN2, GPIO.OUT)\nGPIO.setup(ENA, GPIO.OUT)\npwm = GPIO.PWM(ENA, 1000)\npwm.start(0)\n\ndef rotate_left(speed=100):\n GPIO.output(IN1, GPIO.HIGH)\n GPIO.output(IN2, GPIO.LOW)\n pwm.ChangeDutyCycle(speed)\n\ndef rotate_right(speed=100):\n GPIO.output(IN1, GPIO.LOW)\n GPIO.output(IN2, GPIO.HIGH)\n pwm.ChangeDutyCycle(speed)\n\ndef stop_motor():\n pwm.ChangeDutyCycle(0)\n GPIO.output(IN1, GPIO.LOW)\n GPIO.output(IN2, GPIO.LOW)\n\n# ─── 4) Camera init & background capture ────────────────────────────────────\nos.environ[\"BCM2835_PERI_BASE\"] = \"0xFE000000\"\nos.environ[\"BCM2708_PERI_BASE\"] = \"0xFE000000\"\n\npicam2 = Picamera2()\ncfg = picam2.create_preview_configuration(main={\"size\": (640,480)})\npicam2.configure(cfg)\npicam2.start()\ntime.sleep(2)\nbackground = picam2.capture_array().astype(np.int16)\n\n# ─── 5) OpenAI‐based classify function (resized, JPEG, sanitized + logging) ─\ndef classify_with_openai(frame: np.ndarray) -> (str, float):\n global CLASS_NAMES\n\n # 1) shrink to 224×224 & convert to RGB\n pil = Image.fromarray(frame).resize((224,224), Image.LANCZOS)\n if pil.mode != \"RGB\":\n pil = pil.convert(\"RGB\")\n\n # 2) JPEG-compress\n buf = io.BytesIO()\n pil.save(buf, format=\"JPEG\", quality=20)\n b64 = base64.b64encode(buf.getvalue()).decode()\n\n # 3) prompt model to reply with exactly one category word\n prompt = (\n \"Classify the object on the platform image into exactly one of these words:\\n\"\n \"biodegradable, cardboard, glass, metal, paper, plastic\\n\"\n \"Reply with exactly one word (no punctuation).\\n\\n\"\n \"Here is the image (base64 JPEG):\\n\" + b64\n )\n resp = openai.chat.completions.create(\n model=\"gpt-4.1\",\n messages=[\n {\"role\": \"system\", \"content\": \"You are an expert recycling classifier.\"},\n {\"role\": \"user\", \"content\": prompt}\n ],\n max_completion_tokens=3\n )\n\n raw = resp.choices[0].message.content.strip().lower()\n print(f\"[OpenAI] raw response → {raw}\") # log to terminal\n\n # 4) sanitize: match against CLASS_NAMES\n label = next((c for c in CLASS_NAMES if raw == c or c in raw), None)\n if label is None:\n print(f\"[OpenAI] unexpected label “{raw}”, defaulting to “trash”\")\n label = \"trash\"\n return label, 1.0\n\n# ─── 6) Shared state & background thread ───────────────────────────────────\nrunning = True\ndisplay_label = \"Waiting for Object\"\nconfidence = 0.0\ntrash_weight = 0.0\nrecycle_weight = 0.0\nbin_capacity = BIN_CAP\n\ndef classify_and_act():\n global display_label, confidence, trash_weight, recycle_weight\n while running:\n frame = picam2.capture_array()\n diff_val = np.mean(np.abs(frame.astype(np.int16) - background))\n if diff_val < DIFF_THRESH:\n display_label = \"Waiting for Object\"\n confidence = 0.0\n else:\n time.sleep(PAUSE_BEFORE)\n raw_label, conf = classify_with_openai(frame)\n confidence = conf\n\n if raw_label in RECYCLE_SET:\n display_label = f\"Recycle ({raw_label.capitalize()})\"\n recycle_weight += ITEM_WEIGHT\n rotate_left(); time.sleep(4); stop_motor()\n time.sleep(1)\n rotate_right(); time.sleep(4); stop_motor()\n elif raw_label in TRASH_SET:\n display_label = f\"Trash ({raw_label.capitalize()})\"\n trash_weight += ITEM_WEIGHT\n rotate_right(); time.sleep(4); stop_motor()\n time.sleep(1)\n rotate_left(); time.sleep(4); stop_motor()\n else:\n display_label = f\"Unknown ({raw_label.capitalize()})\"\n stop_motor()\n\n time.sleep(5)\n\nthreading.Thread(target=classify_and_act, daemon=True).start()\n\n# ─── 7) Pygame UI loop ───────────────────────────────────────────────────────\npygame.init()\nSCREEN_W, SCREEN_H = 720, 1280\nscreen = pygame.display.set_mode((SCREEN_W, SCREEN_H))\npygame.display.set_caption(\"AI Trash\")\n\nWHITE = (255,255,255)\nBLACK = (0,0,0)\nLIGHT_BLUE = (173,216,230)\nLIGHT_CORAL = (240,128,128)\n\nfont_title = pygame.font.Font(None, 100)\nfont_text = pygame.font.Font(None, 60)\nfont_button = pygame.font.Font(None, 50)\n\nbtn_h, btn_w = 80, 220\nbtn_y = SCREEN_H - btn_h - 100\nreset_rect = pygame.Rect(60, btn_y, btn_w, btn_h)\ncap_rect = pygame.Rect(SCREEN_W - btn_w - 60, btn_y, btn_w, btn_h)\n\ntry:\n while running:\n for ev in pygame.event.get():\n if ev.type == pygame.QUIT:\n running = False\n elif ev.type == pygame.MOUSEBUTTONDOWN:\n x,y = ev.pos\n if reset_rect.collidepoint(x,y):\n trash_weight = recycle_weight = 0.0\n display_label = \"Waiting for Object\"\n elif cap_rect.collidepoint(x,y):\n bin_capacity += -0.5 if x < cap_rect.centerx else 0.5\n bin_capacity = max(1.0, bin_capacity)\n\n screen.fill(WHITE)\n title = font_title.render(\"AI Trash\", True, BLACK)\n screen.blit(title, ((SCREEN_W - title.get_width())//2, 20))\n\n cur = font_text.render(display_label, True, BLACK)\n screen.blit(cur, ((SCREEN_W - cur.get_width())//2, 140))\n\n pct_rec = min(recycle_weight / bin_capacity, 1.0)\n pct_tr = min(trash_weight / bin_capacity, 1.0)\n rec = font_text.render(f\"Recycling: {pct_rec:.1%}\", True, LIGHT_BLUE)\n tr = font_text.render(f\"Trash: {pct_tr:.1%}\", True, LIGHT_CORAL)\n screen.blit(rec, ((SCREEN_W - rec.get_width())//2, 220))\n screen.blit(tr, ((SCREEN_W - tr.get_width())//2, 300))\n\n frame = picam2.capture_array()\n if frame.ndim == 2:\n frame = np.stack((frame,)*3, axis=-1)\n elif frame.shape[2] == 4:\n frame = frame[:,:,:3]\n h,w = frame.shape[:2]\n surf = pygame.image.frombuffer(frame.tobytes(), (w,h), 'RGB')\n fw = SCREEN_W - 120\n fh = int(fw * h / w)\n feed = pygame.transform.scale(surf, (fw, fh))\n screen.blit(feed, ((SCREEN_W - fw)//2, 380))\n\n pygame.draw.rect(screen, LIGHT_BLUE, reset_rect)\n rs = font_button.render(\"Reset\", True, BLACK)\n screen.blit(rs, (reset_rect.x + (btn_w - rs.get_width())//2,\n reset_rect.y + (btn_h - rs.get_height())//2))\n\n pygame.draw.rect(screen, LIGHT_BLUE, cap_rect)\n ct = font_button.render(f\"< {bin_capacity:.1f} gal >\", True, BLACK)\n screen.blit(ct, (cap_rect.x + (btn_w - ct.get_width())//2,\n cap_rect.y + (btn_h - ct.get_height())//2))\n\n pygame.display.flip()\n\nfinally:\n picam2.stop()\n pwm.stop()\n GPIO.cleanup()\n pygame.quit()\n"}}}}