{"id":4657,"date":"2026-06-20T12:43:03","date_gmt":"2026-06-20T10:43:03","guid":{"rendered":"https:\/\/jvelektronika.cz\/?page_id=4657"},"modified":"2026-06-21T15:57:24","modified_gmt":"2026-06-21T13:57:24","slug":"ai-jenda","status":"publish","type":"page","link":"https:\/\/jvelektronika.cz\/?page_id=4657","title":{"rendered":"AI JENDA"},"content":{"rendered":"\n<p class=\"has-text-align-center has-background has-medium-font-size\" style=\"background:linear-gradient(135deg,rgb(6,147,227) 0%,rgb(240,241,242) 46%)\"><strong>Um\u011bl\u00e1 inteligence JENDA<\/strong><\/p>\n\n\n\n<p>V sou\u010dasn\u00e9 podob\u011b  AI JENDA  disponuje grafick\u00fdm animovan\u00fdm UI. Komunikace s JENDOU prob\u00edh\u00e1 v \u010desk\u00e9m jazyce a st\u00e1le z\u016fstav\u00e1 i mo\u017enost ps\u00e1t textov\u00e9 konverzace. Funguje pln\u011b offline s vyu\u017eit\u00edm HW po\u010d\u00edta\u010de av\u0161ak um\u00ed si pot\u0159ebn\u00e9 znalosti a data st\u00e1hnout z internetu a na povel i r\u016fzn\u00e9 informace ulo\u017eit na disk trvale. <\/p>\n\n\n\n<p><strong>HW m\u00e9ho PC beru jako doporu\u010den\u00fd<\/strong> a instalace na v\u00fdkonov\u011b slab\u0161\u00ed PC je riziko ka\u017ed\u00e9ho kdo si JENDU zprovozn\u00ed.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"576\" src=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-1024x576.png\" alt=\"\" class=\"wp-image-4647\" srcset=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-1024x576.png 1024w, https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-300x169.png 300w, https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-768x432.png 768w, https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-1536x864.png 1536w, https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level-2048x1152.png 2048w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-text-align-center has-background\" style=\"background-color:#dde8f1\"><strong>RYZEN 9 5900X 12-Core &#8211; GeForce RTX 3070Ti 8Gb &#8211; DDR4 RAM 32GB &#8211; SSD 1Tb<\/strong>, <strong>Win11 x64<\/strong><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>UK\u00c1ZKA FUNK\u010cNOSTI AI S P\u0158EDCHOZ\u00cd GRAFIKOU<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls poster=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/ai-next-level.png\" src=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/20260527_174415.mp4\"><\/video><figcaption class=\"wp-element-caption\">UK\u00c1ZKA FUNK\u010cNOSTI AI<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>JEDNOTLIV\u00c9 INFOMACE PRO N\u00c1VOD ZPROVOZN\u011aN\u00cd JENDY BUDU VKL\u00c1DAT POSTUPN\u011a, jedn\u00e1 se o pom\u011brn\u011b komplikovanou z\u00e1le\u017eitost s vyu\u017eit\u00edm mnoha komponent a c\u00edlem je vytvo\u0159it takov\u00fd n\u00e1vod na jeho\u017e z\u00e1klad\u011b si ka\u017ed\u00fd kdo ovl\u00e1da po\u010d\u00edta\u010d alespo\u0148 na st\u0159edn\u00ed urovni s minim\u00e1ln\u00edm z\u00e1kladem programov\u00e1n\u00ed bude moci s\u00e1m zprovoznit um\u011blou inteligenci.<\/p>\n\n\n\n<p>Po dokon\u010den\u00ed n\u00e1vodu vlo\u017e\u00edm i n\u011bkter\u00e9 soubory ke sta\u017een\u00ed v komprimovan\u00e9 slo\u017ece.<\/p>\n\n\n\n<p class=\"has-text-align-center has-text-color\" style=\"color:#969da2\">POSLEDN\u00cd ZM\u011aNA 21.6. 2026<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-text-align-center has-background\" style=\"background-color:#c3e4f8\">PRO VE\u0160KER\u00c9 ZDE UVEDEN\u00c9 ZDROJOV\u00c9 K\u00d3DY JE NUTN\u00c9 VYU\u017d\u00cdVAT K\u00d3DOV\u00c1N\u00cd UTF-8<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Vytvo\u0159te slo\u017eku s n\u00e1zvem johntron<\/p>\n\n\n\n<p>Instalace i spou\u0161t\u011bn\u00ed bude prob\u00edhat pomoc\u00ed termin\u00e1lu otev\u0159en\u00e9ho z t\u00e9to slo\u017eky.<\/p>\n\n\n\n<p>Pro snadn\u00e9 spu\u0161t\u011bn\u00ed jako b\u011b\u017enou aplikaci vytvo\u0159\u00edme soubor start.bat<\/p>\n\n\n\n<p>Spou\u0161t\u011bn\u00ed JENDY na m\u00e9m po\u010d\u00edta\u010di prob\u00edh\u00e1 z disku G:\\  &#8230;. ozna\u010den\u00ed jednotky nastavte podle disku na kter\u00e9m bude AI ulo\u017eena a spou\u0161t\u011bna.<\/p>\n\n\n\n<p>(JENDU spus\u0165te a\u017e budou \u00fasp\u011b\u0161n\u011b dokon\u010deny ve\u0161ker\u00e9 kroky)<\/p>\n\n\n\n<p>Obsah souboru start.bat:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>@echo off\r\n\r\ncd \/d G:\\johntron\r\n\r\ncall .\\venv\\Scripts\\activate\r\n\r\npython main.py\r\n\r\npause<\/code><\/pre>\n\n\n\n<p>1) St\u00e1hn\u011bte a nainstalujte program MICROSOFT Visual Studio Code. Program je zdarma.<\/p>\n\n\n\n<p>2) St\u00e1hn\u011bte si PyInstaller (<a href=\"https:\/\/github.com\/pyinstaller\/pyinstaller\" data-type=\"link\" data-id=\"https:\/\/github.com\/pyinstaller\/pyinstaller\">ZDE<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install pyinstaller\r\npyinstaller --onefile main.py<\/code><\/pre>\n\n\n\n<p>3) St\u00e1hn\u011bte a nainstalujte lok\u00e1ln\u00ed\/offline AI model Ollama (<a href=\"https:\/\/github.com\/ollama\/ollama\" data-type=\"link\" data-id=\"https:\/\/github.com\/ollama\/ollama\">ZDE<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>ollama run mistral<\/code><\/pre>\n\n\n\n<p>4) <\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>pokra\u010dov\u00e1n\u00ed p\u0159\u00ed\u0161t\u011b &#8230;.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>ui.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># =========================================================\n# JENDA AI v3 - BLUE CINEMATIC EDITION\n# =========================================================\n\nimport math\nimport random\nfrom datetime import datetime\n\nimport numpy as np\nimport sounddevice as sd\n\nfrom PyQt5.QtCore import Qt, QTimer\nfrom PyQt5.QtGui import (\n    QColor,\n    QPainter,\n    QPen,\n    QFont,\n    QLinearGradient\n)\n\nfrom PyQt5.QtWidgets import (\n    QWidget,\n    QLabel,\n    QTextEdit,\n    QVBoxLayout,\n    QHBoxLayout,\n    QFrame,\n    QPushButton\n)\n\nfrom commands import *\n\n\n# =========================================================\n# COLOR PALETTE\n# =========================================================\n\nBLUE_MAIN = \"#2ea8ff\"\nBLUE_BRIGHT = \"#5bc0ff\"\nBLUE_DARK = \"#0a1630\"\nBLUE_SOFT = \"#1f7cff\"\n\nTEXT = \"#8fd3ff\"\n\n\n# =========================================================\n# HUD PANEL\n# =========================================================\n\nclass HudPanel(QFrame):\n\n    def __init__(self, title):\n\n        super().__init__()\n\n        self.setStyleSheet(f\"\"\"\n            QFrame {{\n                background-color: rgba(5,10,25,180);\n                border: 2px solid rgba(46,168,255,120);\n                border-radius: 26px;\n            }}\n        \"\"\")\n\n        layout = QVBoxLayout()\n\n        layout.setContentsMargins(16, 16, 16, 16)\n\n        title_label = QLabel(title)\n\n        title_label.setStyleSheet(f\"\"\"\n            color:{BLUE_BRIGHT};\n            font-size:18px;\n            font-weight:bold;\n            padding-bottom:8px;\n        \"\"\")\n\n        layout.addWidget(title_label)\n\n        self.setLayout(layout)\n\n\n# =========================================================\n# MAIN UI\n# =========================================================\n\nclass UI(QWidget):\n\n    def __init__(self):\n\n        super().__init__()\n\n        self.setWindowTitle(\"JENDA AI v3\")\n\n        self.showMaximized()\n\n        self.setStyleSheet(\"\"\"\n            background:black;\n        \"\"\")\n\n        # =====================================================\n        # STATES\n        # =====================================================\n\n        self.audio_level = 0\n\n        self.rotation = 0\n\n        self.eye_blink = 1.0\n\n        self.blink_timer = 0\n\n        self.speak_pulse = 0\n\n        self.energy_phase = 0\n\n        self.ai_state = \"JENDA CORE\"\n\n        self.breath = 0\n\n        self.breath_dir = 1\n\n        # =====================================================\n        # AUDIO\n        # =====================================================\n\n        self.stream = sd.InputStream(\n            channels=1,\n            callback=self.audio_callback\n        )\n\n        self.stream.start()\n\n        # =====================================================\n        # PARTICLES\n        # =====================================================\n\n        self.particles = &#91;]\n\n        for _ in range(900):\n\n            self.particles.append({\n\n                \"x\": random.uniform(0, 1920),\n\n                \"y\": random.uniform(0, 1080),\n\n                \"size\": random.uniform(1, 4),\n\n                \"speed\": random.uniform(0.1, 0.9),\n\n                \"alpha\": random.randint(40, 255),\n\n                \"depth\": random.uniform(0.4, 1.8)\n\n            })\n\n        # =====================================================\n        # LAYOUT\n        # =====================================================\n\n        root = QHBoxLayout()\n\n        root.setContentsMargins(20, 20, 20, 20)\n\n        root.setSpacing(24)\n\n        # =====================================================\n        # LEFT\n        # =====================================================\n\n        left = QVBoxLayout()\n\n        left.setSpacing(18)\n\n        self.logo = QLabel(\"JENDA\")\n\n        self.logo.setFont(QFont(\"Arial\", 40, QFont.Bold))\n\n        self.logo.setStyleSheet(f\"\"\"\n            color:{BLUE_BRIGHT};\n            padding:10px;\n        \"\"\")\n\n        left.addWidget(self.logo)\n\n        # =====================================================\n        # CHAT PANEL\n        # =====================================================\n\n        self.chat_panel = HudPanel(\"KONVERZACE\")\n\n        self.chat = QTextEdit()\n\n        self.chat.setReadOnly(True)\n\n        self.chat.setStyleSheet(f\"\"\"\n            background:transparent;\n            border:none;\n            color:{TEXT};\n            font-size:15px;\n            padding:6px;\n        \"\"\")\n\n        self.chat_panel.layout().addWidget(self.chat)\n\n        left.addWidget(self.chat_panel, 4)\n\n        # =====================================================\n        # VOICE\n        # =====================================================\n\n        self.voice_panel = HudPanel(\"POSLOUCH\u00c1M\")\n\n        self.wave_label = QLabel(\"\u2582\u2583\u2584\u2585\u2586\u2587\")\n\n        self.wave_label.setAlignment(Qt.AlignCenter)\n\n        self.wave_label.setStyleSheet(f\"\"\"\n            color:{BLUE_BRIGHT};\n            font-size:28px;\n            padding:10px;\n        \"\"\")\n\n        self.voice_panel.layout().addWidget(self.wave_label)\n\n        self.voice_status = QLabel(\"STATUS: ONLINE\")\n\n        self.voice_status.setStyleSheet(f\"\"\"\n            color:#00ff66;\n            font-size:14px;\n            padding:6px;\n        \"\"\")\n\n        self.voice_panel.layout().addWidget(self.voice_status)\n\n        left.addWidget(self.voice_panel, 1)\n\n        # =====================================================\n        # QUICK COMMANDS\n        # =====================================================\n\n        self.quick_panel = HudPanel(\"P\u0158\u00cdKAZY\")\n\n        quick_buttons = &#91;\n\n            (\"GOOGLE\", open_google),\n            (\"YOUTUBE\", open_youtube),\n            (\"WIKIPEDIA\", open_wikipedia),\n            (\"PR\u016eZKUMN\u00cdK\", open_explorer),\n            (\"SPR\u00c1VCE \u00daLOH\", open_task_manager),\n            (\"NASTAVEN\u00cd\", open_settings)\n\n        ]\n\n        for text, func in quick_buttons:\n\n            btn = QPushButton(text)\n\n            btn.clicked.connect(func)\n\n            btn.setStyleSheet(f\"\"\"\n                QPushButton {{\n                    background-color: rgba(15,20,40,180);\n                    border: 1px solid rgba(91,192,255,100);\n                    border-radius: 14px;\n                    color:{TEXT};\n                    padding:12px;\n                    font-size:13px;\n                }}\n\n                QPushButton:hover {{\n                    background-color: rgba(46,168,255,60);\n                    border: 1px solid rgba(91,192,255,220);\n                }}\n            \"\"\")\n\n            self.quick_panel.layout().addWidget(btn)\n\n        left.addWidget(self.quick_panel, 2)\n\n        root.addLayout(left, 2)\n\n        # =====================================================\n        # CENTER\n        # =====================================================\n\n        center = QVBoxLayout()\n\n        center.addStretch()\n\n        center.addStretch()\n\n        root.addLayout(center, 3)\n\n        # =====================================================\n        # RIGHT\n        # =====================================================\n\n        right = QVBoxLayout()\n\n        right.setSpacing(18)\n\n        # =====================================================\n        # CLOCK\n        # =====================================================\n\n        self.clock_panel = HudPanel(\"\u010cAS\")\n\n        self.clock = QLabel(\"--:--:--\")\n\n        self.clock.setStyleSheet(f\"\"\"\n            color:{BLUE_BRIGHT};\n            font-size:28px;\n            padding:6px;\n        \"\"\")\n\n        self.clock_panel.layout().addWidget(self.clock)\n\n        self.date_label = QLabel(\"\")\n\n        self.date_label.setStyleSheet(f\"\"\"\n            color:{TEXT};\n            font-size:16px;\n            padding-left:6px;\n        \"\"\")\n\n        self.clock_panel.layout().addWidget(self.date_label)\n\n        right.addWidget(self.clock_panel)\n\n        # =====================================================\n        # SYSTEM\n        # =====================================================\n\n        self.system_panel = HudPanel(\"SYST\u00c9M\")\n\n        self.cpu = QLabel(\"CPU   32%\")\n        self.ram = QLabel(\"RAM   48%\")\n        self.disk = QLabel(\"DISK  26%\")\n\n        for lbl in &#91;self.cpu, self.ram, self.disk]:\n\n            lbl.setStyleSheet(f\"\"\"\n                color:{TEXT};\n                font-size:16px;\n                padding:12px;\n            \"\"\")\n\n            self.system_panel.layout().addWidget(lbl)\n\n        right.addWidget(self.system_panel, 2)\n\n        # =====================================================\n        # PC CONTROL\n        # =====================================================\n\n        self.pc_panel = HudPanel(\"OVL\u00c1D\u00c1N\u00cd PC\")\n\n        pc_buttons = &#91;\n\n            (\"NASTAVEN\u00cd\", open_settings),\n            (\"SPR\u00c1VCE \u00daLOH\", open_task_manager),\n            (\"ZAMKNOUT\", lock_pc),\n            (\"RESTART\", restart_pc)\n\n        ]\n\n        for text, func in pc_buttons:\n\n            btn = QPushButton(text)\n\n            btn.clicked.connect(func)\n\n            btn.setStyleSheet(f\"\"\"\n                QPushButton {{\n                    background-color: rgba(15,20,40,180);\n                    border: 1px solid rgba(91,192,255,100);\n                    border-radius: 14px;\n                    color:{TEXT};\n                    padding:12px;\n                    font-size:13px;\n                }}\n\n                QPushButton:hover {{\n                    background-color: rgba(46,168,255,60);\n                    border: 1px solid rgba(91,192,255,220);\n                }}\n            \"\"\")\n\n            self.pc_panel.layout().addWidget(btn)\n\n        right.addWidget(self.pc_panel, 2)\n\n        root.addLayout(right, 2)\n\n        self.setLayout(root)\n\n        # =====================================================\n        # TIMERS\n        # =====================================================\n\n        self.clock_timer = QTimer()\n\n        self.clock_timer.timeout.connect(self.update_clock)\n\n        self.clock_timer.start(1000)\n\n        self.anim_timer = QTimer()\n\n        self.anim_timer.timeout.connect(self.animate)\n\n        self.anim_timer.start(16)\n\n        self.wave_timer = QTimer()\n\n        self.wave_timer.timeout.connect(self.animate_wave)\n\n        self.wave_timer.start(120)\n\n    # =========================================================\n    # AUDIO\n    # =========================================================\n\n    def audio_callback(\n        self,\n        indata,\n        frames,\n        time,\n        status\n    ):\n\n        volume = np.linalg.norm(indata) * 10\n\n        self.audio_level = min(volume, 1.0)\n\n    # =========================================================\n    # CLOCK\n    # =========================================================\n\n    def update_clock(self):\n\n        now = datetime.now()\n\n        self.clock.setText(now.strftime(\"%H:%M:%S\"))\n\n        self.date_label.setText(\n            now.strftime(\"%d.%m.%Y\")\n        )\n\n    # =========================================================\n    # WAVE\n    # =========================================================\n\n    def animate_wave(self):\n\n        waves = &#91;\n\n            \"\u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2588\",\n            \"\u2582\u2583\u2584\u2585\u2586\u2587\u2588\u2587\",\n            \"\u2583\u2584\u2585\u2586\u2587\u2588\u2587\u2586\",\n            \"\u2584\u2585\u2586\u2587\u2588\u2587\u2586\u2585\"\n\n        ]\n\n        self.wave_label.setText(\n            random.choice(waves)\n        )\n\n    # =========================================================\n    # ANIMATION\n    # =========================================================\n\n    def animate(self):\n\n        self.energy_phase += 0.03\n\n        self.breath += 0.45 * self.breath_dir\n\n        if self.breath &gt; 10:\n            self.breath_dir = -1\n\n        if self.breath &lt; -10:\n            self.breath_dir = 1\n\n        # blinking\n\n        self.blink_timer += 1\n\n        if self.blink_timer &gt; 240:\n\n            self.eye_blink -= 0.12\n\n            if self.eye_blink &lt;= 0.05:\n\n                self.eye_blink = 1.0\n\n                self.blink_timer = 0\n\n        # speaking\n\n        if self.audio_level &gt; 0.12:\n\n            self.ai_state = \"JENDA ACTIVE\"\n\n            self.speak_pulse = min(\n                self.speak_pulse + 4,\n                100\n            )\n\n        else:\n\n            self.ai_state = \"JENDA CORE\"\n\n            self.speak_pulse = max(\n                self.speak_pulse - 3,\n                0\n            )\n\n        self.update()\n\n    # =========================================================\n    # PAINT\n    # =========================================================\n\n    def paintEvent(self, event):\n\n        super().paintEvent(event)\n\n        painter = QPainter(self)\n\n        painter.setRenderHint(\n            QPainter.Antialiasing\n        )\n\n        w = self.width()\n\n        h = self.height()\n\n        cx = w \/\/ 2\n\n        cy = h \/\/ 2\n\n        # =====================================================\n        # BACKGROUND GRADIENT\n        # =====================================================\n\n        gradient = QLinearGradient(0, 0, 0, h)\n\n        gradient.setColorAt(0, QColor(0, 0, 0))\n\n        gradient.setColorAt(1, QColor(5, 10, 30))\n\n        painter.fillRect(\n            self.rect(),\n            gradient\n        )\n\n        # =====================================================\n        # PARTICLES\n        # =====================================================\n\n        painter.setPen(Qt.NoPen)\n\n        for p in self.particles:\n\n            glow_size = p&#91;\"size\"] * (\n                2 + p&#91;\"depth\"]\n            )\n\n            painter.setBrush(\n\n                QColor(\n                    46,\n                    168,\n                    255,\n                    int(p&#91;\"alpha\"] * 0.2)\n                )\n\n            )\n\n            painter.drawEllipse(\n\n                int(p&#91;\"x\"] - glow_size \/ 2),\n                int(p&#91;\"y\"] - glow_size \/ 2),\n\n                int(glow_size),\n                int(glow_size)\n\n            )\n\n            painter.setBrush(\n\n                QColor(\n                    120,\n                    210,\n                    255,\n                    p&#91;\"alpha\"]\n                )\n\n            )\n\n            painter.drawEllipse(\n\n                int(p&#91;\"x\"]),\n                int(p&#91;\"y\"]),\n\n                int(p&#91;\"size\"]),\n                int(p&#91;\"size\"])\n\n            )\n\n            p&#91;\"y\"] += (\n\n                p&#91;\"speed\"] * p&#91;\"depth\"]\n\n                + self.audio_level * 0.6\n\n            )\n\n            if p&#91;\"y\"] &gt; h:\n\n                p&#91;\"y\"] = 0\n\n                p&#91;\"x\"] = random.randint(0, w)\n\n        # =====================================================\n        # FACE CORE\n        # =====================================================\n\n        face_radius = int(\n\n            210\n\n            + self.breath\n\n            + self.speak_pulse * 0.15\n\n        )\n\n        # aura\n\n        for i in range(12):\n\n            radius = face_radius + i * 18\n\n            alpha = 45 - i * 3\n\n            painter.setBrush(\n\n                QColor(\n                    46,\n                    168,\n                    255,\n                    alpha\n                )\n\n            )\n\n            painter.drawEllipse(\n\n                int(cx - radius),\n                int(cy - radius),\n\n                int(radius * 2),\n                int(radius * 2)\n\n            )\n\n        # energy rings\n\n        for i in range(8):\n\n            radius = int(\n                145\n                + i * 26\n                + math.sin(\n                    self.energy_phase + i\n                ) * 5\n            )\n\n            pen = QPen(\n\n                QColor(\n                    91,\n                    192,\n                    255,\n                    150 - i * 14\n                ),\n\n                2\n            )\n\n            painter.setPen(pen)\n\n            painter.drawEllipse(\n\n                int(cx - radius),\n                int(cy - radius),\n\n                int(radius * 2),\n                int(radius * 2)\n\n            )\n\n        # =====================================================\n        # EYES\n        # =====================================================\n\n        eye_offset_x = 92\n\n        eye_y = cy - 40\n\n        eye_w = 92\n\n        eye_h = int(\n            34 * self.eye_blink\n        )\n\n        for glow in range(5):\n\n            alpha = 60 - glow * 10\n\n            painter.setBrush(\n\n                QColor(\n                    91,\n                    192,\n                    255,\n                    alpha\n                )\n\n            )\n\n            size_w = eye_w + glow * 16\n\n            size_h = max(\n                6,\n                eye_h + glow * 10\n            )\n\n            # left\n\n            painter.drawRoundedRect(\n\n                int(cx - eye_offset_x - size_w \/\/ 2),\n                int(eye_y - glow * 4),\n\n                int(size_w),\n                int(size_h),\n\n                18,\n                18\n\n            )\n\n            # right\n\n            painter.drawRoundedRect(\n\n                int(cx + eye_offset_x - size_w \/\/ 2),\n                int(eye_y - glow * 4),\n\n                int(size_w),\n                int(size_h),\n\n                18,\n                18\n\n            )\n\n        painter.setBrush(\n\n            QColor(\n                255,\n                255,\n                255,\n                240\n            )\n\n        )\n\n        painter.setPen(Qt.NoPen)\n\n        # left eye\n\n        painter.drawRoundedRect(\n\n            int(cx - eye_offset_x - eye_w \/\/ 2),\n            int(eye_y),\n\n            int(eye_w),\n            int(max(6, eye_h)),\n\n            18,\n            18\n\n        )\n\n        # right eye\n\n        painter.drawRoundedRect(\n\n            int(cx + eye_offset_x - eye_w \/\/ 2),\n            int(eye_y),\n\n            int(eye_w),\n            int(max(6, eye_h)),\n\n            18,\n            18\n\n        )\n\n        # =====================================================\n        # MOUTH\n        # =====================================================\n\n        mouth_width = int(\n            50\n            + self.audio_level * 130\n        )\n\n        mouth_height = int(\n            5\n            + self.audio_level * 18\n        )\n\n        for i in range(5):\n\n            painter.setBrush(\n\n                QColor(\n                    91,\n                    192,\n                    255,\n                    50 - i * 8\n                )\n\n            )\n\n            painter.drawRoundedRect(\n\n                int(cx - mouth_width \/\/ 2 - i * 4),\n                int(cy + 92 - i * 2),\n\n                int(mouth_width + i * 8),\n                int(mouth_height + i * 4),\n\n                10,\n                10\n\n            )\n\n        painter.setBrush(\n\n            QColor(\n                255,\n                255,\n                255,\n                220\n            )\n\n        )\n\n        painter.drawRoundedRect(\n\n            int(cx - mouth_width \/\/ 2),\n            int(cy + 92),\n\n            int(mouth_width),\n            int(mouth_height),\n\n            8,\n            8\n\n        )\n\n        # =====================================================\n        # BOTTOM TEXT\n        # =====================================================\n\n        text_width = 420\n\n        text_height = 80\n\n        text_x = cx - text_width \/\/ 2\n\n        text_y = h - 130\n\n        # glow box\n\n        painter.setBrush(\n\n            QColor(\n                10,\n                20,\n                40,\n                180\n            )\n\n        )\n\n        painter.setPen(\n\n            QPen(\n                QColor(\n                    91,\n                    192,\n                    255,\n                    120\n                ),\n                2\n            )\n\n        )\n\n        painter.drawRoundedRect(\n\n            text_x,\n            text_y,\n\n            text_width,\n            text_height,\n\n            28,\n            28\n\n        )\n\n        painter.setPen(\n\n            QColor(\n                91,\n                192,\n                255,\n                255\n            )\n\n        )\n\n        painter.setFont(\n            QFont(\n                \"Arial\",\n                28,\n                QFont.Bold\n            )\n        )\n\n        painter.drawText(\n\n            text_x,\n            text_y,\n\n            text_width,\n            text_height,\n\n            Qt.AlignCenter,\n\n            self.ai_state\n\n        )\n\n        # =====================================================\n        # SCANLINES\n        # =====================================================\n\n        painter.setPen(\n\n            QPen(\n                QColor(\n                    91,\n                    192,\n                    255,\n                    10\n                ),\n                1\n            )\n\n        )\n\n        for y in range(0, h, 4):\n\n            painter.drawLine(\n                0,\n                y,\n                w,\n                y\n            )\n\n    # =========================================================\n    # LOG\n    # =========================================================\n\n    def log_msg(self, text):\n\n        self.chat.append(text)\n\n    # =========================================================\n    # STATUS\n    # =========================================================\n\n    def set_mode(self, mode):\n\n        self.voice_status.setText(\n            f\"STATUS: {mode}\"\n        )<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>voice.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import speech_recognition as sr\nimport webrtcvad\nimport collections\nimport pyaudio\nimport subprocess\nimport os\n\n# \ud83c\udfa4 Speech recognition\nrecognizer = sr.Recognizer()\n\n# \ud83d\udd0a VAD\nvad = webrtcvad.Vad(2)\n\nRATE = 16000\nFRAME_DURATION = 30\nFRAME_SIZE = int(RATE * FRAME_DURATION \/ 1000)\n\npa = pyaudio.PyAudio()\n\n# \ud83d\udcc1 Piper setup\nBASE_DIR = os.path.dirname(os.path.abspath(__file__))\nPIPER_PATH = os.path.join(BASE_DIR, \"piper\", \"piper.exe\")\nMODEL_PATH = os.path.join(BASE_DIR, \"piper\", \"cs_CZ-jirka-medium.onnx\")\nOUTPUT_FILE = os.path.join(BASE_DIR, \"piper\", \"out.wav\")\n\n\n# \ud83d\udd0a HLAS (PIPER)\ndef speak(text):\n    print(\"JOHNTRON:\", text)\n\n    try:\n        cmd = &#91;\n            PIPER_PATH,\n            \"--model\", MODEL_PATH,\n            \"--output_file\", OUTPUT_FILE\n        ]\n\n        process = subprocess.Popen(\n            cmd,\n            stdin=subprocess.PIPE,\n            shell=False\n        )\n\n        process.communicate(input=text.encode(\"utf-8\"))\n\n        if os.path.exists(OUTPUT_FILE):\n            os.startfile(OUTPUT_FILE)\n\n    except Exception as e:\n        print(\"PIPER ERROR:\", e)\n\n\n# \ud83c\udfa4 POSLECH (VAD)\ndef listen():\n    print(\"\ud83c\udfa4 VAD POSLOUCH\u00c1...\")\n\n    stream = pa.open(\n        format=pyaudio.paInt16,\n        channels=1,\n        rate=RATE,\n        input=True,\n        frames_per_buffer=FRAME_SIZE\n    )\n\n    frames = &#91;]\n    ring_buffer = collections.deque(maxlen=10)\n    triggered = False\n\n    try:\n        while True:\n            frame = stream.read(FRAME_SIZE, exception_on_overflow=False)\n            is_speech = vad.is_speech(frame, RATE)\n\n            if not triggered:\n                ring_buffer.append((frame, is_speech))\n                if len(&#91;f for f, s in ring_buffer if s]) &gt; 6:\n                    triggered = True\n                    print(\"\ud83d\udfe2 START\")\n                    frames.extend(&#91;f for f, _ in ring_buffer])\n                    ring_buffer.clear()\n\n            else:\n                frames.append(frame)\n                ring_buffer.append((frame, is_speech))\n\n                if len(&#91;f for f, s in ring_buffer if not s]) &gt; 8:\n                    print(\"\ud83d\udd34 END\")\n                    break\n\n    finally:\n        stream.stop_stream()\n        stream.close()\n\n    audio = b\"\".join(frames)\n\n    try:\n        import io\n        import wave\n\n        wav_buffer = io.BytesIO()\n        wf = wave.open(wav_buffer, \"wb\")\n        wf.setnchannels(1)\n        wf.setsampwidth(pa.get_sample_size(pyaudio.paInt16))\n        wf.setframerate(RATE)\n        wf.writeframes(audio)\n        wf.close()\n\n        wav_buffer.seek(0)\n\n        with sr.AudioFile(wav_buffer) as source:\n            audio_data = recognizer.record(source)\n\n        text = recognizer.recognize_google(audio_data, language=\"cs-CZ\")\n\n        print(\"SLY\u0160ENO:\", text)\n        return text.lower()\n\n    except Exception as e:\n        print(\"VAD ERROR:\", e)\n        return input(\"Ty: \").lower()<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>vision.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import mss\nimport numpy as np\n\ndef screenshot():\n    with mss.mss() as sct:\n        img = sct.grab(sct.monitors&#91;1])\n        return np.array(img)<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>memory.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import json\nimport os\n\nFILE = \"memory.json\"\n\ndef load():\n    if not os.path.exists(FILE):\n        return &#91;]\n    with open(FILE, \"r\", encoding=\"utf-8\") as f:\n        return json.load(f)\n\ndef save(text, response):\n    data = load()\n    data.append({\"user\": text, \"ai\": response})\n\n    # limit pam\u011bti (posledn\u00edch 50)\n    data = data&#91;-50:]\n\n    with open(FILE, \"w\", encoding=\"utf-8\") as f:\n        json.dump(data, f, ensure_ascii=False, indent=2)\n\ndef get_context():\n    data = load()\n    return \"\\n\".join(&#91;f\"U: {x&#91;'user']}\\nA: {x&#91;'ai']}\" for x in data&#91;-5:]])<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>main.py<\/p>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sys\nfrom threading import Thread\n\nfrom PyQt5.QtWidgets import QApplication\n\nfrom ui import UI\nfrom voice import speak, listen\nfrom brain import ask_ai\n\n\n# =========================================================\n# QT APP\n# =========================================================\n\napp = QApplication(sys.argv)\n\nui = UI()\n\nui.show()\n\n\n# =========================================================\n# START MESSAGE\n# =========================================================\n\nprint(\"\ud83d\udd25 JENDA START\")\n\nui.set_mode(\"SPEAKING\")\n\nspeak(\"Jenda je p\u0159ipraven\")\n\nui.set_mode(\"IDLE\")\n\n\n# =========================================================\n# MAIN LOOP\n# =========================================================\n\ndef assistant_loop():\n\n    while True:\n\n        try:\n\n            # =================================================\n            # LISTENING\n            # =================================================\n\n            ui.set_mode(\"LISTENING\")\n\n            text = listen()\n\n            if not text:\n                continue\n\n            print(\"SLY\u0160ENO:\", text)\n\n            # =================================================\n            # USER MESSAGE\n            # =================================================\n\n            try:\n                ui.chat.append(f\"&lt;span style='color:#55ccff'&gt;Ty:&lt;\/span&gt; {text}\")\n            except:\n                pass\n\n            # =================================================\n            # THINKING\n            # =================================================\n\n            ui.set_mode(\"THINKING\")\n\n            response = ask_ai(text)\n\n            print(\"JENDA:\", response)\n\n            # =================================================\n            # AI MESSAGE\n            # =================================================\n\n            try:\n                ui.chat.append(\n                    f\"&lt;span style='color:#00ff99'&gt;Jenda:&lt;\/span&gt; {response}\"\n                )\n            except:\n                pass\n\n            # =================================================\n            # SPEAKING\n            # =================================================\n\n            ui.set_mode(\"SPEAKING\")\n\n            speak(response)\n\n            # =================================================\n            # IDLE\n            # =================================================\n\n            ui.set_mode(\"IDLE\")\n\n        except Exception as e:\n\n            print(\"MAIN LOOP ERROR:\", e)\n\n            ui.set_mode(\"IDLE\")\n\n\n# =========================================================\n# THREAD\n# =========================================================\n\nthread = Thread(\n    target=assistant_loop,\n    daemon=True\n)\n\nthread.start()\n\n\n# =========================================================\n# RUN APP\n# =========================================================\n\nsys.exit(app.exec_())<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>internet.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import requests\n\ndef search_web(query):\n    try:\n        url = f\"https:\/\/api.duckduckgo.com\/?q={query}&amp;format=json\"\n        res = requests.get(url).json()\n\n        if res.get(\"Abstract\"):\n            return res&#91;\"Abstract\"]\n\n        if res.get(\"RelatedTopics\"):\n            return res&#91;\"RelatedTopics\"]&#91;0].get(\"Text\", \"\")\n\n        return \"Na internetu jsem nic nena\u0161el\"\n\n    except Exception as e:\n        return f\"Internet error: {e}\"<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>control.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport webbrowser\n\ndef execute(text):\n    t = text.lower()\n\n    if \"chrome\" in t:\n        os.system(\"start chrome\")\n        return \"Otev\u00edr\u00e1m Chrome\"\n\n    if \"pozn\u00e1mkov\u00fd blok\" in t:\n        os.system(\"notepad\")\n        return \"Otev\u00edr\u00e1m pozn\u00e1mkov\u00fd blok\"\n\n    if \"kalkula\u010dka\" in t:\n        os.system(\"calc\")\n        return \"Otev\u00edr\u00e1m kalkula\u010dku\"\n\n    if \"slo\u017eku\" in t:\n        os.system(\"explorer\")\n        return \"Otev\u00edr\u00e1m slo\u017eky\"\n\n    if \"youtube\" in t:\n        webbrowser.open(\"https:\/\/youtube.com\")\n        return \"Otev\u00edr\u00e1m YouTube\"\n\n    if \"google\" in t:\n        query = t.replace(\"google\", \"\")\n        webbrowser.open(f\"https:\/\/www.google.com\/search?q={query}\")\n        return \"Hled\u00e1m na Google\"\n\n    return None<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>config.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>WAKE_WORD = \"johntron\"\nMODEL = \"mistral\"<\/code><\/pre>\n\n\n\n<p>commands.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nimport webbrowser\nimport subprocess\n\n\n# =========================================================\n# WEB\n# =========================================================\n\ndef open_youtube():\n\n    webbrowser.open(\"https:\/\/youtube.com\")\n\n\ndef open_google():\n\n    webbrowser.open(\"https:\/\/google.com\")\n\n\ndef open_wikipedia():\n\n    webbrowser.open(\"https:\/\/wikipedia.org\")\n\n\ndef search_google(query):\n\n    url = f\"https:\/\/www.google.com\/search?q={query}\"\n\n    webbrowser.open(url)\n\n\n# =========================================================\n# FILES\n# =========================================================\n\ndef open_documents():\n\n    path = os.path.expanduser(\"~\/Documents\")\n\n    os.startfile(path)\n\n\ndef open_downloads():\n\n    path = os.path.expanduser(\"~\/Downloads\")\n\n    os.startfile(path)\n\n\ndef open_pictures():\n\n    path = os.path.expanduser(\"~\/Pictures\")\n\n    os.startfile(path)\n\n\ndef open_explorer():\n\n    subprocess.Popen(\"explorer\")\n\n\n# =========================================================\n# SYSTEM\n# =========================================================\n\ndef open_task_manager():\n\n    subprocess.Popen(\"taskmgr\")\n\n\ndef open_settings():\n\n    subprocess.Popen(\"start ms-settings:\", shell=True)\n\n\ndef shutdown_pc():\n\n    os.system(\"shutdown \/s \/t 1\")\n\n\ndef restart_pc():\n\n    os.system(\"shutdown \/r \/t 1\")\n\n\ndef lock_pc():\n\n    os.system(\"rundll32.exe user32.dll,LockWorkStation\")<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>brain.py<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import ollama\n\n\nSYSTEM_PROMPT = \"\"\"\nJsi Jenda.\nPokro\u010dil\u00fd \u010desk\u00fd AI asistent.\n\nMluv \u010desky.\nOdpov\u00eddej stru\u010dn\u011b, p\u0159irozen\u011b a inteligentn\u011b.\n\nJsi futuristick\u00e1 AI.\n\"\"\"\n\n\ndef ask_ai(prompt):\n\n    try:\n\n        response = ollama.chat(\n            model=\"llama3\",\n            messages=&#91;\n                {\n                    \"role\": \"system\",\n                    \"content\": SYSTEM_PROMPT\n                },\n                {\n                    \"role\": \"user\",\n                    \"content\": prompt\n                }\n            ]\n        )\n\n        return response&#91;\"message\"]&#91;\"content\"]\n\n    except Exception as e:\n\n        return f\"Chyba AI: {e}\"<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<p>Ve\u0161ker\u00e9 zdrojov\u00e9 k\u00f3dy jsou zde ke sta\u017een\u00ed. Z archivu je p\u0159ekop\u00edrujte do slo\u017eky johntron na disk na kter\u00e9m se bude JENDA spou\u0161t\u011bt. Nyn\u00ed ji\u017e bude sta\u010dit nainstalovat v\u0161e pot\u0159ebn\u00e9 podle n\u00e1vodu.<\/p>\n\n\n\n<p class=\"has-text-align-center\">(po dokon\u010den\u00ed n\u00e1vodu tento text v z\u00e1vorce vyma\u017eu)<\/p>\n\n\n\n<div class=\"wp-block-file has-background\" style=\"background:linear-gradient(135deg,rgb(124,236,229) 31%,rgb(113,194,237) 90%)\"><a id=\"wp-block-file--media-87101dc8-5a17-4dd5-8920-32231c68037c\" href=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/AI-JENDA.zip\">AI JENDA<\/a><a href=\"https:\/\/jvelektronika.cz\/wp-content\/uploads\/2026\/06\/AI-JENDA.zip\" class=\"wp-block-file__button wp-element-button\" download aria-describedby=\"wp-block-file--media-87101dc8-5a17-4dd5-8920-32231c68037c\">St\u00e1hnout<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Opera\u010dn\u00ed syst\u00e9m Windows m\u00e1 ur\u010ditou nev\u00fdhodu a bohu\u017eel pro ka\u017edou odpov\u011b\u010f od JENDY se otev\u0159e aplikace Windows Media Player, kterou je po vyslechnut\u00ed vhodn\u011bj\u0161\u00ed zav\u0159\u00edt. Existuj\u00ed mo\u017enosti jak toto zm\u011bnit, ale tomu se budu v\u011bnovat v budoucnosti podle \u010dasov\u00fdch mo\u017enost\u00ed. Za p\u0159edpokladu, \u017ee budete vyu\u017e\u00edvat Linux, tak nen\u00ed nutn\u00e9 \u0159e\u0161it zav\u00edr\u00e1n\u00ed aplikace audio p\u0159ehr\u00e1va\u010de.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-text-align-center has-small-font-size\">Jako pomocn\u00edka p\u0159i tvorb\u011b UM\u011aL\u00c9 INTELIGENCE JENDA jsem vyu\u017eil ChatGPT (varianta zdarma) <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Um\u011bl\u00e1 inteligence JENDA V sou\u010dasn\u00e9 podob\u011b AI JENDA disponuje grafick\u00fdm animovan\u00fdm UI. Komunikace s JENDOU prob\u00edh\u00e1 v \u010desk\u00e9m jazyce a st\u00e1le z\u016fstav\u00e1 i mo\u017enost ps\u00e1t textov\u00e9 konverzace. Funguje pln\u011b offline s vyu\u017eit\u00edm HW po\u010d\u00edta\u010de av\u0161ak um\u00ed si pot\u0159ebn\u00e9 znalosti a data st\u00e1hnout z internetu a na povel i r\u016fzn\u00e9 informace [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"_links":{"self":[{"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/pages\/4657"}],"collection":[{"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4657"}],"version-history":[{"count":10,"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/pages\/4657\/revisions"}],"predecessor-version":[{"id":4680,"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=\/wp\/v2\/pages\/4657\/revisions\/4680"}],"wp:attachment":[{"href":"https:\/\/jvelektronika.cz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4657"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}