Author SHA1 Message Date
Martin 41b5772ff0 Update README.md 2025-05-29 21:51:25 +02:00
Martin c1a1e9409d Merge pull request #234 from hung-ngm/test-tools-parsing
Test tools parsing
2025-05-28 08:42:18 +02:00
Hung Nguyen 41fe95fcb1 Refine test_tools_parsing 2025-05-28 11:47:21 +10:00
Hung Nguyen c8bccc2395 Added unit tests for tools parsing 2025-05-28 11:44:00 +10:00
Martin e45fa86cda Merge pull request #231 from lckdl/main
fix issue #230
2025-05-27 21:48:30 +02:00
lck c8df9e759c fix: handle missing </think> tag in remove_reasoning_text 2025-05-28 02:26:41 +08:00
Martin b3672c60c0 Merge pull request #229 from Fosowl/dev
update readme
2025-05-27 19:35:08 +02:00
martin legrand 97460ded48 set config.ini back like before 2025-05-27 19:31:28 +02:00
martin legrand 9a34ff3646 set config.ini back like before 2025-05-27 19:30:26 +02:00
martin legrand a53842b8b7 update readme disclaimer 2025-05-27 19:29:03 +02:00
Martin 0a8d898e0b Merge pull request #224 from manra399/feature/added-docker-ignore
Added Docker Ignore file.
2025-05-27 18:50:51 +02:00
martin legrand 92f721886c idk 2025-05-27 18:21:31 +02:00
manra399 ee6687df85 Added Docker Ignore file. 2025-05-27 13:55:52 +01:00
Martin 8d15546771 Merge pull request #212 from ifurther/patch-1
Update README_CHT.md
2025-05-26 18:48:14 +02:00
ifurther 7ad084b27f updat readme 2025-05-26 21:20:17 +08:00
Further 63cd5eddd7 Update README_CHT.md 2025-05-26 20:48:22 +08:00
martin legrand 6d053cc3a5 merge with #191 2025-05-25 15:39:23 +02:00
Martin 27b4aaa5e9 Merge pull request #191 from klimentij/feature/openrouter-provider
Openrouter provider
2025-05-25 15:18:57 +02:00
Klimentiy Bulygin 3c19f26792 Merge branch 'main' into feature/openrouter-provider 2025-05-25 13:15:56 +02:00
Klimentij Bulygin 12eec50e1c return original docker-compose 2025-05-25 13:14:10 +02:00
Klimentij Bulygin cd78cb36a0 minor 2025-05-25 13:13:03 +02:00
Klimentij Bulygin ec8cab2d6b Merge branch 'feature/openrouter-provider' of https://github.com/klimentij/agenticSeek into feature/openrouter-provider 2025-05-25 13:12:33 +02:00
Klimentij Bulygin b1f9375115 OpenRouter in .env.example 2025-05-25 13:11:10 +02:00
martin legrand 758faf6285 readme update & refactor llm_provider 2025-05-25 11:45:18 +02:00
Martin 20457a574a Merge pull request #197 from Fosowl/dev
Expandable view of reasoning above message instead of a separate view
2025-05-24 19:15:14 +02:00
martin legrand d375359582 feat : better view of reasoning 2025-05-24 12:45:10 +02:00
Klimentiy Bulygin f738fc732e Update config.ini 2025-05-24 00:16:16 +02:00
Klimentiy Bulygin 3be07e3dcb Update config.ini 2025-05-24 00:15:36 +02:00
Martin 7d252ad422 Merge pull request #190 from Fosowl/dev
Add stop button, reasoning view, add anthropic provider
2025-05-21 16:40:08 +02:00
Klimentij Bulygin 1c73ef141c Restore original config.ini settings 2025-05-20 22:47:09 +02:00
Klimentij Bulygin e3757f54ac Undo OpenRouter related changes to README files 2025-05-20 22:46:56 +02:00
Klimentij Bulygin 12afae7472 Fix: Correct provider_name parsing in config.ini 2025-05-20 19:58:59 +02:00
Klimentij Bulygin 9cbf62b47d Configure OpenRouter as default and verify API key handling 2025-05-20 17:50:41 +02:00
Klimentij Bulygin 51b0ca54c7 Initial commit for OpenRouter provider 2025-05-20 17:47:40 +02:00
martin legrand 0f116cc3d0 rm png file 2025-05-20 16:57:46 +02:00
martin legrand a19ef5df66 rm : test code 2025-05-20 16:56:13 +02:00
martin legrand 195b4a07a9 fix : safety of bash interpreter 2025-05-20 16:53:04 +02:00
martin legrand e3d01083d9 feat : stop button integration 2025-05-20 16:47:35 +02:00
martin legrand 102dc60efb feat : integrate reasoning view 2025-05-17 22:04:07 +02:00
Martin ca2b05b35e Merge pull request #188 from Fosowl/dev
Better browser fingerprint spoofing + Markdown support for frontend + block color display fix
2025-05-16 22:31:16 +02:00
martin legrand 713c01193f sec: no crossorigin allow 2025-05-16 14:05:36 +02:00
martin legrand 50a9cb8d27 fix : frontend color 2025-05-16 12:41:56 +02:00
martin legrand bd26d7233d refactor : comments + feat : selected lang in config influe browser config 2025-05-16 10:18:26 +02:00
martin legrand 45fbf5a88c fix comment 2025-05-16 09:24:46 +02:00
martin legrand 384d9a8c0b feat : markdown support on frontend 2025-05-16 09:19:45 +02:00
martin legrand 95d5aea1d5 feat : upgrade stealthness 2025-05-16 09:04:19 +02:00
martin legrand 38b1e17628 feat : better browser spoofing 2025-05-15 15:13:25 +02:00
martin legrand 637ca0f826 feat : attempt to bypass bot detection even more 2025-05-14 21:55:59 +02:00
martin legrand 201b3de15c feat : attempt to bypass bot detection 2025-05-14 21:43:13 +02:00
martin legrand 4739a1377c install: improve sh scripts 2025-05-14 18:50:40 +02:00
Martin 4bb7a21604 Merge pull request #181 from CoruNethron/main
Update README.md to match recent code changes
2025-05-12 22:59:19 +02:00
CoruNethron 725a3c3292 Update README.md to match recent code changes
`deepseek-api` was renamed to `deepseek`
`server` directory is now `llm_server`
2025-05-12 15:46:24 +10:00
Martin e72072090e Merge pull request #176 from Fosowl/dev
Fix connection issue with 0.0.0.0 in app.js + more wide browser view
2025-05-08 13:49:31 +02:00
martin legrand ef91502961 fix : connection issue with 0.0.0.0 in app.js + unzoom browser view 2025-05-08 13:38:07 +02:00
Martin 2048af854f Merge pull request #170 from Fosowl/dev
clarification in readme
2025-05-06 22:45:36 +02:00
martin legrand dd6ddaeca3 upd readme 2025-05-06 22:43:51 +02:00
martin legrand 47fec1914a comment out in progress mcp agent to avoid confusion 2025-05-06 22:39:15 +02:00
Martin 9ff69d1876 Merge pull request #168 from Fosowl/dev
update readme - enforce python 3.10
2025-05-06 20:24:44 +02:00
martin legrand ca2eea8089 update readme 2025-05-06 20:23:53 +02:00
Martin 3678c091ac Merge pull request #167 from rense/feature/remote-ollama
Allow connecting to a remote Ollama server
2025-05-06 19:49:18 +02:00
rense 94fb15359b allow connecting to remote Ollama server 2025-05-06 18:03:14 +02:00
Martin 3d1b3d02d9 Merge pull request #166 from Fosowl/dev
Update ja readme up to date
2025-05-06 11:02:13 +02:00
martin legrand c769e790bc upd: jp readme 2025-05-06 11:01:28 +02:00
martin legrand 23a51e6a05 upd: jp readme 2025-05-06 11:00:35 +02:00
martin legrand 94eada9d5d fix : return for json load 2025-05-05 19:11:56 +02:00
Martin 2cdbb49ecd Merge pull request #163 from Fosowl/dev
MCP Agent prototype (with no MCPs yet), Readme update, New function for memory system
2025-05-05 19:04:42 +02:00
MartinandCopilot dd033d4084 Update sources/memory.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-05 19:00:49 +02:00
martin legrand de2650c007 set limit_to_model_ctx to true 2025-05-05 18:36:37 +02:00
martin legrand deb79b81ca fix: typo 2025-05-05 18:32:06 +02:00
martin legrand 24dc1e1a2c fix: ensure logging is not on stdout/err 2025-05-05 18:29:42 +02:00
martin legrand af7619650a ja readme update 2025-05-05 18:17:58 +02:00
martin legrand df645f9a02 remove start ollama in windows scritp 2025-05-05 18:04:07 +02:00
martin legrand dc6eef8031 update readme 2025-05-05 18:01:02 +02:00
martin legrand 5c391dbb6e update japanese readme 2025-05-05 17:55:34 +02:00
martin legrand 101c103aeb fix : reset of blocks 2025-05-05 15:37:13 +02:00
martin legrand de315a43a1 upd readme 2025-05-05 14:23:10 +02:00
martin legrand 90f173ba52 upd readme 2025-05-05 14:22:18 +02:00
martin legrand e4591ea1b4 feat: improve compression/web agent memory management 2025-05-05 14:15:32 +02:00
martin legrand a7deffedec feat : improve memory system 2025-05-04 21:54:01 +02:00
martin legrand 5949540007 feat : tool description proprety 2025-05-04 19:29:31 +02:00
martin legrand 7afb79117b update agent 2025-05-04 18:49:04 +02:00
martin legrand 442bb4a340 Feat : MCP agent 2025-05-04 18:34:05 +02:00
Martin 99467be133 Merge pull request #162 from Fosowl/dev
upd readme examples
2025-05-04 12:02:27 +02:00
martin legrand 887060acdf upd readme 2025-05-04 12:01:44 +02:00
Martin 90609e960c Merge pull request #161 from Fosowl/dev
Update readme manual install instruction
2025-05-04 11:44:26 +02:00
martin legrand d893928221 update all readme 2025-05-04 11:43:32 +02:00
martin legrand 5bc086fd9d update fr readme 2025-05-04 11:24:40 +02:00
martin legrand aca176b9e7 update readme 2025-05-04 11:14:31 +02:00
Martin 9707dbcbf9 Merge pull request #159 from Fosowl/dev
Fixed tts not working with web interface
2025-05-03 19:23:16 +02:00
martin legrand 52e5af8116 fix : tts not working with web interface 2025-05-03 19:22:01 +02:00
Martin 42058244f2 Merge pull request #158 from Fosowl/dev
Chinese and Japanese Text-to-Speech support + readme update
2025-05-03 18:00:12 +02:00
martin legrand bddaa75e8c upd readme 2025-05-03 16:57:43 +02:00
martin legrand 7904439f35 feat : japanese tts support 2025-05-03 16:48:20 +02:00
martin legrand c873af3d00 fix : text to speech in chinese 2025-05-03 16:34:52 +02:00
Martin fa2852d3e7 Merge pull request #153 from Fosowl/dev
Update config.ini + fix requirement.txt + fix SSL issue with undetected chromedriver
2025-05-02 17:41:17 +02:00
martin legrand 1c4ebefae4 rm png file 2025-05-02 17:30:04 +02:00
martin legrand 96a6dd368a feat: fallback for ssl issues 2025-05-02 17:27:22 +02:00
martin legrand ed4f04b19c update requirement.txt 2025-05-02 17:26:26 +02:00
martin legrand f325865869 feat : update config 2025-05-02 16:56:52 +02:00
Martin a15dd998f3 Merge pull request #152 from Fosowl/dev
Improve chromedriver install error handling + improved fileFinder
2025-05-02 14:30:35 +02:00
martin legrand f17dc0550b feat: better fileFinder read 2025-05-02 14:23:00 +02:00
martin legrand ed76c8415b feat : fileFinder read pdf, browser better chromedriver install 2025-05-02 14:10:16 +02:00
Martin 9f2c105074 Merge pull request #151 from Fosowl/Fosowl-patch-1
Create FUNDING.yml
2025-05-02 11:38:48 +02:00
Martin ccef61b2b9 Create FUNDING.yml 2025-05-02 11:38:14 +02:00
martin legrand 3cf1cab68f cmv 2025-05-01 22:16:55 +02:00
martin legrand 0579fd3bb6 upd readme 2025-05-01 22:14:59 +02:00
martin legrand c6688355a7 set code safety on by default 2025-05-01 22:10:54 +02:00
martin legrand 68ed1834a9 fix : errors related to API based LLMs 2025-05-01 18:17:03 +02:00
Martin 487670d207 Merge pull request #147 from floriangab/docs/bump-conduct-and-contributing
Docs/bump conduct and contributing
2025-05-01 14:43:19 +02:00
florianG a109ac98ed docs: bump Python requirement from 3.8 to 3.10 and add Podman 2025-05-01 12:52:30 +02:00
florianG d928a95ed1 docs: update Code of Conduct from v2.0 to v2.1
- Bump version number in header/footer to 2.1
- Prepend reporting clause:
  “Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement: you need to send a private message to maintainers on Discord.”
- Adjust changelog entry accordingly
2025-05-01 12:46:07 +02:00
florianG ffa6873a86 fix: update Discord server invite link 2025-05-01 12:44:49 +02:00
Martin db2eb6fbac Merge pull request #144 from Fosowl/dev
Update readme
2025-04-29 21:39:21 +02:00
martin legrand 68d471bfc6 update readmes 2025-04-29 21:38:29 +02:00
martin legrand 03c71368f5 update readme 2025-04-29 21:19:09 +02:00
Martin 2fd83289fd Merge pull request #143 from Fosowl/dev
fix : start_services.sh not supporting newest docker compose (#137)
2025-04-29 12:02:50 +02:00
martin legrand 7dd60a8946 fix : start_services.sh not supporting newest docker compose (#137) 2025-04-29 12:01:56 +02:00
Martin ccaf1fae52 Merge pull request #141 from Fosowl/Fosowl-patch-3
Update README.md
2025-04-28 20:04:15 +02:00
Martin 4db2ec5911 Update README.md 2025-04-28 20:03:20 +02:00
Martin 34e9baccf3 Merge pull request #140 from Fosowl/Fosowl-patch-3
Update README.md
2025-04-28 10:42:36 +02:00
Martin 3febcfcc04 Update README.md 2025-04-28 10:42:18 +02:00
Martin bb15199b4e Merge pull request #139 from Fosowl/Fosowl-patch-2
Update README.md with new video
2025-04-28 10:38:35 +02:00
Martin 4ec54b690c Update README.md with new video 2025-04-28 10:38:09 +02:00
Martin 3f7408301a Merge pull request #138 from Fosowl/dev
Planner agent improvements
2025-04-28 10:32:36 +02:00
martin legrand da7dde23d4 feat : display planner next task on front 2025-04-28 10:24:30 +02:00
martin legrand 5517f53f8a fix : go interpreter error, hf provider import + feat : more logger 2025-04-27 20:37:23 +02:00
Martin 9f128f8445 Merge pull request #136 from Fosowl/dev
Readme: update image with logo
2025-04-26 20:49:56 +02:00
martin legrand f02f096356 upd readme 2025-04-26 20:48:45 +02:00
martin legrand e0ffa95951 update readme logo 2025-04-26 20:48:06 +02:00
martin legrand 357f0e7bb1 update readme logo 2025-04-26 20:47:36 +02:00
Martin 475807a1c6 Merge pull request #135 from Fosowl/dev
Fix : #133 : improve ip online check + add tests
2025-04-26 10:49:02 +02:00
martin legrand e06acd65a6 fix : http added to url unnecessary 2025-04-26 10:42:29 +02:00
martin legrand 893f9ec2d8 fix: server_fn 2025-04-26 10:29:56 +02:00
martin legrand 1274a0c646 fix: server_fn 2025-04-26 10:29:36 +02:00
martin legrand e4ae8162a0 add test for ip_online check 2025-04-26 10:27:17 +02:00
martin legrand dce9074969 fix : is_ip_online function 2025-04-26 10:06:20 +02:00
martin legrand b7da34ff93 install readline on windows 2025-04-26 10:01:03 +02:00
martin legrand c360240259 fix : #133 2025-04-26 09:56:14 +02:00
Martin e68dc2212c Merge pull request #132 from Fosowl/dev
Planner agent improvement + Frontend fix
2025-04-25 22:12:05 +02:00
martin legrand e63d772959 readme update 2025-04-25 22:07:41 +02:00
martin legrand 45700d77ab fix : was showing code after execution 2025-04-25 21:54:36 +02:00
martin legrand f09cb8a7b5 fix : block not display on front with planner 2025-04-25 21:35:31 +02:00
martin legrand 49a36de149 upd readmeme 2025-04-25 21:17:17 +02:00
martin legrand 309a481a69 feat : enhance planner 2025-04-25 21:15:49 +02:00
martin legrand a11445e7c0 readme 2025-04-25 20:52:59 +02:00
martin legrand d5c431a609 update readme 2025-04-25 20:50:31 +02:00
martin legrand cfe19e637f feat : planner improvement, google provider 2025-04-25 20:13:25 +02:00
Martin cea68fed86 Merge pull request #131 from Fosowl/dev
Feat : MCP finder tool
2025-04-24 21:15:49 +02:00
martin legrand 273f4bd858 Feat : MCP finder tool 2025-04-24 21:13:29 +02:00
Martin 55d5ff39ff Merge pull request #130 from Fosowl/dev
Planner agent improvement, Browser agent stuck prevention, frontend change, readme update + fix
2025-04-24 13:53:54 +02:00
martin legrand 6049db1f24 fix : wrong value 2025-04-24 13:33:36 +02:00
martin legrand b479dd0b2f rm debug print 2025-04-24 13:24:56 +02:00
martin legrand 8b199869c7 fix : planner agent bug 2025-04-24 13:23:17 +02:00
martin legrand b9a954a058 upd readme 2025-04-24 12:24:28 +02:00
martin legrand 82aecd0aae fix : blocks not appearing on front for planner agent 2025-04-24 12:22:52 +02:00
martin legrand 812af254b5 upd readme 2025-04-24 10:45:45 +02:00
martin legrand a05596c416 upd readme 2025-04-24 10:41:46 +02:00
martin legrand cb251f93b5 upd readme 2025-04-24 10:41:00 +02:00
martin legrand 317f1521eb update readme 2025-04-24 10:36:47 +02:00
martin legrand 9c9824c05e update readme 2025-04-24 10:35:39 +02:00
martin legrand 564a09c96d feat : planner adapt to task failure + temporary remove frontend task panel 2025-04-23 15:51:47 +02:00
Martin 7fb5fa75ee Merge pull request #128 from Fosowl/dev
Integrate new frontend + random user agent
2025-04-22 20:10:21 +02:00
martin legrand d01ae7217f feat : random ua + more coherent browser signature 2025-04-22 14:44:34 +02:00
Martin 2ff93cef3c Merge pull request #127 from Saminu/Simba
refactor: update styles and structure for improved UI; add color cons…
2025-04-21 19:19:22 +02:00
Simba f7f33d0c79 refactor: update styles and structure for improved UI; add color constants 2025-04-21 18:45:02 +02:00
Martin 50142b48f8 Merge pull request #126 from Fosowl/dev
Update readme and slight frontend fix attempt
2025-04-21 15:08:56 +02:00
martin legrand 1b17b95e8c feat : slight fix attempt for frontend 2025-04-21 15:06:21 +02:00
martin legrand 4de527aa42 update discord link + less strict url format check 2025-04-21 12:10:13 +02:00
Martin de22f7218a Merge pull request #124 from Fosowl/dev
Add no cache dir to installation script and ensure wheel is up to date
2025-04-19 09:56:39 +02:00
martin legrand fdb4c887c3 fix : install script 2025-04-19 09:52:53 +02:00
Martin c6fe2865b6 Merge pull request #123 from Fosowl/dev
update ja readme according to change (auto-translate)
2025-04-18 19:18:19 +02:00
martin legrand 5ea0b4a895 update ja readme according to change (auto-translate) 2025-04-18 19:17:23 +02:00
Martin 523e7f8271 Merge pull request #122 from Fosowl/dev
Huge refactor and Frontend interface integration
2025-04-18 19:05:22 +02:00
Martin c93ff60900 Merge branch 'main' into dev 2025-04-18 19:05:06 +02:00
martin legrand 26e5159c1d fix : use effect 2025-04-18 18:47:41 +02:00
martin legrand 0f09ef92dd refactor : message for status 2025-04-18 18:31:11 +02:00
martin legrand 5ac7df1854 fix : browser stuck due to history problem 2025-04-18 18:05:54 +02:00
martin legrand 7f3682e884 fix : message not displayed bug 2025-04-18 17:54:47 +02:00
martin legrand 600bff8da4 fix : error 2025-04-18 17:38:51 +02:00
martin legrand c9f6d76d30 fix : status display on frontend 2025-04-18 17:18:11 +02:00
martin legrand c030b55521 fix : web front bugs 2025-04-18 16:29:59 +02:00
martin legrand 83c595144b feat : frontend message streaming 2025-04-18 15:42:53 +02:00
martin legrand 3a9514629a upd all readme 2025-04-18 10:23:39 +02:00
martin legrand ae8ff0640b upd zh readme 2025-04-17 20:44:53 +02:00
martin legrand b883b003be upd zh readme 2025-04-17 20:41:50 +02:00
martin legrand 89f91f7831 upd readme 2025-04-17 20:29:00 +02:00
martin legrand a4f56d582b fix : frontend route 2025-04-17 19:48:12 +02:00
martin legrand 56d5ec2d37 readme update 2025-04-17 19:48:03 +02:00
martin legrand ad9ca5e7cb commented out backend service until solution found for chrome in docker problem 2025-04-17 18:59:13 +02:00
martin legrand 36b26b43c9 fix deployement script 2025-04-17 12:05:23 +02:00
martin legrand 3d1f42351f upd readme 2025-04-16 22:36:11 +02:00
martin legrand 1a2b790f2b rename app to api.py 2025-04-16 22:33:50 +02:00
martin legrand 81b772df9a upd readme 2025-04-16 22:20:30 +02:00
martin legrand 7c4f283a05 update readme & config 2025-04-16 21:33:49 +02:00
martin legrand 66c460adad update readme & config 2025-04-16 21:21:19 +02:00
martin legrand efa1bbaecb update: readme 2025-04-16 21:14:30 +02:00
martin legrand ad21f66a44 refactor : frontend 2025-04-16 21:00:08 +02:00
martin legrand d5a07c11db fix : .md img path 2025-04-16 20:45:39 +02:00
martin legrand f4b0af1eb1 move technical images from media to docs 2025-04-16 20:44:42 +02:00
martin legrand 79400b8f52 refactor: move some .md to docs/ 2025-04-16 20:40:05 +02:00
martin legrand e1706d97f2 refactor: project folder names 2025-04-16 20:35:33 +02:00
martin legrand 023c183e85 refactor: rename server to llm_server for clarity 2025-04-16 20:29:46 +02:00
martin legrand 77d6e23c45 refactor : frontend line 2025-04-16 15:14:47 +02:00
martin legrand ca1f12b91b refactor : rename main.py to cli.py 2025-04-16 15:11:41 +02:00
martin legrand f2eda0e7d7 feat : update .cmd services & requirements.txt 2025-04-16 14:37:45 +02:00
martin legrand 153bd21910 feat : custom chhrome path save to env 2025-04-16 14:10:48 +02:00
martin legrand a3ca718131 feat : improve chrome path check + no query refusal on complex task 2025-04-16 13:59:11 +02:00
martin legrand 4342677344 fix : update screenshot on front kinda work 2025-04-16 13:57:53 +02:00
martin legrand 26421190b1 fix : change browser waiting check 2025-04-16 10:08:03 +02:00
martin legrand 906dc18060 fix : start_service.sh & compose 2025-04-16 08:43:32 +02:00
martin legrand 2cb7ac34ce add tools log 2025-04-15 21:39:24 +02:00
martin legrand 6d1edf9184 fix :__main__ not working within interpreter 2025-04-15 20:56:58 +02:00
martin legrand e1d55649d5 fix : invalid usage of memory_clear_section 2025-04-15 20:41:23 +02:00
Martin 6a7a3d623e Merge pull request #121 from Fosowl/Fosowl-patch-1
Update README.md
2025-04-15 19:31:29 +02:00
Martin 83e93dcf43 Update README.md 2025-04-15 19:30:45 +02:00
martin legrand a32cf60958 feat : small frontend improvement & planner auto fix 2025-04-15 16:31:53 +02:00
martin legrand 14f42b638d ci : full deploy with searxng, usgi, frontend (in progress) 2025-04-15 11:04:41 +02:00
martin legrand 89c3ecea68 ci: full docker compose deploy 2025-04-14 21:51:46 +02:00
martin legrand c65e6321f5 fix: error on browser view 2025-04-14 20:28:58 +02:00
martin legrand d1954ff326 First front & backend integration 2025-04-14 20:08:53 +02:00
martin legrand 592c7e6915 refactor : pre-backend implementation 2025-04-14 16:55:15 +02:00
martin legrand ecbdcaa57e upd readme 2025-04-14 14:33:04 +02:00
Martin aad1b426f0 Merge pull request #120 from Fosowl/dev
readme update + avoid asking for clarification multiple times
2025-04-14 14:31:32 +02:00
martin legrand ce81133560 upd readme 2025-04-14 11:58:52 +02:00
martin legrand 454e68033c Fix : prevent asking for clarification multiple time + readme update 2025-04-14 11:58:02 +02:00
martin legrand 8da3d2b3f8 refactor : test code in llmprovider 2025-04-13 20:57:39 +02:00
Martin 59795c3dc3 Merge pull request #118 from Fosowl/dev
Dev
2025-04-13 20:38:26 +02:00
Martin 6adc04200e Update README.md 2025-04-13 20:37:56 +02:00
Martin f3c71d6f19 Update README.md 2025-04-13 20:37:25 +02:00
Martin 8cedd9123b Merge pull request #117 from Fosowl/dev
Update README.md video
2025-04-13 20:23:53 +02:00
Martin 7313294c69 Update README.md 2025-04-13 19:29:42 +02:00
Martin 424c5c4f7b Merge pull request #116 from Fosowl/dev
Better web form handling
2025-04-13 17:30:00 +02:00
martin legrand e0f0c5c7f6 feat : better web form handling 2025-04-13 17:23:00 +02:00
Martin 2eb97e6724 Merge pull request #115 from Fosowl/dev
Improve browser note taking and contributing.md
2025-04-12 18:19:06 +02:00
martin legrand 5b491ddbf7 feat: enhance browser agent note taking 2025-04-12 16:40:19 +02:00
martin legrand 164b741d57 refactor: rm debug print 2025-04-12 14:59:45 +02:00
martin legrand dfda888e57 upd contributing.md 2025-04-12 13:25:07 +02:00
martin legrand a6c4b5ab3d doc image 2025-04-12 11:56:37 +02:00
Martin 488a645cf4 Merge pull request #114 from Fosowl/dev
Refactor self.role for new multilingual router + contributing.md
2025-04-12 11:54:37 +02:00
martin legrand 68bfc0ecef update contributing.md 2025-04-12 11:51:06 +02:00
martin legrand f4feb42dda refactor: self.role for router 2025-04-12 11:50:48 +02:00
Martin 49fab1b488 Merge pull request #113 from Fosowl/dev
Router support any language + Java interpreter with fixed lang keyerror
2025-04-11 14:14:11 +02:00
martin legrand 06e6b2798b fix : lang error 2025-04-11 14:11:09 +02:00
martin legrand 09ce9a882a update fr reademe 2025-04-11 13:45:22 +02:00
martin legrand 2ff7e90cea update readme 2025-04-11 13:00:20 +02:00
martin legrand a9c1f5b790 feat : java interpreter bash handle 2025-04-11 12:59:14 +02:00
martin legrand 9fe561085b feat : add java interpreter tool for code agent 2025-04-11 12:46:12 +02:00
martin legrand 92f9b93353 fix : language_bash_attempt error 2025-04-11 12:44:55 +02:00
martin legrand 4198e932ca feat : support any language set in config 2025-04-11 11:13:07 +02:00
Martin 00d1b01624 Merge pull request #110 from eltociear/add-japanese-readme
docs: add Japanese README
2025-04-11 09:43:54 +02:00
Ikko Eltociear Ashimine 75e417129d docs: add Japanese README
I created Japanese translated README.
2025-04-11 16:13:19 +09:00
Martin 46b5edfd3b Merge pull request #109 from Fosowl/dev
Fix fileFinder read file issue, browser agents prompts, browser stealth mode enhancement
2025-04-10 17:23:11 +02:00
martin legrand e66f535dd3 feat : more router few shots 2025-04-10 16:43:05 +02:00
martin legrand 4d5a532b23 mistalke in prompt 2025-04-10 16:39:50 +02:00
martin legrand 369850b86d fix : major issue with file reading tool, feat : prompt improvement for browser agent 2025-04-10 16:35:07 +02:00
martin legrand 7553d9dbb6 refactor : memory clear section function logic 2025-04-09 19:03:04 +02:00
martin legrand ed2a9cc204 server gpu percentage for vllm 2025-04-08 20:58:32 +02:00
martin legrand 9a1b2b93f6 fix : SessionNotCreatedException caused by data dir conflict 2025-04-08 20:31:07 +02:00
martin legrand 3c66eb646e fix : vllm Nonetype 2025-04-08 19:48:18 +02:00
martin legrand 82cf54706b feat : vllm in server fix 2025-04-08 19:40:02 +02:00
martin legrand 8cfb2d1246 feat : vllm in server 2025-04-08 19:38:06 +02:00
Martin aa9177df0c Merge pull request #106 from Fosowl/dev
Better action management of web browsing agent
2025-04-08 14:18:38 +02:00
martin legrand 864fb36af5 feat : change planner agent prompt 2025-04-08 14:16:59 +02:00
Martin f0aaa06d15 Update README.md 2025-04-08 13:37:25 +02:00
martin legrand 60795111b0 feat: action enum for browser agent 2025-04-08 13:35:21 +02:00
martin legrand 469551c2b5 fix : stuck for and back same webpage link 2025-04-08 10:43:28 +02:00
martin legrand 6eafeb15a4 feat : improve browser agent code structure 2025-04-08 10:34:39 +02:00
Martin d3e95712fd Update README.md 2025-04-07 17:02:00 +02:00
Martin fecc01e230 Merge pull request #103 from Fosowl/dev
readme update & tests add
2025-04-07 16:57:18 +02:00
martin legrand d75735ecb0 readme update & tests add 2025-04-07 16:56:36 +02:00
Martin 70fcb0d70d Merge pull request #102 from Fosowl/dev
current_dir -> work_dir for fileFinder + fix wrong url in dl safetensors script
2025-04-07 15:05:02 +02:00
martin legrand 6eee5cf350 rm debug print 2025-04-07 15:01:17 +02:00
martin legrand 21bf224fef fix: browser bug 2025-04-07 14:55:41 +02:00
Martin 139f8cdc11 Merge pull request #101 from Fosowl/dev
Feat : planner prompt improvement + enhance display + new readme image
2025-04-07 13:51:43 +02:00
martin legrand ff8fdddbdc feat : new readme img 2025-04-07 13:16:26 +02:00
martin legrand 93ebb9468c feat: small show answer display change 2025-04-07 12:03:28 +02:00
martin legrand a1e71fd0ce feat : improve planner agent handling of multifiles project 2025-04-07 12:02:01 +02:00
Martin 208bb5e93d Merge pull request #100 from Fosowl/dev
small fix
2025-04-06 20:04:11 +02:00
martin legrand 416d9d00ad fix: undeclared variable used in return 2025-04-06 20:02:55 +02:00
martin legrand 3550c4a448 fix: undeclared variable used in return 2025-04-06 20:02:21 +02:00
Martin 3af3791f54 Merge pull request #99 from Fosowl/dev
Enhanced web navigation & planner agent + logging system
2025-04-06 20:01:46 +02:00
MartinandCopilot 196841db50 Update sources/agents/browser_agent.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-06 20:00:49 +02:00
martin legrand bb67df8f42 feat : signal handler now agent specific instead of global 2025-04-06 19:46:52 +02:00
martin legrand 26e9dbcd40 feat : slight improvement for planner & web agent 2025-04-06 14:50:19 +02:00
martin legrand 42f9485a39 feat : enhance browser agent + add tests 2025-04-06 12:17:38 +02:00
martin legrand 6fb9ce67c0 feat : better web navigation of web agent 2025-04-05 22:13:29 +02:00
martin legrand 06ddc45955 fix : server cache bug 2025-04-05 16:47:38 +02:00
martin legrand 93c8f0f8e4 fix : server cache bug 2025-04-05 16:45:03 +02:00
martin legrand a667f89c12 fix : server cache 2025-04-05 16:41:24 +02:00
martin legrand 8991aaae8d feat : planner agent improvement 2025-04-05 16:39:16 +02:00
martin legrand 97708c7947 feat : server response cache 2025-04-05 16:36:58 +02:00
martin legrand 688e94d97c feat : html to actual markdown for browser + better logging system 2025-04-05 14:14:23 +02:00
martin legrand a09b6bf8aa feat : logger class for better logging 2025-04-05 12:12:38 +02:00
Martin f2ce720a3d Merge pull request #98 from Fosowl/dev
Fix various bug + handle webpage numerical value + improve prompts.
2025-04-04 15:50:50 +02:00
martin legrand a5c5061a2f feat : prompt change for casual agent 2025-04-04 15:07:43 +02:00
martin legrand 5321dcc3ba fix : exception in browser 2025-04-04 14:15:29 +02:00
martin legrand ac5118c4e3 feat : prompt change 2025-04-04 14:15:01 +02:00
martin legrand a4f28cec5d feat : .voices folder for tts 2025-04-04 12:34:00 +02:00
martin legrand 95f43be2af fix : avoid loading compress of planner agent memory 2025-04-04 11:57:06 +02:00
martin legrand ff9c1576b6 feat : better numerical value handling on webpage 2025-04-04 11:56:11 +02:00
martin legrand 4f7e30b498 feat : slight prompt change 2025-04-04 11:55:11 +02:00
martin legrand d6aba5fd39 feat : dsk_deepseek 2025-04-04 11:54:34 +02:00
martin legrand f70606b5ec feat : improve tts test code at bottom of file & index safety 2025-04-04 11:53:37 +02:00
martin legrand 92e2e8c0d6 fix : memory summarization issue 2025-04-04 11:41:47 +02:00
Martin 23dce5b886 Merge pull request #97 from Fosowl/dev
add CHS readme
2025-04-03 20:59:43 +02:00
martin legrand 80a3391b84 readme fix tab level 2025-04-03 20:58:55 +02:00
martin legrand 8f8c2104a2 update readme 2025-04-03 20:55:44 +02:00
martin legrand 7f4c96371e add simplified chinese readme 2025-04-03 20:53:39 +02:00
Martin 46c3b7c17e Merge pull request #96 from Fosowl/dev
update fr & en readme
2025-04-03 11:26:41 +02:00
martin legrand 319a4389ac update rf & en readme 2025-04-03 11:25:42 +02:00
Martin 32b3908aa3 Merge pull request #95 from Fosowl/dev
Multilingual routing system (english, french, chinese) + Better web agent handling of web form (#94 corrected)
2025-04-02 21:55:11 +02:00
martin legrand f798e4936c update requirement.txt 2025-04-02 21:50:08 +02:00
martin legrand e534faf115 fix : possible bus error 2025-04-02 21:09:22 +02:00
martin legrand a93dbbfb5c readme update 2025-04-02 18:28:32 +02:00
martin legrand f0cca0ed02 readme update 2025-04-02 18:27:49 +02:00
martin legrand 0f7ad9b741 readme update 2025-04-02 18:23:23 +02:00
martin legrand b9fc781f28 readme update 2025-04-02 18:21:13 +02:00
martin legrand c47e921a3b update readme 2025-04-02 18:18:01 +02:00
martin legrand 7890b4b3ca feat : better form handling 2025-04-02 15:43:51 +02:00
martin legrand f69ceb5025 feat : fast browser memory recovery 2025-04-02 13:49:18 +02:00
martin legrand aa75d276dc readme image change 2025-04-02 13:48:28 +02:00
martin legrand ffebcccd32 feat : slight prompt change for coder agent 2025-04-02 13:24:26 +02:00
martin legrand 3b201c82db docs: update readme given router now multilingual 2025-04-02 13:23:55 +02:00
martin legrand 704509560a feat : multilingual agent router 2025-04-02 13:22:32 +02:00
Martin 8c496d2bc2 Merge pull request #93 from Fosowl/dev
readme update
2025-04-01 21:07:17 +02:00
martin legrand 5992fdd659 readme update 2025-04-01 21:06:33 +02:00
Martin d476cf91dc Merge pull request #92 from Fosowl/dev
Improve web form handling & Better prompt for planner agent.
2025-04-01 19:47:25 +02:00
MartinandCopilot 02d28b4322 Update sources/agents/browser_agent.py for duplicate typing
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-01 19:42:44 +02:00
MartinandCopilot 9e47e2bf4f Update sources/llm_provider.py to remove duplicate typing
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-01 19:42:16 +02:00
MartinandCopilot 95f5b9df68 Update sources/speech_to_text.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-01 19:41:59 +02:00
martin legrand 1ffaf4689e rm : tmp file 2025-04-01 19:21:35 +02:00
martin legrand 140f7842cc feat: add config back to default settings 2025-04-01 19:19:10 +02:00
martin legrand b5311b2651 fix : typo in readme fr version 2025-04-01 19:10:57 +02:00
martin legrand e99851fba3 note: commit 56b5db7 was a mistake by agenticseek itself lol 2025-04-01 19:05:47 +02:00
martin legrand 3acbae5ea0 feat : no call to llm on goodbye, prompt adjustement for file agent 2025-04-01 19:00:39 +02:00
martin legrand 56b5db7df3 Initial project setup 2025-04-01 18:49:37 +02:00
martin legrand 698ed78acc feat: better find_and_click_submission function 2025-04-01 15:12:53 +02:00
martin legrand 9c3330b45d add french readme 2025-04-01 14:21:48 +02:00
Martin 9e5b2c5ed7 Merge pull request #91 from steveh8758/main
Mod README
2025-04-01 13:45:46 +02:00
steveh8758 11fa4aed48 Merge branch 'Fosowl:main' into main 2025-04-01 19:43:24 +08:00
steveh8758_lab 919cf1437d Mod README 2025-04-01 19:41:46 +08:00
martin legrand 1b5a55ccf2 feat : cleaner import arrangement 2025-04-01 13:10:06 +02:00
martin legrand b3efd09fb3 fix : browser not handling properly web form 2025-04-01 13:09:16 +02:00
Martin 617927c291 Merge pull request #89 from steveh8758/main
Add Chinese-Traditional README
2025-04-01 12:51:38 +02:00
steveh8758_lab 0ce492d083 Add Chinese-Traditional README 2025-04-01 18:19:54 +08:00
steveh8758 4cf1beb49f Merge branch 'Fosowl:main' into main 2025-04-01 18:16:17 +08:00
Martin c41c259cd6 Merge pull request #88 from Fosowl/dev
Browser stealth mode
2025-03-30 19:06:37 +02:00
martin legrand a3e95abfde update readme 2025-03-30 17:48:43 +02:00
martin legrand 164d2b21e9 update readme 2025-03-30 17:47:04 +02:00
martin legrand b34e343535 fix : possible crash with planner agent if wrong format returned by llm 2025-03-30 17:38:22 +02:00
martin legrand 8ccb6f4d77 fix : issue with browser 2025-03-30 17:22:35 +02:00
martin legrand 36b80dc758 fix duplicate : config.ini 2025-03-30 17:13:23 +02:00
martin legrand 927d09ffb5 feat : new config.ini 2025-03-30 16:15:48 +02:00
martin legrand a5ecd2d389 fix : improve install script 2025-03-30 16:13:44 +02:00
martin legrand 039ea71678 feat: stealth option in config 2025-03-30 16:00:38 +02:00
martin legrand a0b09410b3 feat : nopecha crx 2025-03-30 15:37:06 +02:00
martin legrand 3dbef96cf0 feat : stealth browser with selenium_stealth for captcha 2025-03-30 15:20:43 +02:00
martin legrand 69f276955a fix: ollama server issue 2025-03-30 12:04:06 +02:00
martin legrand e56e5a4b3d fix : fix 2025-03-30 12:02:17 +02:00
martin legrand 6b31516cd9 fix : bug from weird ollama behavior 2025-03-30 12:00:20 +02:00
martin legrand 61d83e6614 fix relative import issue 2025-03-30 11:55:55 +02:00
martin legrand 4d0130c297 feat : loading verbose message 2025-03-30 11:53:25 +02:00
martin legrand 7331cb7cb2 feat : better verbose message 2025-03-30 11:51:41 +02:00
martin legrand 8c431c690e readme update 2025-03-29 21:28:42 +01:00
martin legrand f60406d0f1 script update 2025-03-29 21:27:19 +01:00
Martin 7e18d78805 Merge pull request #87 from Fosowl/dev
Integration of new custom server provider
2025-03-29 20:29:13 +01:00
MartinandCopilot cd1833f3ad Update comment in sources/browser.py by copilot
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-03-29 20:25:52 +01:00
martin legrand 45818b1eba fix : display carriage problem 2025-03-29 20:12:18 +01:00
martin legrand 9561ca95a1 fix : healess browser setting not applied properly 2025-03-29 20:09:44 +01:00
martin legrand 875ab3bd8e feat : increase ctx size 2025-03-29 19:54:45 +01:00
martin legrand 1dd8e0a016 fix : llamacpp handler problem again 2025-03-29 19:47:44 +01:00
martin legrand 5862c98f3e fix : llamacpp handler problem 2025-03-29 19:41:29 +01:00
martin legrand ddb533a255 fix : server model download 2025-03-29 19:27:08 +01:00
martin legrand cc951d4745 feat : remove browser message 2025-03-29 18:48:38 +01:00
martin legrand 557f7aa333 perf: trying to improve perf 2025-03-29 18:20:47 +01:00
martin legrand e0eee90202 fix : server crash with ollama 2025-03-29 18:07:38 +01:00
martin legrand d8ded2d456 fix: animate_thinking bug 2025-03-29 16:13:42 +01:00
martin legrand 862a78276f feat : simpler, better terminal color 2025-03-29 15:53:27 +01:00
martin legrand e69cff0735 fix : pretty_print issue 2025-03-29 14:43:50 +01:00
martin legrand f42a31578e fix : response timeout 2025-03-29 14:30:28 +01:00
martin legrand 90894f806a fix : response timeout 2025-03-29 14:23:53 +01:00
martin legrand 5c9ada9468 fix : bug 2025-03-29 13:55:01 +01:00
martin legrand cf1d3d0ba1 fix : llama_cpp not defined 2025-03-29 13:34:16 +01:00
martin legrand 58d52ad61f fix : server problem with llamacpp 2025-03-29 13:33:25 +01:00
martin legrand 0c3a07f208 fix : server problem with llamacpp 2025-03-29 13:32:46 +01:00
martin legrand 44e0508ae5 fix : server problem with llamacpp 2025-03-29 13:31:13 +01:00
martin legrand 4676b817e9 fix : serverbug 2025-03-29 13:25:26 +01:00
martin legrand 32b17c3373 feat : better logging 2025-03-29 13:17:01 +01:00
martin legrand 7e95498f7a feat : better logging 2025-03-29 13:14:37 +01:00
martin legrand 4712d39427 feat : better server log 2025-03-29 12:52:33 +01:00
martin legrand 4c87353db4 readme update for server install instruction 2025-03-29 12:40:50 +01:00
martin legrand d1b20a1446 fix : server error 2025-03-29 12:34:51 +01:00
martin legrand 18f23db0fa fix : none generator error 2025-03-29 12:29:38 +01:00
martin legrand 8106cff45f fix : jsonify problem in server 2025-03-29 12:26:58 +01:00
martin legrand 75ac1631c4 fix : jsonify problem in server 2025-03-29 12:24:39 +01:00
martin legrand 021ef0cdc1 feat : logging message for server 2025-03-29 12:21:40 +01:00
martin legrand c995d2a47c fix app.py problem for server 2025-03-29 12:13:03 +01:00
martin legrand de76fe14ea feat : selective import 2025-03-29 12:10:16 +01:00
martin legrand ca50b1f2d0 fix : server problem 2025-03-29 11:52:17 +01:00
martin legrand a4cfa9c651 feat : better server provider 2025-03-29 11:46:22 +01:00
Martin 430d032095 Merge pull request #86 from Fosowl/dev
fix : execution problem when line start with block tag + dont load tts if disabled
2025-03-28 22:17:40 +01:00
martin legrand 0bf813e865 fix : execution problem when line start with block tag + dont load tts if disabled 2025-03-28 18:51:03 +01:00
Martin a65f54e9a1 Merge pull request #85 from Fosowl/dev
better readme image
2025-03-28 17:55:20 +01:00
martin legrand 0c7ce90980 update readme 2025-03-28 17:54:30 +01:00
martin legrand 4aba1bc7cb demo image for readme 2025-03-28 17:52:48 +01:00
martin legrand cf1ef1c819 rm DS_store file 2025-03-28 16:29:56 +01:00
Martin 855e376610 Merge pull request #84 from Fosowl/dev
fix readme image
2025-03-28 16:28:15 +01:00
martin legrand c6eeabce62 fix readme image 2025-03-28 16:27:37 +01:00
Martin 5e7b1ff0ba Merge pull request #83 from Fosowl/dev
Fix display & router problem + Feat : memory compression on session loading + personality customization + doc image
2025-03-28 16:23:37 +01:00
martin legrand 2b512b1315 change unsafe cmd list 2025-03-28 16:22:04 +01:00
martin legrand dae2c224e5 fix: memory compression on session loading 2025-03-28 15:41:54 +01:00
martin legrand fcda0abc21 change file agent prompt 2025-03-28 15:06:41 +01:00
martin legrand c862d496e3 feat : fix displaying problem + memory compression on loading + personality prompt + technical image 2025-03-28 14:43:05 +01:00
Martin 7968f83bf8 Merge pull request #81 from Fosowl/dev
readme udpate, changed deepseek-api to just deepseek for deepseek api provider
2025-03-27 21:11:43 +01:00
martin legrand 8cba1bad43 update readme 2025-03-27 21:06:33 +01:00
martin legrand bc6365567f fix : deepseek api not in example 2025-03-27 19:08:27 +01:00
Martin 6c4e8adda1 Merge pull request #80 from Fosowl/dev
udpate readme
2025-03-27 19:02:06 +01:00
martin legrand c22ec9b074 udpate readme 2025-03-27 19:01:18 +01:00
Martin 3e753bcf97 Merge pull request #79 from Fosowl/dev
udpate readme
2025-03-27 18:59:53 +01:00
martin legrand 6ba95de6e6 udpate readme 2025-03-27 18:58:40 +01:00
Martin 064d41588c Merge pull request #78 from Fosowl/dev
feat : lm-studio integration
2025-03-27 18:39:39 +01:00
martin legrand 582462a73f feat : lm-studio integration 2025-03-27 18:35:07 +01:00
Martin f58e7f04f1 Merge pull request #77 from Fosowl/dev
Local openai based api support + readme update + fix crash&bug
2025-03-27 12:58:08 +01:00
martin legrand bd951e19d3 docs : readme image 2025-03-27 12:52:20 +01:00
martin legrand 91e99a2dbf update readme.md 2025-03-27 12:49:26 +01:00
martin legrand a7d2beabe0 docs : readme image 2025-03-27 12:46:47 +01:00
martin legrand 2f78d033ab feat : browser agent knowledge of current note for navigation reasoning 2025-03-27 12:30:07 +01:00
martin legrand cce74b29ad fix : planner agent crash 2025-03-27 12:19:54 +01:00
martin legrand aa1c0a24e2 Fix : crash due to driver closing in multi agent web search 2025-03-27 12:16:51 +01:00
martin legrand cf4d9b63c7 rm debug log 2025-03-27 11:59:10 +01:00
martin legrand f0802c3035 typo in readme 2025-03-27 11:44:59 +01:00
martin legrand 86da6acf3f feat : support for local openai based api 2025-03-27 11:42:31 +01:00
martin legrand 697bc882c7 fix : memory recovery bug 2025-03-27 10:22:48 +01:00
steveh8758 8a0ffc940e Merge branch 'Fosowl:main' into main 2025-03-27 13:06:46 +08:00
Martin 63e947bf84 Merge pull request #76 from Fosowl/dev
Integration of better router + Integration of planner agent
2025-03-27 00:07:23 +01:00
martin legrand 24329aa3d2 change browser settings 2025-03-26 23:51:54 +01:00
martin legrand 58bdaca252 change config.ini 2025-03-26 23:49:39 +01:00
martin legrand 6249049bcc headless option in config 2025-03-26 23:48:10 +01:00
martin legrand 70e89d9203 headless option in config 2025-03-26 23:47:44 +01:00
martin legrand 39f053eee4 improved linux_install.sh script 2025-03-26 23:46:14 +01:00
martin legrand 4cfcb28c60 readme update 2025-03-26 23:39:10 +01:00
martin legrand 1027a2a77b fix : planner not passing info properly between agents 2025-03-26 20:51:31 +01:00
martin legrand 5dd3ffd9ef readme update 2025-03-26 15:47:28 +01:00
martin legrand 2aa31ac911 readme update 2025-03-26 15:43:24 +01:00
martin legrand 3d49e0aabe feat : media image + fix: router bug 2025-03-26 15:28:10 +01:00
martin legrand 8c425f62b6 fix : browser duplication, isolate driver creation 2025-03-26 14:17:52 +01:00
martin legrand 9080697dc0 feat : re-integrated and improved planner agent 2025-03-26 13:21:10 +01:00
martin legrand 279bdf8c7e rm : useless js function 2025-03-26 12:23:12 +01:00
martin legrand 7d67ae2562 feat : file agent imrprovement 2025-03-26 12:21:03 +01:00
martin legrand 8922350379 feat : file agent improved 2025-03-26 12:06:27 +01:00
martin legrand df922b18a7 fix : wrong condition 2025-03-26 11:09:05 +01:00
martin legrand 5d08565ff1 fix : bug 2025-03-26 11:06:03 +01:00
martin legrand 757a9b1e3e feat : task complexity routing 2025-03-26 10:54:25 +01:00
martin legrand 32bc096d9a feat : better ensemble logic for router 2025-03-26 09:58:27 +01:00
steveh8758 5b52dcc7fe Merge branch 'Fosowl:main' into main 2025-03-26 07:03:25 +08:00
martin legrand d871c378fe feat : better routing system 2025-03-25 15:44:23 +01:00
martin legrand 68bc60f6f4 Fix : installation script for windows 2025-03-25 13:04:01 +01:00
Martin 47a3e71b01 Merge pull request #75 from Fosowl/mow-branch
start_services for windows
2025-03-24 22:33:03 +01:00
martin legrand dffd8b5299 yaml: remove --fail 2025-03-24 22:20:43 +01:00
steveh8758 85f8dcef98 Merge branch 'Fosowl:main' into main 2025-03-25 05:17:31 +08:00
steveh8758 d3884c6eca Merge pull request #72 from Fosowl/dev
Ability to handle web form, Refactor some code, fix server script problem, fix save / load session problem
2025-03-25 05:17:02 +08:00
martin legrand af168d2c57 feat : zero shot router for other lang 2025-03-24 20:22:30 +01:00
martin legrand a289ddf1fd Feat: prompt change for casual agent 2025-03-24 15:56:40 +01:00
martin legrand 323783b89e Feat : improve prompt, add agent verbose option 2025-03-24 14:41:24 +01:00
martin legrand d423c08440 feat : tests for browser 2025-03-24 13:35:37 +01:00
martin legrand 38fe983010 Feat : handle recaptcha 2025-03-24 13:09:36 +01:00
martin legrand 1b32dff6a4 Add precommit hook 2025-03-24 12:58:19 +01:00
martin legrand 189fb0d767 Fix: ask for value with input 2025-03-24 11:45:04 +01:00
martin legrand 037995ab59 captcha testing 2025-03-24 11:31:00 +01:00
martin legrand 8dde9f19a4 fix: server script 2025-03-24 10:41:43 +01:00
martin legrand 8c77f3eddb refactor: remove debug print 2025-03-23 21:24:05 +01:00
martin legrand e74bbe4044 minor fixes 2025-03-23 21:08:34 +01:00
martin legrand 9448ac1012 Fix: server script 2025-03-23 21:07:44 +01:00
martin legrand 8b5bb28c94 fix : various bugs & improve memory system 2025-03-23 17:25:49 +01:00
martin legrand caf1b5e9a9 Refactor : browser class & browsing agent can now login 2025-03-23 16:05:07 +01:00
martin legrand fa7d586a97 Feat : browser login form detecting and fill, fix: memory saving problems 2025-03-23 11:11:38 +01:00
137 changed files with 36404 additions and 1670 deletions
+19
View File
@@ -0,0 +1,19 @@
# Python cache files
__pycache__/
*.py[cod]
# Virtual environments
venv/
.venv/
# Environment variables (secrets)
.env
# Git metadata
.git/
# macOS Finder files
.DS_Store
# Log files
*.log
+3 -1
View File
@@ -1,2 +1,4 @@
SEARXNG_BASE_URL="http://127.0.0.1:8080" SEARXNG_BASE_URL="http://127.0.0.1:8080"
OPENAI_API_KEY='dont share this, not needed for local providers' OPENAI_API_KEY='xxxxx'
DEEPSEEK_API_KEY='xxxxx'
OPENROUTER_API_KEY='xxxxx'
+4
View File
@@ -0,0 +1,4 @@
# These are supported funding model platforms
github: [Fosowl ]# Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+27 -1
View File
@@ -1,11 +1,37 @@
*.wav *.wav
config.ini *.DS_Store
*.log
*.tmp
*.safetensors
*.egg-info *.egg-info
cookies.json
test_agent.py
config.ini
.voices/
experimental/ experimental/
chrome_bundle/
.logs/
.screenshots/*.png
.screenshots/*.jpg
conversations/ conversations/
agentic_env/* agentic_env/*
agentic_seek_env/*
.env .env
*/.env */.env
dsk/
### react ###
.DS_*
*.log
logs
**/*.backup.*
**/*.back.*
node_modules
bower_components
*.sublime*
psd
thumb
sketch
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
+9
View File
@@ -0,0 +1,9 @@
repos:
- repo: local
hooks:
- id: trufflehog
name: TruffleHog
description: Detect secrets in your data.
entry: bash -c 'trufflehog git file://. --since-commit HEAD --results=verified,unknown --no-update'
language: system
stages: ["commit", "push"]
-92
View File
@@ -1,92 +0,0 @@
# Contributors guide
## Prerequisites
- Python 3.8 or higher
- Ollama installed (for local model execution)
- Basic familiarity with Python and AI models
## Contribution Guidelines
We welcome contributions in the following areas:
- Code Improvements: Optimize existing code, fix bugs, or add new features.
- Documentation: Improve the README, write tutorials, or add inline comments.
- Testing: Write unit tests, integration tests, or help with debugging.
- New Features: Implement new tools, agents, or integrations.
## Steps to Contribute
Fork the project to your GitHub account.
Create a Branch:
```bash
git checkout -b feature/your-feature-name
```
Make Your Changes.
Write your code, add documentation, or fix bugs.
Test Your Changes.
Ensure your changes work as expected and do not break existing functionality.
Push your changes to your fork and submit a pull request to the main branch of this repository. Provide a clear description of your changes and reference any related issues.
## Coding Philosophy
1. **Privacy First, Always Local**
- All core functionality must be able to run 100% locally
- Cloud services should only be optional alternatives, clearly defined with a warning message.
- User data privacy is non-negotiable
2. **Agent-Based Architecture**
- Each agent should have a clear, single responsibility
- Agents should be modular and independently testable
- New agents should solve specific use cases
3. **Tool-Based Extensibility**
- Tools should be self-contained and follow the Tools base class
- Each tool should do one thing well
- Tools should provide clear feedback on success/failure
4. **User Experience**
- Provide meaningful feedback for all operations
- Support multiple languages (chinese, french, english for now)
- Text to speech with short response.
- Keep responses concise
5. **Code Quality**
- Write clear, self-documenting code
- Include type hints and docstrings
- Follow existing patterns in the codebase
- Add a if __name__ == "__main__" at the bottom of each class file for individual testing.
- Ideally had automated tests.
6. **Error Handling**
- Fail gracefully with meaningful messages
- Include recovery mechanisms where possible
- Log errors appropriately without exposing sensitive data
## Areas Needing Help
Here are some high-priority tasks and areas where we need contributions:
- Web Browsing: Improve the autonomous web browsing capabilities for the assistant.
- Graphical interface, a web graphical interface. (please ask first)
- Multi-Agent System: Enhance the planner agent for divide and conqueer for task (please ask first).
- New Tools: Add support for additional programming languages or APIs.
- Multi-language support for Text to speech & speech to text (english, chinese, spanish first)
- Testing: Write comprehensive tests for existing features.
- Better readme image: make a better readme image (robot whale that use tools. Ghibli or anime style, inspiration could be https://sakana.ai/assets/ai-scientist/cover.jpeg)
If you're unsure where to start, feel free to reach out by opening an issue or joining our community discussions.
## Code of Conduct
See CODE_OF_CONDUCT.md
**Thank You!**
-26
View File
@@ -1,26 +0,0 @@
# Use official Python 3.11 image as the base
FROM python:3.11
# Set working directory
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
gcc \
g++ \
gfortran \
libportaudio2 \
portaudio19-dev \
ffmpeg \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
chromium \
chromium-driver \
&& rm -rf /var/lib/apt/lists/*
RUN pip cache purge
COPY . .
RUN BLIS_ARCH=generic pip install --no-cache-dir -r requirements.txt
+47
View File
@@ -0,0 +1,47 @@
FROM ubuntu:22.04
# Warning: doesn't work yet, backend is run on host machine for now
WORKDIR /app
RUN apt-get update -qq -y && \
apt-get install -y \
gcc \
g++ \
gfortran \
libportaudio2 \
portaudio19-dev \
ffmpeg \
libavcodec-dev \
libavformat-dev \
libavutil-dev \
gnupg2 \
wget \
unzip \
python3 \
python3-pip \
libasound2 \
libatk-bridge2.0-0 \
libgtk-4-1 \
libnss3 \
xdg-utils \
wget && \
RUN chmod +x /opt/chrome/chrome
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application code
COPY api.py .
COPY sources/ ./sources/
COPY prompts/ ./prompts/
COPY crx/ crx/
COPY llm_router/ llm_router/
COPY .env .
COPY config.ini .
# Expose port
EXPOSE 8000
# Run the application
CMD ["python3", "api.py"]
+335 -165
View File
@@ -1,57 +1,46 @@
# AgenticSeek: Private, Local Manus Alternative.
# AgenticSeek: Manus-like AI powered by Deepseek R1 Agents. <p align="center">
<img align="center" src="./media/agentic_seek_logo.png" width="300" height="300" alt="Agentic Seek Logo">
<p>
English | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Français](./README_FR.md) | [日本語](./README_JP.md)
**A fully local alternative to Manus AI**, a voice-enabled AI assistant that codes, explores your filesystem, browse the web and correct it's mistakes all without sending a byte of data to the cloud. Built with reasoning models like DeepSeek R1, this autonomous agent runs entirely on your hardware, keeping your data private. *A **100% local alternative to Manus AI**, this voice-enabled AI assistant autonomously browses the web, writes code, and plans tasks while keeping all data on your device. Tailored for local reasoning models, it runs entirely on your hardware, ensuring complete privacy and zero cloud dependency.*
[![Visit AgenticSeek](https://img.shields.io/static/v1?label=Website&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![License](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/4Ub2D6Fj) [![Visit AgenticSeek](https://img.shields.io/static/v1?label=Website&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![License](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/8hGDaME3TC) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/fosowl.svg?style=social&label=Update%20%40Fosowl)](https://x.com/Martin993886460) [![GitHub stars](https://img.shields.io/github/stars/Fosowl/agenticSeek?style=social)](https://github.com/Fosowl/agenticSeek/stargazers)
> 🛠️ **Work in Progress** Looking for contributors! ### Why AgenticSeek ?
![alt text](./media/whale_readme.jpg) * 🔒 Fully Local & Private - Everything runs on your machine — no cloud, no data sharing. Your files, conversations, and searches stay private.
> *Do a web search to find tech startup in Japan working on cutting edge AI research* * 🌐 Smart Web Browsing - AgenticSeek can browse the internet by itself — search, read, extract info, fill web form — all hands-free.
> *Make a snake game in Python* * 💻 Autonomous Coding Assistant - Need code? It can write, debug, and run programs in Python, C, Go, Java, and more — all without supervision.
> *Scan my network with nmap, find out who is connected?* * 🧠 Smart Agent Selection - You ask, it figures out the best agent for the job automatically. Like having a team of experts ready to help.
> *Hey can you find where is contract.pdf*? * 📋 Plans & Executes Complex Tasks - From trip planning to complex projects — it can split big tasks into steps and get things done using multiple AI agents.
## Features: * 🎙️ Voice-Enabled - Clean, fast, futuristic voice and speech to text allowing you to talk to it like it's your personal AI from a sci-fi movie
- **100% Local**: No cloud, runs on your hardware. Your data stays yours. ### **Demo**
- **Voice interaction**: Voice-enabled natural interaction. > *Can you search for the agenticSeek project, learn what skills are required, then open the CV_candidates.zip and then tell me which match best the project*
- **Filesystem interaction**: Use bash to navigate and manipulate your files effortlessly. https://github.com/user-attachments/assets/b8ca60e9-7b3b-4533-840e-08f9ac426316
- **Code what you ask**: Can write, debug, and run code in Python, C, Golang and more languages on the way. Disclaimer: This demo, including all the files that appear (e.g: CV_candidates.zip), are entirely fictional. We are not a corporation, we seek open-source contributors not candidates.
- **Autonomous**: If a command flops or code breaks, it retries and fixes it by itself. > 🛠⚠️ **Active Work in Progress** Please note that Code/Bash is not dockerized yet but will be soon (see docker_deployement branch) - Do not deploy over network or production.
- **Agent routing**: Automatically picks the right agent for the job. > 🙏 This project started as a side-project with zero roadmap and zero funding. It's grown way beyond what I expected by ending in GitHub Trending. Contributions, feedback, and patience are deeply appreciated.
- **Divide and Conquer**: For big tasks, spins up multiple agents to plan and execute. ## Installation
- **Tool-Equipped**: From basic search to flight APIs and file exploration, every agent has it's own tools. Make sure you have chrome driver, docker and python3.10 installed.
- **Memory**: Remembers whats useful, your preferences and past sessions conversation. We highly advice you use exactly python3.10 for the setup. Dependencies error might happen otherwise.
- **Web Browsing**: Autonomous web navigation.
### Searching the web with agenticSeek :
![alt text](./media/exemples/search_startup.png)
*See media/examples for other use case screenshots.*
---
## **Installation**
Make sure you have chrome driver, docker and python3.10 (or newer) installed.
For issues related to chrome driver, see the **Chromedriver** section. For issues related to chrome driver, see the **Chromedriver** section.
@@ -73,126 +62,234 @@ source agentic_seek_env/bin/activate
### 3️⃣ **Install package** ### 3️⃣ **Install package**
**Automatic Installation:** Ensure Python, Docker and docker compose, and Google chrome are installed.
We recommand Python 3.10.0.
**Automatic Installation (Recommanded):**
For Linux/Macos:
```sh ```sh
./install.sh ./install.sh
``` ```
For windows:
```sh
./install.bat
```
**Manually:** **Manually:**
```sh **Note: For any OS, ensure the ChromeDriver you install matches your installed Chrome version. Run `google-chrome --version`. See known issues if you have chrome >135**
pip3 install -r requirements.txt
# or
python3 setup.py install
```
- *Linux*:
## Run locally on your machine Update Package List: `sudo apt update`
**We recommend using at least Deepseek 14B, smaller models struggle with tool use and forget quickly the context.** Install Dependencies: `sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
### 1️⃣ **Download Models** Install ChromeDriver matching your Chrome browser version:
`sudo apt install -y chromium-chromedriver`
Make sure you have [Ollama](https://ollama.com/) installed. Install requirements: `pip3 install -r requirements.txt`
Download the `deepseek-r1:14b` model from [DeepSeek](https://deepseek.com/models) - *Macos*:
```sh Update brew : `brew update`
ollama pull deepseek-r1:14b
```
### 2 **Run the Assistant (Ollama)** Install chromedriver : `brew install --cask chromedriver`
Install portaudio: `brew install portaudio`
Upgrade pip : `python3 -m pip install --upgrade pip`
Upgrade wheel : : `pip3 install --upgrade setuptools wheel`
Install requirements: `pip3 install -r requirements.txt`
- *Windows*:
Install pyreadline3 `pip install pyreadline3`
Install portaudio manually (e.g., via vcpkg or prebuilt binaries) and then run: `pip install pyaudio`
Download and install chromedriver manually from: https://sites.google.com/chromium.org/driver/getting-started
Place chromedriver in a directory included in your PATH.
Install requirements: `pip3 install -r requirements.txt`
---
## Setup for running LLM locally on your machine
**Hardware Requirements:**
To run LLMs locally, you'll need sufficient hardware. At a minimum, a GPU capable of running Qwen/Deepseek 14B is required. See the FAQ for detailed model/performance recommendations.
**Setup your local provider**
Start your local provider, for example with ollama:
Start the ollama server
```sh ```sh
ollama serve ollama serve
``` ```
Change the config.ini file to set the provider_name to `ollama` and provider_model to `deepseek-r1:14b` See below for a list of local supported provider.
NOTE: `deepseek-r1:14b`is an example, use a bigger model if your hardware allow it. **Update the config.ini**
Change the config.ini file to set the provider_name to a supported provider and provider_model to a LLM supported by your provider. We recommand reasoning model such as *Qwen* or *Deepseek*.
See the **FAQ** at the end of the README for required hardware.
```sh ```sh
[MAIN] [MAIN]
is_local = True is_local = True # Whenever you are running locally or with remote provider.
provider_name = ollama provider_name = ollama # or lm-studio, openai, etc..
provider_model = deepseek-r1:14b provider_model = deepseek-r1:14b # choose a model that fit your hardware
provider_server_address = 127.0.0.1:11434 provider_server_address = 127.0.0.1:11434
agent_name = Jarvis # name of your AI
recover_last_session = True # whenever to recover the previous session
save_session = True # whenever to remember the current session
speak = True # text to speech
listen = False # Speech to text, only for CLI
work_dir = /Users/mlg/Documents/workspace # The workspace for AgenticSeek.
jarvis_personality = False # Whenever to use a more "Jarvis" like personality (experimental)
languages = en zh # The list of languages, Text to speech will default to the first language on the list
[BROWSER]
headless_browser = True # Whenever to use headless browser, recommanded only if you use web interface.
stealth_mode = True # Use undetected selenium to reduce browser detection
``` ```
start all services : Warning: Do *NOT* set provider_name to `openai` if using LM-studio for running LLMs. Set it to `lm-studio`.
```sh Note: Some provider (eg: lm-studio) require you to have `http://` in front of the IP. For example `http://127.0.0.1:1234`
sudo ./start_services.sh
```
Run the assistant: **List of local providers**
```sh | Provider | Local? | Description |
python3 main.py |-----------|--------|-----------------------------------------------------------|
``` | ollama | Yes | Run LLMs locally with ease using ollama as a LLM provider |
| lm-studio | Yes | Run LLM locally with LM studio (set `provider_name` to `lm-studio`)|
| openai | Yes | Use openai compatible API (eg: llama.cpp server) |
*See the **Usage** section if you don't understand how to use it* Next step: [Start services and run AgenticSeek](#Start-services-and-Run)
*See the **Known issues** section if you are having issues* *See the **Known issues** section if you are having issues*
*See the **Run with an API** section if your hardware can't run deepseek locally* *See the **Run with an API** section if your hardware can't run deepseek locally*
*See the **Config** section for detailled config file explanation.*
---
## Setup to run with an API
Set the desired provider in the `config.ini`. See below for a list of API providers.
```sh
[MAIN]
is_local = False
provider_name = google
provider_model = gemini-2.0-flash
provider_server_address = 127.0.0.1:5000 # doesn't matter
```
Warning: Make sure there is not trailing space in the config.
Export your API key: `export <<PROVIDER>>_API_KEY="xxx"`
Example: export `TOGETHER_API_KEY="xxxxx"`
**List of API providers**
| Provider | Local? | Description |
|-----------|--------|-----------------------------------------------------------|
| openai | Depends | Use ChatGPT API |
| deepseek | No | Deepseek API (non-private) |
| huggingface| No | Hugging-Face API (non-private) |
| togetherAI | No | Use together AI API (non-private) |
| google | No | Use google gemini API (non-private) |
*We advice against using gpt-4o or other closedAI models*, performance are poor for web browsing and task planning.
Please also note that coding/bash might fail with gemini, it seem to ignore our prompt for format to respect, which are optimized for deepseek r1.
Next step: [Start services and run AgenticSeek](#Start-services-and-Run)
*See the **Known issues** section if you are having issues*
*See the **Config** section for detailled config file explanation.*
---
## Start services and Run
Activate your python env if needed.
```sh
source agentic_seek_env/bin/activate
```
Start required services. This will start all services from the docker-compose.yml, including:
- searxng
- redis (required by searxng)
- frontend
```sh
sudo ./start_services.sh # MacOS
start ./start_services.cmd # Window
```
**Options 1:** Run with the CLI interface.
```sh
python3 cli.py
```
We advice you set `headless_browser` to False in the config.ini for CLI mode.
**Options 2:** Run with the Web interface.
Start the backend.
```sh
python3 api.py
```
Go to `http://localhost:3000/` and you should see the web interface.
--- ---
## Usage ## Usage
Warning: currently the system that choose the best AI agent routing system will work poorly with non-english text. This is because the agent routing currently use a model that was trained on english text. We are working hard to fix this. Please use english for now. Make sure the services are up and running with `./start_services.sh` and run the AgenticSeek with `python3 cli.py` for CLI mode or `python3 api.py` then go to `localhost:3000` for web interface.
You can also use speech to text by setting `listen = True` in the config. Only for CLI mode.
Make sure the services are up and running with `./start_services.sh` and run the agenticSeek with `python3 main.py` To exit, simply say/type `goodbye`.
```sh
sudo ./start_services.sh
python3 main.py
```
You will be prompted with `>>> `
This indicate agenticSeek await you type for instructions.
You can also use speech to text by setting `listen = True` in the config.
Here are some example usage: Here are some example usage:
### Coding/Bash > *Make a snake game in python!*
> *Help me with matrix multiplication in Golang* > *Search the web for top cafes in Rennes, France, and save a list of three with their addresses in rennes_cafes.txt.*
> *Scan my network with nmap, find if any suspicious devices is connected* > *Write a Go program to calculate the factorial of a number, save it as factorial.go in your workspace*
> *Make a snake game in python* > *Search my summer_pictures folder for all JPG files, rename them with todays date, and save a list of renamed files in photos_list.txt*
### Web search > *Search online for popular sci-fi movies from 2024 and pick three to watch tonight. Save the list in movie_night.txt.*
> *Do a web search to find cool tech startup in Japan working on cutting edge AI research* > *Search the web for the latest AI news articles from 2025, select three, and write a Python script to scrape their titles and summaries. Save the script as news_scraper.py and the summaries in ai_news.txt in /home/projects*
> *Can you find on the internet who created agenticSeek?* > *Friday, search the web for a free stock price API, register with supersuper7434567@gmail.com then write a Python script to fetch using the API daily prices for Tesla, and save the results in stock_prices.csv*
> *Can you find on which website I can buy a rtx 4090 for cheap* *Note that form filling capabilities are still experimental and might fail.*
### File system
> *Hey can you find where is million_dollars_contract.pdf i lost it*
> *Show me how much space I have left on my disk*
> *Find and read the README.md and follow the install instruction*
### Casual
> *Tell me a joke*
> *Where is flight ABC777 ? my mom is on that plane*
> *what is the meaning of life ?*
After you type your query, agenticSeek will allocate the best agent for the task.
After you type your query, AgenticSeek will allocate the best agent for the task.
Because this is an early prototype, the agent routing system might not always allocate the right agent based on your query. Because this is an early prototype, the agent routing system might not always allocate the right agent based on your query.
@@ -206,77 +303,64 @@ Instead, ask:
--- ---
## **Run the LLM on your own server** ## **Setup to run the LLM on your own server**
If you have a powerful computer or a server that you can use, but you want to use it from your laptop you have the options to run the LLM on a remote server. If you have a powerful computer or a server that you can use, but you want to use it from your laptop you have the options to run the LLM on a remote server using our custom llm server.
### 1️⃣ **Set up and start the server scripts**
On your "server" that will run the AI model, get the ip address On your "server" that will run the AI model, get the ip address
```sh ```sh
ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 # local ip
curl https://ipinfo.io/ip # public ip
``` ```
Note: For Windows or macOS, use ipconfig or ifconfig respectively to find the IP address. Note: For Windows or macOS, use ipconfig or ifconfig respectively to find the IP address.
Clone the repository and then, run the script `stream_llm.py` in `server/` Clone the repository and enter the `server/`folder.
```sh ```sh
python3 server_ollama.py git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/llm_server/
``` ```
### 2️⃣ **Run it** Install server specific requirements:
```sh
pip3 install -r requirements.txt
```
Run the server script.
```sh
python3 app.py --provider ollama --port 3333
```
You have the choice between using `ollama` and `llamacpp` as a LLM service.
Now on your personal computer: Now on your personal computer:
Clone the repository. Change the `config.ini` file to set the `provider_name` to `server` and `provider_model` to `deepseek-r1:xxb`.
Change the `config.ini` file to set the `provider_name` to `server` and `provider_model` to `deepseek-r1:14b`.
Set the `provider_server_address` to the ip address of the machine that will run the model. Set the `provider_server_address` to the ip address of the machine that will run the model.
```sh ```sh
[MAIN] [MAIN]
is_local = False is_local = False
provider_name = server provider_name = server
provider_model = deepseek-r1:14b provider_model = deepseek-r1:70b
provider_server_address = x.x.x.x:5000 provider_server_address = x.x.x.x:3333
``` ```
Run the assistant:
```sh Next step: [Start services and run AgenticSeek](#Start-services-and-Run)
sudo ./start_services.sh
python3 main.py
```
## **Run with an API**
Clone the repository.
Set the desired provider in the `config.ini`
```sh
[MAIN]
is_local = False
provider_name = openai
provider_model = gpt4-o
provider_server_address = 127.0.0.1:5000 # can be set to anything, not used
```
Run the assistant:
```sh
sudo ./start_services.sh
python3 main.py
```
--- ---
## Speech to Text ## Speech to Text
Please note that currently speech to text only work in english.
The speech-to-text functionality is disabled by default. To enable it, set the listen option to True in the config.ini file: The speech-to-text functionality is disabled by default. To enable it, set the listen option to True in the config.ini file:
``` ```
@@ -300,25 +384,81 @@ End your request with a confirmation phrase to signal the system to proceed. Exa
"do it", "go ahead", "execute", "run", "start", "thanks", "would ya", "please", "okay?", "proceed", "continue", "go on", "do that", "go it", "do you understand?" "do it", "go ahead", "execute", "run", "start", "thanks", "would ya", "please", "okay?", "proceed", "continue", "go on", "do that", "go it", "do you understand?"
``` ```
## Config
Example config:
```
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:32b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = False
save_session = False
speak = False
listen = False
work_dir = /Users/mlg/Documents/ai_folder
jarvis_personality = False
languages = en zh
[BROWSER]
headless_browser = False
stealth_mode = False
```
**Explanation**:
- is_local -> Runs the agent locally (True) or on a remote server (False).
- provider_name -> The provider to use (one of: `ollama`, `server`, `lm-studio`, `deepseek-api`)
- provider_model -> The model used, e.g., deepseek-r1:32b.
- provider_server_address -> Server address, e.g., 127.0.0.1:11434 for local. Set to anything for non-local API.
- agent_name -> Name of the agent, e.g., Friday. Used as a trigger word for TTS.
- recover_last_session -> Restarts from last session (True) or not (False).
- save_session -> Saves session data (True) or not (False).
- speak -> Enables voice output (True) or not (False).
- listen -> listen to voice input (True) or not (False).
- work_dir -> Folder the AI will have access to. eg: /Users/user/Documents/.
- jarvis_personality -> Uses a JARVIS-like personality (True) or not (False). This simply change the prompt file.
- languages -> The list of supported language, needed for the llm router to work properly, avoid putting too many or too similar languages.
- headless_browser -> Runs browser without a visible window (True) or not (False).
- stealth_mode -> Make bot detector time harder. Only downside is you have to manually install the anticaptcha extension.
- languages -> List of supported languages. Required for agent routing system. The longer the languages list the more model will be downloaded.
## Providers ## Providers
The table below show the available providers: The table below show the available providers:
| Provider | Local? | Description | | Provider | Local? | Description |
|-----------|--------|-----------------------------------------------------------| |-----------|--------|-----------------------------------------------------------|
| Ollama | Yes | Run LLMs locally with ease using ollama as a LLM provider | | ollama | Yes | Run LLMs locally with ease using ollama as a LLM provider |
| Server | Yes | Host the model on another machine, run your local machine | | server | Yes | Host the model on another machine, run your local machine |
| OpenAI | No | Use ChatGPT API (non-private) | | lm-studio | Yes | Run LLM locally with LM studio (`lm-studio`) |
| Deepseek | No | Deepseek API (non-private) | | openai | Depends | Use ChatGPT API (non-private) or openai compatible API |
| HuggingFace| No | Hugging-Face API (non-private) | | deepseek-api | No | Deepseek API (non-private) |
| huggingface| No | Hugging-Face API (non-private) |
| togetherAI | No | Use together AI API (non-private) |
| google | No | Use google gemini API (non-private) |
To select a provider change the config.ini: To select a provider change the config.ini:
``` ```
is_local = False is_local = True
provider_name = openai provider_name = ollama
provider_model = gpt-4o provider_model = deepseek-r1:32b
provider_server_address = 127.0.0.1:5000 provider_server_address = 127.0.0.1:5000
``` ```
`is_local`: should be True for any locally running LLM, otherwise False. `is_local`: should be True for any locally running LLM, otherwise False.
@@ -352,40 +492,70 @@ And download the chromedriver version matching your OS.
![alt text](./media/chromedriver_readme.png) ![alt text](./media/chromedriver_readme.png)
If this section is incomplete please raise an issue.
## connection adapters Issues
```
Exception: Provider lm-studio failed: HTTP request failed: No connection adapters were found for '127.0.0.1:11434/v1/chat/completions'
```
Make sure you have `http://` in front of the provider IP address :
`provider_server_address = http://127.0.0.1:11434`
## SearxNG base URL must be provided
```
raise ValueError("SearxNG base URL must be provided either as an argument or via the SEARXNG_BASE_URL environment variable.")
ValueError: SearxNG base URL must be provided either as an argument or via the SEARXNG_BASE_URL environment variable.
```
Maybe you didn't move `.env.example` as `.env` ? You can also export SEARXNG_BASE_URL:
`export SEARXNG_BASE_URL="http://127.0.0.1:8080"`
## FAQ ## FAQ
**Q: What hardware do I need?** **Q: What hardware do I need?**
7B Model: GPU with 8GB VRAM. | Model Size | GPU | Comment |
14B Model: 12GB GPU (e.g., RTX 3060). |-----------|--------|-----------------------------------------------------------|
32B Model: 24GB+ VRAM. | 7B | 8GB Vram | ⚠️ Not recommended. Performance is poor, frequent hallucinations, and planner agents will likely fail. |
| 14B | 12 GB VRAM (e.g. RTX 3060) | ✅ Usable for simple tasks. May struggle with web browsing and planning tasks. |
| 32B | 24+ GB VRAM (e.g. RTX 4090) | 🚀 Success with most tasks, might still struggle with task planning |
| 70B+ | 48+ GB Vram (eg. mac studio) | 💪 Excellent. Recommended for advanced use cases. |
**Q: Why Deepseek R1 over other models?** **Q: Why Deepseek R1 over other models?**
Deepseek R1 excels at reasoning and tool use for its size. We think its a solid fit for our needs other models work fine, but Deepseek is our primary pick. Deepseek R1 excels at reasoning and tool use for its size. We think its a solid fit for our needs other models work fine, but Deepseek is our primary pick.
**Q: I get an error running `main.py`. What do I do?** **Q: I get an error running `cli.py`. What do I do?**
Ensure Ollama is running (`ollama serve`), your `config.ini` matches your provider, and dependencies are installed. If none work feel free to raise an issue. Ensure local is running (`ollama serve`), your `config.ini` matches your provider, and dependencies are installed. If none work feel free to raise an issue.
**Q: Can it really run 100% locally?** **Q: Can it really run 100% locally?**
Yes with Ollama or Server providers, all speech to text, LLM and text to speech model run locally. Non-local options (OpenAI or others API) are optional. Yes with Ollama, lm-studio or server providers, all speech to text, LLM and text to speech model run locally. Non-local options (OpenAI or others API) are optional.
**Q: How come it is older than manus ?** **Q: Why should I use AgenticSeek when I have Manus?**
we started this a fun side project to make a fully local, Jarvis-like AI. However, with the rise of Manus, we saw the opportunity to redirected some tasks to make yet another alternative. This started as Side-Project we did out of interest about AI agents. Whats special about it is that we want to use local model and avoid APIs.
We draw inspiration from Jarvis and Friday (Iron man movies) to make it "cool" but for functionnality we take more inspiration from Manus, because that's what people want in the first place: a local manus alternative.
**Q: How is it better than manus ?** Unlike Manus, AgenticSeek prioritizes independence from external systems, giving you more control, privacy and avoid api cost.
It's not but we prioritizes local execution and privacy over cloud based approach. Its a fun, accessible alternative!
## Contribute ## Contribute
Were looking for developers to improve AgenticSeek! Check out open issues or discussion. Were looking for developers to improve AgenticSeek! Check out open issues or discussion.
[Contribution guide](./docs/CONTRIBUTING.md)
[![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date) [![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
## Authors: ## Maintainers:
> [Fosowl](https://github.com/Fosowl)
> [steveh8758](https://github.com/steveh8758) > [Fosowl](https://github.com/Fosowl) | Paris Time
> [antoineVIVIES](https://github.com/antoineVIVIES) | Taipei Time
> [steveh8758](https://github.com/steveh8758) | Taipei Time
+571
View File
@@ -0,0 +1,571 @@
# AgenticSeek: Private, Local Manus Alternative.
<p align="center">
<img align="center" src="./media/whale_readme.jpg">
<p>
[English](./README.md) | 中文 | [日本語](./README_JP.md)
*一个 **100% 本地替代 Manus AI** 的方案,这款支持语音的 AI 助理能够自主浏览网页、编写代码和规划任务,同时将所有数据保留在您的设备上。专为本地推理模型量身打造,完全在您自己的硬件上运行,确保完全的隐私保护和零云端依赖。*
[![Visit AgenticSeek](https://img.shields.io/static/v1?label=Website&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![License](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/8hGDaME3TC) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/fosowl.svg?style=social&label=Update%20%40Fosowl)](https://x.com/Martin993886460)
### 为什么选择 AgenticSeek
* 🔒 完全本地化与隐私保护 - 所有功能都在您的设备上运行 — 无云端服务,无数据共享。您的文件、对话和搜索始终保持私密。
* 🌐 智能网页浏览 - AgenticSeek 能够自主浏览互联网 — 搜索、阅读、提取信息、填写网页表单 — 全程无需人工操作。
* 💻 自主编码助手 - 需要代码?它可以编写、调试并运行 Python、C、Go、Java 等多种语言的程序 — 全程无需监督。
* 🧠 智能代理选择 - 您提问,它会自动选择最适合该任务的代理。就像拥有一个随时待命的专家团队。
* 📋 规划与执行复杂任务 - 从旅行规划到复杂项目 — 它能将大型任务分解为步骤,并利用多个 AI 代理完成工作。
* 🎙️ 语音功能 - 清晰、快速、未来感十足的语音与语音转文本功能,让您能像科幻电影中一样与您的个人 AI 助手对话。
https://github.com/user-attachments/assets/4bd5faf6-459f-4f94-bd1d-238c4b331469
> 🛠️ **目前还在开发阶段** – 欢迎任何贡献者加入我们!
---
## **安装**
确保已安装了 Chrome driverDocker 和 Python 3.10(或更新)。
我们强烈建议您使用 Python 3.10 进行设置,否则可能会发生依赖错误。
有关于 Chrome driver 的问题,请参见 **Chromedriver** 部分。
### 1️⃣ **复制储存库与设置环境变数**
```sh
git clone https://github.com/Fosowl/agenticSeek.git
cd agenticSeek
mv .env.example .env
```
### 2 **建立虚拟环境**
```sh
python3 -m venv agentic_seek_env
source agentic_seek_env/bin/activate
# On Windows: agentic_seek_env\Scripts\activate
```
### 3️⃣ **安装所需套件**
**自动安装:**
```sh
./install.sh
```
** 若要让文本转语音(TTS)功能支持中文,你需要安装 jieba(中文分词库)和 cn2an(中文数字转换库):**
```
pip3 install jieba cn2an
```
**手动安装:**
**注意:对于任何操作系统,请确保您安装的 ChromeDriver 与您已安装的 Chrome 版本匹配。运行 `google-chrome --version`。如果您的 Chrome 版本 > 135,请参阅已知问题**
- *Linux*:
更新软件包列表:`sudo apt update`
安装依赖项:`sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
安装与您的 Chrome 浏览器版本匹配的 ChromeDriver
`sudo apt install -y chromium-chromedriver`
安装 requirements`pip3 install -r requirements.txt`
- *Macos*:
更新 brew`brew update`
安装 chromedriver`brew install --cask chromedriver`
安装 portaudio`brew install portaudio`
升级 pip`python3 -m pip install --upgrade pip`
升级 wheel`pip3 install --upgrade setuptools wheel`
安装 requirements`pip3 install -r requirements.txt`
- *Windows*:
安装 pyreadline3`pip install pyreadline3`
手动安装 portaudio(例如,通过 vcpkg 或预编译的二进制文件),然后运行:`pip install pyaudio`
从以下网址手动下载并安装 chromedriverhttps://sites.google.com/chromium.org/driver/getting-started
将 chromedriver 放置在包含在您的 PATH 中的目录中。
安装 requirements`pip3 install -r requirements.txt`
## 在本地机器上运行 AgenticSeek
**建议至少使用 Deepseek 14B 以上参数的模型,较小的模型难以使用助理功能并且很快就会忘记上下文之间的关系。**
**本地运行助手**
启动你的本地提供者,例如使用 ollama:
```sh
ollama serve
```
请参阅下方支持的本地提供者列表。
**更新 config.ini**
修改 config.ini 文件以设置 provider_name 为支持的提供者,并将 provider_model 设置为该提供者支持的 LLM。我们推荐使用具有推理能力的模型,如 *Qwen**Deepseek*
请参见 README 末尾的 **FAQ** 部分了解所需硬件。
```sh
[MAIN]
is_local = True # 无论是在本地运行还是使用远程提供者。
provider_name = ollama # 或 lm-studio, openai 等..
provider_model = deepseek-r1:14b # 选择适合您硬件的模型
provider_server_address = 127.0.0.1:11434
agent_name = Jarvis # 您的 AI 助手的名称
recover_last_session = True # 是否恢复之前的会话
save_session = True # 是否记住当前会话
speak = True # 文本转语音
listen = False # 语音转文本,仅适用于命令行界面
work_dir = /Users/mlg/Documents/workspace # AgenticSeek 的工作空间。
jarvis_personality = False # 是否使用更"贾维斯"风格的性格,不推荐在小型模型上使用
languages = en zh # 语言列表,文本转语音将默认使用列表中的第一种语言
[BROWSER]
headless_browser = True # 是否使用无头浏览器,只有在使用网页界面时才推荐使用。
stealth_mode = True # 使用无法检测的 selenium 来减少浏览器检测
```
警告:使用 LM-studio 运行 LLM 时,请*不要*将 provider_name 设置为 `openai`。请将其设置为 `lm-studio`
注意:某些提供者(如 lm-studio)需要在 IP 前面加上 `http://`。例如 `http://127.0.0.1:1234`
**本地提供者列表**
| 提供者 | 本地? | 描述 |
|-------------|--------|-------------------------------------------------------|
| ollama | 是 | 使用 ollama 作为 LLM 提供者,轻松本地运行 LLM |
| lm-studio | 是 | 使用 LM Studio 本地运行 LLM(将 `provider_name` 设置为 `lm-studio`|
| openai | 否 | 使用兼容的 API |
下一步: [Start services and run AgenticSeek](#Start-services-and-Run)
---
## **Run with an API (透过 API 执行)**
设定 `config.ini`
```sh
[MAIN]
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000
```
警告:确保 `config.ini` 没有行尾空格。
如果使用基于本机的 openai-based api 则把 `is_local` 设定为 `True`
同时更改你的 IP 为 openai-based api 的 IP。
下一步: [Start services and run AgenticSeek](#Start-services-and-Run)
---
## Start services and Run
(启动服务并运行)
如果需要,请激活你的 Python 环境。
```sh
source agentic_seek_env/bin/activate
```
启动所需的服务。这将启动 `docker-compose.yml` 中的所有服务,包括:
- searxng
- redis(由 redis 提供支持)
- 前端
```sh
sudo ./start_services.sh # MacOS
start ./start_services.cmd # Windows
```
**选项 1:** 使用 CLI 界面运行。
```sh
python3 cli.py
```
**选项 2:** 使用 Web 界面运行。
注意:目前我們建議您使用 CLI 界面。Web 界面仍在積極開發中。
启动后端服务。
```sh
python3 api.py
```
访问 `http://localhost:3000/`,你应该会看到 Web 界面。
请注意,目前 Web 界面不支持消息流式传输。
*如果你不知道如何开始,请参阅 **Usage** 部分*
---
## Usage (使用方法)
为确保 agenticSeek 在中文环境下正常工作,请确保在 config.ini 中设置语言选项。
languages = en zh
更多信息请参阅 Config 部分
确定所有的核心档案都启用了,也就是执行过这条命令 `./start_services.sh` 然后你就可以使用 `python3 cli.py` 来启动 AgenticSeek 了!
```sh
sudo ./start_services.sh
python3 cli.py
```
当你看到执行后显示 `>>> `
这表示一切运作正常,AgenticSeek 正在等待你给他任何指令。
你也可以透过设定 `config.ini` 内的 `listen = True` 来启用语音转文字。
要退出时,只要和他说 `goodbye` 就可以退出!
以下是一些用法:
### Coding/Bash
> *在 Golang 中帮助我进行矩阵乘法*
> *使用 nmap 扫描我的网路,找出是否有任何可疑装置连接*
> *用 Python 制作一个贪食蛇游戏*
### 网路搜寻
> *进行网路搜寻,找出日本从事尖端人工智慧研究的酷炫科技新创公司*
> *你能在网路上找到谁创造了 AgenticSeek 吗?*
> *你能在哪个网站上找到便宜的 RTX 4090 吗?*
### 档案浏览与搜寻
> *嘿,你能找到我遗失的 million_dollars_contract.pdf 在哪里吗?*
> *告诉我我的磁碟还剩下多少空间*
> *寻找并阅读 README.md,并按照安装说明进行操作*
### 日常聊天
> *告诉我关于法国的事*
> *人生的意义是什么?*
> *我应该在锻炼前还是锻炼后服用肌酸?*
当你把指令送出后,AgenticSeek 会自动调用最能提供帮助的助理,去完成你交办的工作和指令。
但也有可能出现怪怪的情况,或是你要找飞机机票,他跑去教你如何一步步做出一台飞机(开玩笑的,但真的可能出现),因为这是一个早期专案,我们会努力教导他、完善他的!
所以我们希望你在使用时,能明确地表明你希望他要怎么做,下面给你一个范例!
你该说:
- 进行网络搜索,找出哪些国家最适合独自旅行
而不是说:
- 你知道哪些国家适合独自旅行?
---
---
## **在本地执行属于你的 LLM 伺服器**
如果你有一台功能强大的电脑或伺服器,但你想透过笔记型电脑使用它,那么你可以选择在远端伺服器上执行 LLM。
### 1️⃣ **设定并启动伺服器脚本**
在运行 AI 模型的「伺服器」上,取得 IP 位址
```sh
ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1
```
注意:请在 Windows 或 MacOS,分别使用 `ipconfig``ifconfig` 来寻找 IP 位址。
**如果你希望使用基于 Openai 的服务,请按照 *透过 API 执行* 部分进行。**
复制储存库并且进入 `server/` 资料夹。
```sh
git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/server/
```
安装伺服器所需的套件:
```sh
pip3 install -r requirements.txt
```
执行伺服器脚本。
```sh
python3 app.py --provider ollama --port 3333
```
您可以选择使用 `ollama``llamacpp` 作为 LLM 的服务框架。
### 2️⃣ **执行**
在你的电脑上:
- 更改 `config.ini`
- `provider_name = server`
- `provider_model = deepseek-r1:14b`
- `provider_server_address = {你执行模型的电脑的 IP 位址}`
```sh
[MAIN]
is_local = False
provider_name = server
provider_model = deepseek-r1:14b
provider_server_address = x.x.x.x:3333
```
---
## 语音转文字
请注意,目前语音转文字功能仅支持英语。
预设状况下,语音转文字功能是停用的。若要启用它,请在 `config.ini` 档案中,将 `listen` 选项设为 `True`
```
listen = True
```
启用后 AgenticSeek 会聆听你是否呼唤他,他才会开始听你说的话,你可以在 *config.ini* 内去设定,要怎么叫他。
```
agent_name = Friday
```
为了获得比较好的结果,我们建议使用常见的英文名称(如 “John” 或 “Emma”)作为他的名字。
当你看到程式开始执行时,请大声说出他的名字,就可以唤醒 AgenticSeek 去聆听!(如:Friday
清楚说出你的需求。
用确认短句结束你说的话,以通知 AgenticSeek 继续。确认短句的范例包括:
```
"do it", "go ahead", "execute", "run", "start", "thanks", "would ya", "please", "okay?", "proceed", "continue", "go on", "do that", "go it", "do you understand?"
```
## Config
Config 范例:
```
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:1.5b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = False
save_session = False
speak = False
listen = False
work_dir = /Users/mlg/Documents/ai_folder
jarvis_personality = False
languages = en zh
[BROWSER]
headless_browser = False
stealth_mode = False
```
**说明**:
- is_local
- True:在本地运行。
- False:在远端伺服器运行。
- provider_name
- 框架类型
- `ollama`, `server`, `lm-studio`, `deepseek-api`
- provider_model
- 运行的模型
- `deepseek-r1:1.5b`, `deepseek-r1:14b`
- provider_server_address
- 伺服器 IP
- `127.0.0.1:11434`
- agent_name
- AgenticSeek 的名字,用作TTS的触发单词。
- `Friday`
- recover_last_session
- True:从上个对话继续。
- False:重启对话。
- save_session
- True:储存对话纪录。
- False:不保存。
- speak
- True:启用语音输出。
- False:关闭语音输出。
- listen
- True:启用语音输入。
- False:关闭语音输入。
- work_dir
- AgenticSeek 拥有能存取与交互的工作目录。
- jarvis_personality
> 就是那个钢铁人的 JARVIS
- True:启用 JARVIS 个性。
- False:关闭 JARVIS 个性。
- headless_browser
- True:前景浏览器。(很酷,推荐使用他 XD)
- False:背景执行浏览器。
- stealth_mode
- 隐私模式,但需要你自己安装反爬虫扩充功能。
- languages
- 支持的语言列表。用于代理路由系统。语言列表越长,下载的模型越多。
## 框架
下表显示了可用的框架:
| 框架 | 本地? | 描述|
|-|-|-|
| ollama | 可 | 使用 ollama 框架去执行本地模型 |
| server | 可 | 本地伺服器执行模型远端调用 |
| lm-studio | 可 | 使用 LM Studio 在本地运行 LLM(设定provider_name为lm-studio|
| openai | 不可 | 使用 ChatGPT API(无法保证隐私)|
| deepseek-api | 不可 | 使用 Deepseek API (无法保证隐私)|
| huggingface | 不可 | 使用 Hugging-Face API (无法保证隐私)|
若要选择框架,请变更 `config.ini` 文件:
```
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000
```
`is_local`: 对于任何本地运行的 LLM 都应该为 True,否则为 False。
`provider_name`: 透过名称选择要使用的框架,请参阅上面的框架清单。
`provider_model`: 设定 AgenticSeek 使用的模型。
`provider_server_address`: 如果不使用云端 API,则可以将其设定为任何内容。
# Known issues (已知问题)
## Chromedriver Issues
**已知问题 #1:** *chromedriver mismatch*
`Exception: Failed to initialize browser: Message: session not created: This version of ChromeDriver only supports Chrome version 113
Current browser version is 134.0.6998.89 with binary path`
如果你的浏览器和 chromedriver 版本不一样,就会发生这种情况。
你可以透过以下连结下载最新版本:
https://developer.chrome.com/docs/chromedriver/downloads
如果您使用的是 Chrome 版本 115 或更新版本,请前往:
https://googlechromelabs.github.io/chrome-for-testing/
下载与你的作业系统相符的 chromedriver 版本。
![alt text](./media/chromedriver_readme.png)
如果有其他问题,请提供尽量详细的叙述到 Issues 上,尽可能包含当前环境和问题是怎么发生的。
## FAQ
**Q: 我需要什麼硬體?**
| 模型大小 | GPU | 備註 |
|-----------|--------|-----------------------------------------------------------|
| 7B | 8GB Vram | ⚠️ 不推薦。性能較差,經常出現幻覺,規劃代理可能會失敗。 |
| 14B | 12 GB VRAM (例如 RTX 3060) | ✅ 適用於簡單任務。可能在網頁瀏覽和規劃任務上表現不佳。 |
| 32B | 24+ GB VRAM (例如 RTX 4090) | 🚀 大多數任務成功,但可能仍在任務規劃上有困難。 |
| 70B+ | 48+ GB Vram (例如 mac studio) | 💪 表現優異。建議用於高級使用情境。 |
**Q:为什么选择 Deepseek R1 而不是其他模型?**
就其尺寸而言,Deepseek R1 在推理和使用方面表现出色。我们认为非常适合我们的需求,其他模型也很好用,但 Deepseek 是我们最后选定的模型。
**Q:我在执行时 `cli.py` 时出现错误。我该怎么办?**
1. 确保 Ollama 正在运行(ollama serve
2.`config.ini``provider_name` 的框架选择正确。
3. 依赖套件已安装
4. 如果均无效,请随时提出 Issues,同样尽可能包含当前环境和问题是怎么发生的。
**Q:它真的是 100% 本地运行吗?**
是的,透过 Ollama 或其他框架,所有语音转文字、LLM 和文字转语音模型都在本地运行。
*但你能选择非本地执行(OpenAI 或其他 API),同样也是可以的*
**Q:我有 Manus 为甚么还要用 AgenticSeek**
这是我们因为兴趣做的一个小 Side-Project,他特别的点在于是一个全部本地化的模型,而且可以像钢铁人里面一样与 `Jarvis` 对话,听起来就超级酷的吧!随着 Manus 的进化,我们也相应的加入更多功能!
**Q:它比 Manus 好在哪里?**
不不不,AgenticSeek 和 Manus 是不同取向的东西,我们优先考虑的是本地执行和隐私,而不是基于云端。这是一个与 Manus 相比起来更有趣且易使用的方案!
**Q: 是否支持中文以外的语言?**
DeepSeek R1 天生会说中文
但注意:代理路由系统只懂英文,所以必须通过 config.ini 的 languages 参数(如 languages = en zh)告诉系统:
如果不设置中文?后果可能是:你让它写代码,结果跳出来个"医生代理"(虽然我们根本没有这个代理... 但系统会一脸懵圈!)
实际上会下载一个小型翻译模型来协助任务分配
## 贡献
我们正在寻找开发者来改善 AgenticSeek!你可以在 Issues 查看未解决的问题或和我们讨论更酷的新功能!
[![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
[Contribution guide](./docs/CONTRIBUTING.md)
## 维护者:
> [Fosowl](https://github.com/Fosowl) | 巴黎时间
> [antoineVIVIES](https://github.com/antoineVIVIES) | Taipei Time
> [steveh8758](https://github.com/steveh8758) | 台北时间
+563
View File
@@ -0,0 +1,563 @@
# AgenticSeek: 類似 Manus 但基於 Deepseek R1 Agents 的本地模型。
<p align="center">
<img align="center" src="./media/whale_readme.jpg">
<p>
--------------------------------------------------------------------------------
[English](./README.md) | 繁體中文 | [日本語](./README_JP.md)
*一个 **100% 本地替代 Manus AI** 的方案,這款支持語音的 AI 助理能够自主瀏覽網頁、编寫代码和規劃任務,同时將所有用戶資料保留在您的裝置上。專門為本地推理模型量身打造,完全在您自己的硬體上執行,确保完全的隐私保护和零雲端依賴。*
[![Visit AgenticSeek](https://img.shields.io/static/v1?label=Website&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![License](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/8hGDaME3TC) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/fosowl.svg?style=social&label=Update%20%40Fosowl)](https://x.com/Martin993886460)
### 为什么選擇 AgenticSeek
* 🔒 完全本地化與隐私保护 - 所有功能都在您的设备上運行 — 无云端服务,无数据共享。您的文件、对话和搜索始终保持私密。
* 🌐 智能網頁瀏覽 - AgenticSeek 能够自主瀏覽網頁 — 搜索、閱读、提取信息、填寫網页表單 — 全程无需人工操作。
* 💻 自主编码助手 - 需要代码?它可以编寫、调试并運行 Python、C、Go、Java 等多种语言的程序 — 全程无需监督。
* 🧠 智能代理选择 - 您提问,它會自动选择最适合该任务的代理。就像拥有一个随时待命的專家团队。
* 📋 规划與执行复杂任务 - 从旅行规划到复杂项目 — 它能將大型任务分解为步骤,并利用多个 AI 代理完成工作。
* 🎙️ 語音功能 - 清晰、快速、未来感十足的語音與語音轉文本功能,讓您能像科幻电影中一样與您的个人 AI 助手对话。
https://github.com/user-attachments/assets/4bd5faf6-459f-4f94-bd1d-238c4b331469
> 🛠️ **目前還在開發階段** – 歡迎任何貢獻者加入我們!
---
## **安裝**
確保已安裝了 Chrome driverDocker 和 Python 3.10(或更新)。
我们强烈建议您使用 Python 3.10 進行設定,否则可能會发生依赖错误。
有關於 Chrome driver 的問題,請參見 **Chromedriver** 部分。
### 1️⃣ **複製儲存庫與設置環境變數**
```sh
git clone https://github.com/Fosowl/agenticSeek.git
cd agenticSeek
mv .env.example .env
```
### 2 **建立虛擬環境**
```sh
python3 -m venv agentic_seek_env
source agentic_seek_env/bin/activate
# On Windows: agentic_seek_env\Scripts\activate
```
### 3️⃣ **安裝所需套件**
**自動安裝:**
```sh
./install.sh
```
** 若要將文字轉成語音(TTS)功能支持中文,你需要安装 jieba(中文分詞庫)和 cn2an(中文數字轉換庫):**
```
pip3 install jieba cn2an
```
**手動安裝:**
**注意:對於不同作業系統,請確保已經安装的 ChromeDriver 與您已安装的 Chrome 版本一致。可以執行 `google-chrome --version`。如果您的 Chrome 版本 > 135,請參考已知问题**
- *Linux*:
更新软件包列表:`sudo apt update`
安装依赖项:`sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
安装與您的 Chrome 瀏覽器版本匹配的 ChromeDriver
`sudo apt install -y chromium-chromedriver`
安装 requirements`pip3 install -r requirements.txt`
- *Macos*:
更新 brew`brew update`
安装 chromedriver`brew install --cask chromedriver`
安装 portaudio`brew install portaudio`
升级 pip`python3 -m pip install --upgrade pip`
升级 wheel`pip3 install --upgrade setuptools wheel`
安装 requirements`pip3 install -r requirements.txt`
- *Windows*:
安装 pyreadline3`pip install pyreadline3`
手动安装 portaudio(例如,通过 vcpkg 或預編譯的二進制文件),然後運行:`pip install pyaudio`
从以下網址手动下载并安装 chromedriverhttps://sites.google.com/chromium.org/driver/getting-started
將 chromedriver 放置在包含在您的 PATH 中的目录中。
安装 requirements`pip3 install -r requirements.txt`
## 在本地機器上運行 AgenticSeek
**建議至少使用 Deepseek 14B 以上參數的模型,較小的模型難以使用助理功能並且很快就會忘記上下文之間的關係。**
**本地運行助手**
啟動你的本地提供者,例如使用 ollama:
```sh
ollama serve
```
请参閱下方支持的本地提供者列表。
修改 config.ini 文件以設定 provider_name 为支持的提供者,并將 provider_model 設定为该提供者支持的 LLM。我们推荐使用具有推理能力的模型,如 *Qwen**Deepseek*
请参见 README 末尾的 **FAQ** 部分了解所需硬件。
```sh
[MAIN]
is_local = True # 无论是在本地運行还是使用远程提供者。
provider_name = ollama # 或 lm-studio, openai 等..
provider_model = deepseek-r1:14b # 选择适合您硬件的模型
provider_server_address = 127.0.0.1:11434
agent_name = Jarvis # 您的 AI 助手的名称
recover_last_session = True # 是否恢复之前的會话
save_session = True # 是否记住当前會话
speak = True # 文本轉語音
listen = False # 語音轉文本,僅适用于命令行界面
work_dir = /Users/mlg/Documents/workspace # AgenticSeek 的工作空间。
jarvis_personality = False # 是否使用更"贾维斯"风格的性格,不推荐在小型模型上使用
languages = en zh # 语言列表,文本轉語音將默认使用列表中的第一种语言
[BROWSER]
headless_browser = True # 是否使用无头瀏覽器,只有在使用網页界面时才推荐使用。
stealth_mode = True # 使用无法檢測的 selenium 来减少瀏覽器檢測
```
**本地提供者列表**
| 提供者 | 本地? | 描述 |
|-------------|--------|-------------------------------------------------------|
| ollama | 是 | 使用 ollama 作为 LLM 提供者,轻松本地運行 LLM |
| lm-studio | 是 | 使用 LM Studio 本地運行 LLM(將 `provider_name` 設定为 `lm-studio`|
| openai | 否 | 使用兼容的 API |
下一步: [Start services and run AgenticSeek](#Start-services-and-Run)
---
## **Run with an API (透過 API 執行)**
設定 `config.ini`
```sh
[MAIN]
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000
```
警告:確保 `config.ini` 沒有行尾空格。
如果使用基於本機的 openai-based api 則把 `is_local` 設定為 `True`
同時更改你的 IP 為 openai-based api 的 IP。
下一步: [Start services and run AgenticSeek](#Start-services-and-Run)
---
## Start services and Run
(啟動服务并運行)
如果需要,请激活你的 Python 环境。
```sh
source agentic_seek_env/bin/activate
```
啟動所需的服务。这將啟動 `docker-compose.yml` 中的所有服务,包括:
- searxng
- redis(由 redis 提供支持)
- 前端
```sh
sudo ./start_services.sh # MacOS
start ./start_services.cmd # Windows
```
**選項 1:** 使用 CLI 界面運行。
```sh
python3 cli.py
```
**選項 2:** 使用 Web 界面運行。
注意:目前我們建議您使用 CLI 界面。Web 界面仍在積極開發中。
啟動後端服务。
```sh
python3 api.py
```
访问 `http://localhost:3000/`,你应该會看到 Web 界面。
请注意,目前 Web 界面不支持消息流式傳輸。
*如果你不知道如何開始,請參閱 **Usage** 部分*
---
## Usage (使用方法)
为确保 agenticSeek 在中文环境下正常工作,请确保在 config.ini 中設定语言選項。
languages = en zh
更多信息请参閱 Config 部分
確定所有的核心檔案都啟用了,也就是執行過這條命令 `./start_services.sh` 然後你就可以使用 `python3 cli.py` 來啟動 AgenticSeek 了!
```sh
sudo ./start_services.sh
python3 cli.py
```
當你看到執行後顯示 `>>> `
這表示一切運作正常,AgenticSeek 正在等待你給他任何指令。
你也可以透過設定 `config.ini` 內的 `listen = True` 來啟用語音轉文字。
要退出時,只要和他說 `goodbye` 就可以退出!
以下是一些用法:
### Coding/Bash
> *在 Golang 中幫助我進行矩陣乘法*
> *使用 nmap 掃描我的網路,找出是否有任何可疑裝置連接*
> *用 Python 製作一個貪食蛇遊戲*
### 網路搜尋
> *進行網路搜尋,找出日本從事尖端人工智慧研究的酷炫科技新創公司*
> *你能在網路上找到誰創造了 AgenticSeek 嗎?*
> *你能在哪個網站上找到便宜的 RTX 4090 嗎?*
### 檔案瀏覽與搜尋
> *嘿,你能找到我遺失的 million_dollars_contract.pdf 在哪裡嗎?*
> *告訴我我的磁碟還剩下多少空間*
> *尋找並閱讀 README.md,並按照安裝說明進行操作*
### 日常聊天
> *告訴我關於法國的事*
> *人生的意義是什麼?*
> *我應該在鍛鍊前還是鍛鍊後服用肌酸?*
當你把指令送出後,AgenticSeek 會自動調用最能提供幫助的助理,去完成你交辦的工作和指令。
但也有可能出現怪怪的情況,或是你要找飛機機票,他跑去教你如何一步步做出一台飛機(開玩笑的,但真的可能出現),因為這是一個早期專案,我們會努力教導他、完善他的!
所以我們希望你在使用時,能明確地表明你希望他要怎麼做,下面給你一個範例!
你該說:
- 進行網路搜索,找出哪些国家最适合獨自旅行
而不是說:
- 你知道哪些国家适合獨自旅行?
---
---
## **在本地執行屬於你的 LLM 伺服器**
如果你有一台功能強大的電腦或伺服器,但你想透過筆記型電腦使用它,那麼你可以選擇在遠端伺服器上執行 LLM。
### 1️⃣ **設定並啟動伺服器腳本**
在運行 AI 模型的「伺服器」上,取得 IP 位址
```sh
ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1
```
注意:請在 Windows 或 MacOS,分別使用 `ipconfig``ifconfig` 來尋找 IP 位址。
**如果你希望使用基於 Openai 的服務,請按照 *透過 API 執行* 部分進行。**
複製儲存庫並且進入 `server/` 資料夾。
```sh
git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/server/
```
安裝伺服器所需的套件:
```sh
pip3 install -r requirements.txt
```
執行伺服器腳本。
```sh
python3 app.py --provider ollama --port 3333
```
您可以選擇使用 `ollama``llamacpp` 作為 LLM 的服務框架。
### 2️⃣ **執行**
在你的電腦上:
- 更改 `config.ini`
- `provider_name = server`
- `provider_model = deepseek-r1:14b`
- `provider_server_address = {你執行模型的電腦的 IP 位址}`
```sh
[MAIN]
is_local = False
provider_name = server
provider_model = deepseek-r1:14b
provider_server_address = x.x.x.x:3333
```
---
## 語音轉文字
请注意,目前語音轉文字功能僅支援英语。
預設狀況下,語音轉文字功能是停用的。若要啟用它,請在 `config.ini` 檔案中,將 `listen` 選項設為 `True`
```
listen = True
```
啟用後 AgenticSeek 會聆聽你是否呼喚他,他才會開始聽你說的話,你可以在 *config.ini* 內去設定,要怎麼叫他。
```
agent_name = Friday
```
為了獲得比較好的結果,我們建議使用常見的英文名稱(如 “John” 或 “Emma”)作為他的名字。
當你看到程式開始執行時,請大聲說出他的名字,就可以喚醒 AgenticSeek 去聆聽!(如:Friday
清楚說出你的需求。
用確認短句結束你說的話,以通知 AgenticSeek 繼續。確認短句的範例包括:
```
"do it", "go ahead", "execute", "run", "start", "thanks", "would ya", "please", "okay?", "proceed", "continue", "go on", "do that", "go it", "do you understand?"
```
## Config
Config 範例:
```
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:1.5b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = False
save_session = False
speak = False
listen = False
work_dir = /Users/mlg/Documents/ai_folder
jarvis_personality = False
languages = en zh
[BROWSER]
headless_browser = False
stealth_mode = False
```
**說明**:
- is_local
- True:在本地運行。
- False:在遠端伺服器運行。
- provider_name
- 框架類型
- `ollama`, `server`, `lm-studio`, `deepseek-api`
- provider_model
- 運行的模型
- `deepseek-r1:1.5b`, `deepseek-r1:14b`
- provider_server_address
- 伺服器 IP
- `127.0.0.1:11434`
- agent_name
- AgenticSeek 的名字,用作TTS的觸發單詞。
- `Friday`
- recover_last_session
- True:從上個對話繼續。
- False:重啟對話。
- save_session
- True:儲存對話紀錄。
- False:不保存。
- speak
- True:啟用語音輸出。
- False:關閉語音輸出。
- listen
- True:啟用語音輸入。
- False:關閉語音輸入。
- work_dir
- AgenticSeek 擁有能存取與交互的工作目錄。
- jarvis_personality
> 就是那個鋼鐵人的 JARVIS
- True:啟用 JARVIS 個性。
- False:關閉 JARVIS 個性。
- headless_browser
- True:前景瀏覽器。(很酷,推薦使用他 XD)
- False:背景執行瀏覽器。
- stealth_mode
- 隱私模式,但需要你自己安裝反爬蟲擴充功能。
- languages
- 支持的语言列表。用于代理路由系统。语言列表越长,下载的模型越多。
## 框架
下表顯示了可用的框架:
| 框架 | 本地? | 描述|
|-|-|-|
| ollama | 可 | 使用 ollama 框架去執行本地模型 |
| server | 可 | 本地伺服器執行模型遠端調用 |
| lm-studio | 可 | 使用 LM Studio 在本地運行 LLM(設定provider_name為lm-studio|
| openai | 不可 | 使用 ChatGPT API(無法保證隱私)|
| deepseek-api | 不可 | 使用 Deepseek API (無法保證隱私)|
| huggingface | 不可 | 使用 Hugging-Face API (無法保證隱私)|
若要選擇框架,請變更 `config.ini` 文件:
```
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000
```
`is_local`: 對於任何本地運行的 LLM 都應該為 True,否則為 False。
`provider_name`: 透過名稱選擇要使用的框架,請參閱上面的框架清單。
`provider_model`: 設定 AgenticSeek 使用的模型。
`provider_server_address`: 如果不使用雲端 API,則可以將其設定為任何內容。
# Known issues (已知問題)
## Chromedriver Issues
**已知問題 #1:** *chromedriver mismatch*
`Exception: Failed to initialize browser: Message: session not created: This version of ChromeDriver only supports Chrome version 113
Current browser version is 134.0.6998.89 with binary path`
如果你的瀏覽器和 chromedriver 版本不一樣,就會發生這種情況。
你可以透過以下連結下載最新版本:
https://developer.chrome.com/docs/chromedriver/downloads
如果您使用的是 Chrome 版本 115 或更新版本,請前往:
https://googlechromelabs.github.io/chrome-for-testing/
下載與你的作業系統相符的 chromedriver 版本。
![alt text](./media/chromedriver_readme.png)
如果有其他問題,請提供盡量詳細的敘述到 Issues 上,盡可能包含當前環境和問題是怎麼發生的。
## FAQ
**Q: 我需要什麼硬體?**
| 模型大小 | GPU | 備註 |
|-----------|--------|-----------------------------------------------------------|
| 7B | 8GB Vram | ⚠️ 不推薦。性能較差,經常出現幻覺,規劃代理可能會失敗。 |
| 14B | 12 GB VRAM (例如 RTX 3060) | ✅ 適用於簡單任務。可能在網頁瀏覽和規劃任務上表現不佳。 |
| 32B | 24+ GB VRAM (例如 RTX 4090) | 🚀 大多數任務成功,但可能仍在任務規劃上有困難。 |
| 70B+ | 48+ GB Vram (例如 mac studio) | 💪 表現優異。建議用於高級使用情境。 |
**Q:為什麼選擇 Deepseek R1 而不是其他模型?**
就其尺寸而言,Deepseek R1 在推理和使用方面表現出色。我們認為非常適合我們的需求,其他模型也很好用,但 Deepseek 是我們最後選定的模型。
**Q:我在執行時 `cli.py` 時出現錯誤。我該怎麼辦?**
1. 確保 Ollama 正在運行(ollama serve
2.`config.ini``provider_name` 的框架選擇正確。
3. 依賴套件已安裝
4. 如果均無效,請隨時提出 Issues,同樣盡可能包含當前環境和問題是怎麼發生的。
**Q:它真的是 100% 本地運行嗎?**
是的,透過 Ollama 或其他框架,所有語音轉文字、LLM 和文字轉語音模型都在本地運行。
*但你能選擇非本地執行(OpenAI 或其他 API),同樣也是可以的*
**Q:我有 Manus 為甚麼還要用 AgenticSeek**
這是我們因為興趣做的一個小 Side-Project,他特別的點在於是一個全部本地化的模型,而且可以像鋼鐵人裡面一樣與 `Jarvis` 對話,聽起來就超級酷的吧!隨著 Manus 的進化,我們也相應的加入更多功能!
**Q:它比 Manus 好在哪裡?**
不不不,AgenticSeek 和 Manus 是不同取向的東西,我們優先考慮的是本地執行和隱私,而不是基於雲端。這是一個與 Manus 相比起來更有趣且易使用的方案!
**Q: 是否支持中文以外的语言?**
DeepSeek R1 天生會说中文
但注意:代理路由系统只懂英文,所以必须通过 config.ini 的 languages 参数(如 languages = en zh)告诉系统:
如果不設定中文?後果可能是:你讓它寫代码,结果跳出来个"醫生代理"(虽然我们根本没有这个代理... 但系统會一脸懵圈!)
实际上會下载一个小型翻译模型来协助任务分配
## 貢獻
我們正在尋找開發者來改善 AgenticSeek!你可以在 Issues 查看未解決的問題或和我們討論更酷的新功能!
[![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
[Contribution guide](./docs/CONTRIBUTING.md)
## 维护者:
> [Fosowl](https://github.com/Fosowl) | 巴黎時間 | (有时很忙)
> [https://github.com/antoineVIVIES](https://github.com/antoineVIVIES) | 台北時間 | (經常很忙)
> [steveh8758](https://github.com/steveh8758) | 台北時間 | (總是很忙)
+498
View File
@@ -0,0 +1,498 @@
<p align="center">
<img align="center" src="./media/whale_readme.jpg">
<p>
--------------------------------------------------------------------------------
[English](./README.md) | [繁體中文](./README_CHT.md) | [日本語](./README_JP.md) | Français
# AgenticSeek: Une IA comme Manus mais à base d'agents DeepSeek R1 fonctionnant en local.
Une alternative **entièrement locale** à Manus AI, un assistant IA qui code, explore votre système de fichiers, navigue sur le web et corrige ses erreurs, tout cela sans envoyer la moindre donnée dans le cloud. Cet agent autonome fonctionne entièrement sur votre hardware, garantissant la confidentialité de vos données.
[![Visit AgenticSeek](https://img.shields.io/static/v1?label=Website&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![License](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/8hGDaME3TC) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/fosowl.svg?style=social&label=Update%20%40Fosowl)](https://x.com/Martin993886460)
> 🛠️ **En cours de développement** On cherche activement des contributeurs!
https://github.com/user-attachments/assets/4bd5faf6-459f-4f94-bd1d-238c4b331469
> *Recherche sur le web des activités à faire à Paris*
> *Code le jeu snake en python*
> *J'aimerais que tu trouve une api météo et que tu me code une application qui affiche la météo à Toulouse*
## Fonctionnalités:
- **100% Local**: Fonctionne en local sur votre PC. Vos données restent les vôtres.
- **Accès à vos Fichiers**: Utilise bash pour naviguer et manipuler vos fichiers.
- **Codage semi-autonome**: Peut écrire, déboguer et exécuter du code en Python, C, Golang et d'autres langages à venir.
- **Routage d'Agent**: Sélectionne automatiquement lagent approprié pour la tâche.
- **Planification**: Pour les taches complexe utilise plusieurs agents.
- **Navigation Web Autonome**: Navigation web autonome.
- **Memoire efficace**: Gestion efficace de la mémoire et des sessions.
---
## **Installation**
Assurez-vous davoir installé le pilote Chrome, Docker et Python 3.10.
Nous vous conseillons fortement d'utiliser exactement Python 3.10 pour l'installation. Des erreurs de dépendances pourraient survenir autrement.
Pour les problèmes liés au pilote Chrome, consultez la section Chromedriver.
### 1️⃣ Cloner le repo et configurer
```sh
git clone https://github.com/Fosowl/agenticSeek.git
cd agenticSeek
mv .env.example .env
```
### 2 **Créer un environnement virtuel**
```sh
python3 -m venv agentic_seek_env
source agentic_seek_env/bin/activate
# Sur Windows: agentic_seek_env\Scripts\activate
```
### 3️⃣ **Installation**
**Automatique:**
```sh
./install.sh
```
**Manuel:**
**Note : Pour tous les systèmes d'exploitation, assurez-vous que le ChromeDriver que vous installez correspond à la version de Chrome installée. Exécutez `google-chrome --version`. Consultez les problèmes connus si vous avez Chrome >135**
- *Linux*:
Mettre à jour la liste des paquets : `sudo apt update`
Installer les dépendances : `sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
Installer ChromeDriver correspondant à la version de votre navigateur Chrome :
`sudo apt install -y chromium-chromedriver`
Installer les prérequis : `pip3 install -r requirements.txt`
- *macOS*:
Mettre à jour brew : `brew update`
Installer chromedriver : `brew install --cask chromedriver`
Installer portaudio : `brew install portaudio`
Mettre à jour pip : `python3 -m pip install --upgrade pip`
Mettre à jour wheel : `pip3 install --upgrade setuptools wheel`
Installer les prérequis : `pip3 install -r requirements.txt`
- *Windows*:
Installer pyreadline3 : `pip install pyreadline3`
Installer portaudio manuellement (par exemple, via vcpkg ou des binaires précompilés) puis exécutez : `pip install pyaudio`
Télécharger et installer chromedriver manuellement depuis : https://sites.google.com/chromium.org/driver/getting-started
Placez chromedriver dans un répertoire inclus dans votre PATH.
Installer les prérequis : `pip3 install -r requirements.txt`
## Faire fonctionner sur votre machine
**Nous recommandons dutiliser au minimum DeepSeek 14B, les modèles plus petits ont du mal avec lutilisation des outils et oublient rapidement le contexte.**
Lancer votre provider local, par exemple avec ollama:
```sh
ollama serve
```
**Configurer le config.ini**
Modifiez le fichier config.ini pour définir provider_name sur un fournisseur supporté et provider_model sur un LLM compatible avec votre fournisseur. Nous recommandons des modèles de raisonnement comme *Qwen* ou *Deepseek*.
Consultez la section **FAQ** à la fin du README pour connaître le matériel requis.
```sh
[MAIN]
is_local = True # Si vous exécutez localement ou avec un fournisseur distant.
provider_name = ollama # ou lm-studio, openai, etc..
provider_model = deepseek-r1:14b # choisissez un modèle adapté à votre matériel
provider_server_address = 127.0.0.1:11434
agent_name = Jarvis # nom de votre IA
recover_last_session = True # récupérer ou non la session précédente
save_session = True # mémoriser ou non la session actuelle
speak = True # synthèse vocale
listen = False # reconnaissance vocale, uniquement pour CLI
work_dir = /Users/mlg/Documents/workspace # L'espace de travail pour AgenticSeek.
jarvis_personality = False # Utiliser une personnalité plus "Jarvis", non recommandé avec des petits modèles
languages = en fr # Liste des langages, la synthèse vocale utilisera par défaut la première langue de la liste
[BROWSER]
headless_browser = True # Utiliser ou non le navigateur sans interface graphique, recommandé uniquement avec l'interface web.
stealth_mode = True # Utiliser selenium non détectable pour réduire la détection du navigateur
```
Remarque : Certains fournisseurs (ex : lm-studio) nécessitent `http://` devant l'adresse IP. Par exemple `http://127.0.0.1:1234`
**Liste des provideurs locaux**
| Fournisseur | Local ? | Description |
|-------------|---------|-----------------------------------------------------------|
| ollama | Oui | Exécutez des LLM localement avec facilité en utilisant ollama comme fournisseur LLM |
| lm-studio | Oui | Exécutez un LLM localement avec LM studio (définissez `provider_name` sur `lm-studio`) |
| openai | Oui | Utilisez une API local compatible avec openai |
### **Démarrer les services & Exécuter**
Activez votre environnement Python si nécessaire.
```sh
source agentic_seek_env/bin/activate
```
Démarrez les services requis. Cela lancera tous les services définis dans le fichier docker-compose.yml, y compris :
- searxng
- redis (nécessaire pour searxng)
- frontend
```sh
sudo ./start_services.sh # MacOS
start ./start_services.cmd # Windows
```
**Option 1 :** Exécuter avec l'interface CLI.
```sh
python3 cli.py
```
**Option 2 :** Exécuter avec l'interface Web.
Démarrez le backend.
```sh
python3 api.py
```
Allez sur `http://localhost:3000/` et vous devriez voir l'interface web.
Veuillez noter que l'interface web ne diffuse pas les messages en continu pour le moment.
Voyez la section **Utilisation** si vous ne comprenez pas comment lutiliser
Voyez la section **Problèmes** connus si vous rencontrez des problèmes
Voyez la section **Exécuter avec une API** si votre matériel ne peut pas exécuter DeepSeek localement
Voyez la section **Configuration** pour une explication détaillée du fichier de configuration.
---
## Utilisation
Assurez-vous que les services sont en cours dexécution avec ./start_services.sh et lancez AgenticSeek avec le CLI ou l'interface Web.
**CLI:**
Vous verrez un prompt : ">>> "
Cela indique quAgenticSeek attend que vous saisissiez des instructions.
Vous pouvez également utiliser la reconnaissance vocale en définissant `listen = True` dans la configuration.
Pour quitter, dites simplement `goodbye`.
**Interface:**
Assurez-vous d'avoir bien démarré le backend avec `python3 api.py`.
Allez sur `localhost:3000` où vous verrez une interface web.
Tapez simplement votre message et patientez.
Si vous n'avez pas d'interface sur `localhost:3000`, c'est que vous n'avez pas démarré les services avec `start_services.sh`.
Voici quelques exemples dutilisation :
### Programmation
> *Aide-moi avec la multiplication de matrices en Golang*
> *Initalize un nouveau project python, setup le readme, gitignore etc.. et fait un premier commit*
> *Fais un jeu snake en Python*
### Recherche web
> *Fais une recherche sur le web pour trouver des startups technologiques au Japon qui travaillent sur des recherches avancées en IA*
> *Peux-tu trouver sur internet qui a créé agenticSeek ?*
> *Peux-tu trouver sur quel site je peux acheter une RTX 4090 à bas prix ?*
### Fichier
> *Hé, peux-tu trouver où est contrat.pdf ? Je lai perdu*
> *Montre-moi combien despace il me reste sur mon disque*
> *Trouve et lis le fichier README.md et suis les instructions dinstallation*
### Conversation
> *Parle-moi de la France*
> *Quel est le sens de la vie ?*
> *Donne moi une recette simple pour ce midi j'ai pas d'inspi*
Après avoir saisi votre requête, AgenticSeek attribuera le meilleur agent pour la tâche.
Le système de routage des agents peut parfois ne pas toujours attribuer le bon agent en fonction de votre requête.
Par conséquent, vous devez être assez explicite sur ce que vous voulez et sur la manière dont lIA doit procéder. Par exemple, si vous voulez quelle effectue une recherche sur le web, ne dites pas :
Connait-tu de bons pays pour voyager seul ?
Dites plutôt :
Fait une recherche sur le web, quels sont les meilleurs pays pour voyager seul?
---
## **Exécuter le LLM sur votre propre serveur**
Si vous disposez dun ordinateur puissant ou dun serveur que vous voulez utiliser, mais que vous souhaitez y accéder depuis votre ordinateur portable, vous avez la possibilité dexécuter le LLM sur un serveur distant.
### 1️⃣ **Configurer et démarrer les scripts du serveur**
Sur votre "serveur" qui exécutera le modèle IA, obtenez ladresse IP
```sh
ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1
```
Remarque : Pour Windows ou macOS, utilisez respectivement ipconfig ou ifconfig pour trouver ladresse IP.
Clonez le dépôt et entrez dans le dossier server/.
```sh
git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/server/
```
Installez les dépendances spécifiques au serveur :
```sh
pip3 install -r requirements.txt
```
Exécutez le script du serveur.
```sh
python3 app.py --provider ollama --port 3333
```
Vous avez le choix entre utiliser ollama et llamacpp comme service LLM.
### 2️⃣ **Lancer**
Maintenant, sur votre ordinateur personnel :
Modifiez le fichier config.ini pour définir provider_name sur server et provider_model sur deepseek-r1:14b.
Définissez provider_server_address sur ladresse IP de la machine qui exécutera le modèle.
```sh
[MAIN]
is_local = False
provider_name = server
provider_model = deepseek-r1:14b
provider_server_address = x.x.x.x:3333
```
Ensuite, exécutez avec le CLI ou l'interface graphique comme expliqué dans la section pour les fournisseurs locaux.
## **Exécuter avec une API externe**
AVERTISSEMENT : Assurez-vous quil ny a pas despace en fin de ligne dans la configuration.
```sh
[MAIN]
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000 # n'importe pas
```
**Liste de provideurs API**
| Fournisseur | Local ? | Description |
|--------------|---------|-----------------------------------------------------------|
| openai | Non | Utilise l'API ChatGPT |
| deepseek-api | Non | API Deepseek (non privé) |
| huggingface | Non | API Hugging-Face (non privé) |
| togetherAI | Non | Utilise l'API Together AI (non privé) |
| google | Non | Utilise l'API Google Gemini (non privé) |
Ensuite, exécutez avec le CLI ou l'interface graphique comme expliqué dans la section pour les fournisseurs locaux.
## Config
Exemple de configuration :
```
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:1.5b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = False
save_session = False
speak = False
listen = False
work_dir = /Users/mlg/Documents/ai_folder
jarvis_personality = False
languages = en fr
[BROWSER]
headless_browser = False
stealth_mode = False
```
**Explication du fichier config.ini**:
`is_local` -> Exécute lagent localement (True) ou sur un serveur distant (False).
`provider_name` -> Le fournisseur à utiliser (parmi : ollama, server, lm-studio, deepseek-api).
`provider_model` -> Le modèle utilisé, par exemple, deepseek-r1:1.5b.
`provider_server_address` -> Adresse du serveur, par exemple, 127.0.0.1:11434 pour local. Définissez nimporte quoi pour une API non locale.
`agent_name` -> Nom de lagent, par exemple, Friday. Utilisé comme mot déclencheur pour la reconnaissance vocale.
`recover_last_session` -> Reprend la dernière session (True) ou non (False).
`save_session` -> Sauvegarde les données de la session (True) ou non (False).
`speak` -> Active la sortie vocale (True) ou non (False).
`listen` -> Écoute les entrées vocales (True) ou non (False).
`work_dir` -> Dossier auquel lIA aura accès, par exemple : /Users/user/Documents/.
`jarvis_personality` -> Utilise une personnalité inspiré de Jarvis (True) ou non (False). Cela utilise simplement une prompt alternative. Marche moins bien en français.
`headless_browser` -> Exécute le navigateur sans fenêtre visible (True) ou non (False).
`stealth_mode` -> Rend la détection des bots plus difficile. Le seul inconvénient est que vous devez installer manuellement lextension anticaptcha.
`languages` -> La liste de languages supportés (nécessaire pour le routage d'agents). Plus la liste est longue. Plus un nombre important de modèles sera téléchargés.
## Providers
Le tableau ci-dessous montre les LLM providers disponibles :
| Provider | Local? | Description |
|-----------|--------|-----------------------------------------------------------|
| ollama | Yes | Exécutez des LLM localement avec facilité en utilisant Ollama comme fournisseur LLM
| server | Yes | Hébergez le modèle sur une autre machine, exécutez sur votre machine locale
| lm-studio | Yes | Exécutez un LLM localement avec LM Studio (définissez provider_name sur lm-studio)
| openai | No | Utilise l'API ChatGPT (pas privé) |
| deepseek-api | No | Utilise l'API Deepseek (pas privé) |
| huggingface| No | Utilise Hugging-Face (pas privé) |
| together| No | Utilise l'api Together AI |
Pour sélectionner un provider LLM, modifiez le config.ini :
```
is_local = False
provider_name = openai
provider_model = gpt-4o
provider_server_address = 127.0.0.1:5000
```
`is_local` : doit être True pour tout LLM exécuté localement, sinon False.
`provider_name` : Sélectionnez le fournisseur à utiliser par son nom, voir la liste des fournisseurs ci-dessus.
`provider_model` : Définissez le modèle à utiliser par lagent.
`provider_server_address` : peut être défini sur nimporte quoi si vous nutilisez pas le fournisseur server.
# Problèmes connus
## Problèmes avec Chromedriver
Erreur #1:**incompatibilité**
`Exception: Failed to initialize browser: Message: session not created: This version of ChromeDriver only supports Chrome version 113
Current browser version is 134.0.6998.89 with binary path`
Cela se produit sil y a une incompatibilité entre votre navigateur et la version de chromedriver.
Vous devez naviguer pour télécharger la dernière version :
https://developer.chrome.com/docs/chromedriver/downloads
Si vous utilisez Chrome version 115 ou plus récent, allez sur :
https://googlechromelabs.github.io/chrome-for-testing/
Et téléchargez la version de chromedriver correspondant à votre système dexploitation.
![alt text](./media/chromedriver_readme.png)
Si cette section est incomplète, merci de faire une nouvelle issue sur github.
## FAQ
**Q: Quel matériel est nécessaire ?**
| Taille du Modèle | GPU | Commentaire |
|--------------------|------|----------------------------------------------------------|
| 7B | 8 Go VRAM | ⚠️ Non recommandé. Performances médiocres, hallucinations fréquentes, et l'agent planificateur échouera probablement. |
| 14B | 12 Go VRAM (par ex. RTX 3060) | ✅ Utilisable pour des tâches simples. Peut rencontrer des difficultés avec la navigation web et les tâches de planification. |
| 32B | 24+ Go VRAM (par ex. RTX 4090) | 🚀 Réussite avec la plupart des tâches, peut encore avoir des difficultés avec la planification des tâches. |
| 70B+ | 48+ Go VRAM (par ex. Mac Studio) | 💪 Excellent. Recommandé pour des cas d'utilisation avancés. |
**Q: Pourquoi deepseek et pas un autre modèle**
DeepSeek R1 excelle dans le raisonnement et lutilisation doutils pour sa taille. Nous pensons que cest un choix solide pour nos besoins, bien que dautres modèles fonctionnent également (bien que moins bien pour un nombre équivalent de paramètres).
**Q: J'ai une erreur quand je lance le programme, je fait quoi?**
Assurez-vous quOllama est en cours dexécution (ollama serve), que votre config.ini correspond à votre fournisseur, et que les dépendances sont installées. Si cela ne fonctionne pas, nhésitez pas à signaler un problème.
**Q: C'est vraiment 100% local?**
Oui, avec les fournisseurs Ollama, lm-studio ou Server, toute la reconnaissance vocale, le LLM et la synthèse vocale fonctionnent localement. Les options non locales (OpenAI ou autres API) sont facultatives.
**Q: En quoi c'est supérieur à Manus**
Il ne l'est certainement pas, mais nous privilégions lexécution locale et la confidentialité par rapport à une approche basée sur le cloud. Cest une alternative plus accessible et surtout moins cher !
## Contribution
Nous recherchons des développeurs pour améliorer AgenticSeek ! Consultez la section "issues" github ou les discussions.
[![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
[Guide du contributeur](./docs/CONTRIBUTING.md)
## Mainteneurs:
> [Fosowl](https://github.com/Fosowl)
> [steveh8758](https://github.com/steveh8758)
> [antoineVIVIES](https://github.com/antoineVIVIES) | Taipei Time
+570
View File
@@ -0,0 +1,570 @@
# AgenticSeek: プライベートなローカルManus代替
<p align="center">
<img align="center" src="./media/agentic_seek_logo.png" width="300" height="300" alt="Agentic Seek ロゴ">
<p>
[English](./README.md) | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Français](./README_FR.md) | 日本語
*Manus AIの**100%ローカルな代替**となるこの音声対応AIアシスタントは、自律的にウェブを閲覧し、コードを書き、タスクを計画しながら、すべてのデータをあなたのデバイスに保持します。ローカル推論モデルに合わせて調整されており、完全にあなたのハードウェア上で動作するため、完全なプライバシーとクラウドへの依存ゼロを保証します。*
[![AgenticSeekを訪問](https://img.shields.io/static/v1?label=ウェブサイト&message=AgenticSeek&color=blue&style=flat-square)](https://fosowl.github.io/agenticSeek.html) ![ライセンス](https://img.shields.io/badge/license-GPL--3.0-green) [![Discord](https://img.shields.io/badge/Discord-参加する-7289DA?logo=discord&logoColor=white)](https://discord.gg/8hGDaME3TC) [![Twitter](https://img.shields.io/twitter/url/https/twitter.com/fosowl.svg?style=social&label=更新%20%40Fosowl)](https://x.com/Martin993886460) [![GitHubスター](https://img.shields.io/github/stars/Fosowl/agenticSeek?style=social)](https://github.com/Fosowl/agenticSeek/stargazers)
### なぜAgenticSeekなのか?
* 🔒 完全ローカル&プライベート - すべてがあなたのマシン上で実行されます — クラウドなし、データ共有なし。あなたのファイル、会話、検索はプライベートに保たれます。
* 🌐 スマートなウェブブラウジング - AgenticSeekは自分でインターネットを閲覧できます — 検索、読み取り、情報抽出、ウェブフォーム入力 — すべてハンズフリーで。
* 💻 自律型コーディングアシスタント - コードが必要ですか?Python、C、Go、Javaなどでプログラムを書き、デバッグし、実行できます — すべて監視なしで。
* 🧠 スマートエージェント選択 - あなたが尋ねると、タスクに最適なエージェントを自動的に見つけ出します。まるで専門家チームが助けてくれるようです。
* 📋 複雑なタスクの計画と実行 - 旅行計画から複雑なプロジェクトまで — 大きなタスクをステップに分割し、複数のAIエージェントを使って物事を成し遂げることができます。
* 🎙️ 音声対応 - クリーンで高速、未来的な音声と音声認識により、まるでSF映画のパーソナルAIのように話しかけることができます。
### **デモ**
> *agenticSeekプロジェクトを検索し、必要なスキルを学び、その後CV_candidates.zipを開いて、プロジェクトに最も適した候補者を教えてください。*
https://github.com/user-attachments/assets/b8ca60e9-7b3b-4533-840e-08f9ac426316
免責事項:このデモは、表示されるすべてのファイル(例:CV_candidates.zip)を含め、完全に架空のものです。私たちは企業ではなく、候補者ではなくオープンソースの貢献者を求めています。
> 🛠️ **作業中** – 貢献者を募集中です!
## インストール
Chrome Driver、Docker、Python 3.10がインストールされていることを確認してください。
セットアップにはPython 3.10を正確に使用することを強くお勧めします。そうでない場合、依存関係のエラーが発生する可能性があります。
Chromeドライバーに関する問題については、**Chromedriver**セクションを参照してください。
### 1️⃣ **リポジトリのクローンとセットアップ**
```sh
git clone https://github.com/Fosowl/agenticSeek.git
cd agenticSeek
mv .env.example .env
```
### 2 **仮想環境の作成**
```sh
python3 -m venv agentic_seek_env
source agentic_seek_env/bin/activate
# Windowsの場合: agentic_seek_env\Scripts\activate
```
### 3️⃣ **パッケージのインストール**
Python、Dockerとdocker compose、Google Chromeがインストールされていることを確認してください。
Python 3.10.0を推奨します。
**自動インストール(推奨):**
Linux/Macosの場合:
```sh
./install.sh
```
** テキスト読み上げ(TTS)機能で日本語をサポートするには、fugashi(日本語分かち書きライブラリ)をインストールする必要があります:**
** 注意: 日本語のテキスト読み上げ(TTS)機能には多くの依存関係が必要で、問題が発生する可能性があります。mecabrcに関する問題が発生することがあります。現在のところ、この問題を修正する方法が見つかっていません。当面は日本語でのテキスト読み上げ機能を無効にすることをお勧めします。**
必要なライブラリをインストールする場合は以下のコマンドを実行してください:
```
pip3 install --upgrade pyopenjtalk jaconv mojimoji unidic fugashi
pip install unidic-lite
python -m unidic download
```
Windowsの場合:
```sh
./install.bat
```
**手動:**
**注意:どのOSでも、インストールするChromeDriverがインストール済みのChromeバージョンと一致していることを確認してください。`google-chrome --version`を実行してください。Chrome >135の場合の既知の問題を参照してください。**
- *Linux*:
パッケージリストの更新:`sudo apt update`
依存関係のインストール:`sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
Chromeブラウザのバージョンに一致するChromeDriverのインストール:
`sudo apt install -y chromium-chromedriver`
要件のインストール:`pip3 install -r requirements.txt`
- *Macos*:
brewの更新:`brew update`
chromedriverのインストール:`brew install --cask chromedriver`
portaudioのインストール:`brew install portaudio`
pipのアップグレード:`python3 -m pip install --upgrade pip`
wheelのアップグレード:`pip3 install --upgrade setuptools wheel`
要件のインストール:`pip3 install -r requirements.txt`
- *Windows*:
pyreadline3のインストール:`pip install pyreadline3`
portaudioの手動インストール(例:vcpkgまたはビルド済みバイナリ経由)後、実行:`pip install pyaudio`
chromedriverの手動ダウンロードとインストール:https://sites.google.com/chromium.org/driver/getting-started
PATHに含まれるディレクトリにchromedriverを配置します。
要件のインストール:`pip3 install -r requirements.txt`
---
## マシン上でローカルにLLMを実行するためのセットアップ
**少なくともDeepseek 14Bの使用を推奨します。より小さなモデルは、特にウェブブラウジングのタスクで苦労します。**
**ローカルプロバイダーのセットアップ**
ローカルプロバイダーを開始します。例えばollamaの場合:
```sh
ollama serve
```
サポートされているローカルプロバイダーのリストについては、以下を参照してください。
**config.iniの更新**
config.iniファイルを変更して、provider_nameをサポートされているプロバイダーに、provider_modelをプロバイダーがサポートするLLMに設定します。*Qwen*や*Deepseek*などの推論モデルを推奨します。
必要なハードウェアについては、READMEの最後にある**FAQ**を参照してください。
```sh
[MAIN]
is_local = True # ローカルで実行するか、リモートプロバイダーで実行するか。
provider_name = ollama # またはlm-studio、openaiなど。
provider_model = deepseek-r1:14b # ハードウェアに合ったモデルを選択してください
provider_server_address = 127.0.0.1:11434
agent_name = Jarvis # AIの名前
recover_last_session = True # 前のセッションを復元するかどうか
save_session = True # 現在のセッションを記憶するかどうか
speak = True # テキスト読み上げ
listen = False # 音声認識、CLIのみ
work_dir = /Users/mlg/Documents/workspace # AgenticSeekのワークスペース。
jarvis_personality = False # より「Jarvis」らしい性格を使用するかどうか(実験的)
languages = en zh # 言語のリスト、テキスト読み上げはリストの最初の言語にデフォルト設定されます
[BROWSER]
headless_browser = True # ヘッドレスブラウザを使用するかどうか、ウェブインターフェースを使用する場合のみ推奨。
stealth_mode = True # undetected seleniumを使用してブラウザ検出を減らす
```
警告:LM-studioを使用してLLMを実行する場合、provider_nameを`openai`に設定しないでください。`lm-studio`に設定してください。
注意:一部のプロバイダー(例:lm-studio)では、IPの前に`http://`が必要です。例:`http://127.0.0.1:1234`
**ローカルプロバイダーのリスト**
| プロバイダー | ローカル? | 説明 |
|-----------|--------|-----------------------------------------------------------|
| ollama | はい | ollamaをLLMプロバイダーとして使用して、LLMをローカルで簡単に実行します |
| lm-studio | はい | LM studioでLLMをローカル実行します(`provider_name``lm-studio`に設定)|
| openai | はい | openai互換API(例:llama.cppサーバー)を使用します |
次のステップ:[サービスの開始とAgenticSeekの実行](#サービスの開始と実行)
*問題が発生した場合は、**既知の問題**セクションを参照してください*
*ハードウェアがローカルでdeepseekを実行できない場合は、**APIで実行**セクションを参照してください*
*詳細な設定ファイルの説明については、**設定**セクションを参照してください。*
---
## APIで実行するためのセットアップ
`config.ini`で目的のプロバイダーを設定します。APIプロバイダーのリストについては、以下を参照してください。
```sh
[MAIN]
is_local = False
provider_name = google
provider_model = gemini-2.0-flash
provider_server_address = 127.0.0.1:5000 # 関係ありません
```
警告:設定に末尾のスペースがないことを確認してください。
APIキーをエクスポートします:`export <<PROVIDER>>_API_KEY="xxx"`
例:`export TOGETHER_API_KEY="xxxxx"`
**APIプロバイダーのリスト**
| プロバイダー | ローカル? | 説明 |
|-----------|--------|-----------------------------------------------------------|
| openai | 場合による | ChatGPT APIを使用 |
| deepseek-api | いいえ | Deepseek API(非プライベート) |
| huggingface| いいえ | Hugging-Face API(非プライベート) |
| togetherAI | いいえ | together AI APIを使用(非プライベート) |
| google | いいえ | google gemini APIを使用(非プライベート) |
*gpt-4oや他のclosedAIモデルの使用は推奨しません*。ウェブブラウジングやタスク計画のパフォーマンスが悪いです。
また、geminiではコーディング/bashが失敗する可能性があることに注意してください。deepseek r1用に最適化されたフォーマットのプロンプトを無視するようです。
次のステップ:[サービスの開始とAgenticSeekの実行](#サービスの開始と実行)
*問題が発生した場合は、**既知の問題**セクションを参照してください*
*詳細な設定ファイルの説明については、**設定**セクションを参照してください。*
---
## サービスの開始と実行
必要に応じてPython環境をアクティブ化します。
```sh
source agentic_seek_env/bin/activate
```
必要なサービスを開始します。これにより、docker-compose.ymlからすべてのサービスが開始されます。これには以下が含まれます:
- searxng
- redissearxngに必要)
- frontend
```sh
sudo ./start_services.sh # MacOS
start ./start_services.cmd # Window
```
**オプション1** CLIインターフェースで実行します。
```sh
python3 cli.py
```
CLIモードでは、config.iniで`headless_browser`をFalseに設定することをお勧めします。
**オプション2** Webインターフェースで実行します。
バックエンドを開始します。
```sh
python3 api.py
```
`http://localhost:3000/`にアクセスすると、Webインターフェースが表示されます。
---
## 使用方法
`./start_services.sh`でサービスが起動していることを確認し、CLIモードの場合は`python3 cli.py`で、Webインターフェースの場合は`python3 api.py`を実行してから`localhost:3000`にアクセスしてAgenticSeekを実行します。
設定で`listen = True`を設定することで、音声認識を使用することもできます。CLIモードのみ。
終了するには、単に`goodbye`と発言/入力します。
以下に使用例をいくつか示します:
> *Pythonでスネークゲームを作って!*
> *フランスのレンヌでトップのカフェをウェブ検索し、3つのカフェのリストとその住所をrennes_cafes.txtに保存して。*
> *数値の階乗を計算するGoプログラムを書いて、それをfactorial.goとしてワークスペースに保存して。*
> *summer_picturesフォルダ内のすべてのJPGファイルを検索し、今日の日付で名前を変更し、名前変更されたファイルのリストをphotos_list.txtに保存して。*
> *2024年の人気のSF映画をオンラインで検索し、今夜観る映画を3つ選んで。リストをmovie_night.txtに保存して。*
> *2025年の最新AIニュース記事をウェブで検索し、3つ選択して、それらのタイトルと要約をスクレイピングするPythonスクリプトを書いて。スクリプトをnews_scraper.pyとして、要約を/home/projectsのai_news.txtに保存して。*
> *金曜日、無料の株価APIをウェブで検索し、supersuper7434567@gmail.comで登録し、そのAPIを使用してテスラの日々の価格を取得するPythonスクリプトを書いて、結果をstock_prices.csvに保存して。*
*フォーム入力機能はまだ実験的であり、失敗する可能性があることに注意してください。*
クエリを入力すると、AgenticSeekはタスクに最適なエージェントを割り当てます。
これは初期のプロトタイプであるため、エージェントルーティングシステムがクエリに基づいて常に適切なエージェントを割り当てるとは限りません。
したがって、何をしたいのか、AIがどのように進むべきかについて非常に明確にする必要があります。たとえば、ウェブ検索を実行させたい場合は、次のように言わないでください:
`一人旅に適した良い国を知っていますか?`
代わりに、次のように尋ねてください:
`ウェブ検索をして、一人旅に最適な国を見つけてください`
---
## **独自のサーバーでLLMを実行するためのセットアップ**
強力なコンピューターまたは使用できるサーバーがあるが、ラップトップから使用したい場合は、カスタムLLMサーバーを使用してリモートサーバーでLLMを実行するオプションがあります。
AIモデルを実行する「サーバー」で、IPアドレスを取得します。
```sh
ip a | grep "inet " | grep -v 127.0.0.1 | awk '{print $2}' | cut -d/ -f1 # ローカルIP
curl https://ipinfo.io/ip # パブリックIP
```
注意:WindowsまたはmacOSの場合、それぞれipconfigまたはifconfigを使用してIPアドレスを見つけます。
リポジトリをクローンし、`server/`フォルダに入ります。
```sh
git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/server/
```
サーバー固有の要件をインストールします:
```sh
pip3 install -r requirements.txt
```
サーバー スクリプトを実行します。
```sh
python3 app.py --provider ollama --port 3333
```
LLMサービスとして`ollama``llamacpp`のどちらかを選択できます。
次に、個人のコンピュータで:
`config.ini`ファイルを変更して、`provider_name``server`に、`provider_model``deepseek-r1:xxb`に設定します。
`provider_server_address`をモデルを実行するマシンのIPアドレスに設定します。
```sh
[MAIN]
is_local = False
provider_name = server
provider_model = deepseek-r1:70b
provider_server_address = x.x.x.x:3333
```
次のステップ:[サービスの開始とAgenticSeekの実行](#サービスの開始と実行)
---
## 音声認識
現在、音声認識は英語でのみ機能することに注意してください。
音声認識機能はデフォルトで無効になっています。有効にするには、config.iniファイルでlistenオプションをTrueに設定します:
```
listen = True
```
有効にすると、音声認識機能は、入力を処理し始める前にトリガーキーワード(エージェントの名前)をリッスンします。*config.ini*ファイルで`agent_name`の値を更新することで、エージェントの名前をカスタマイズできます:
```
agent_name = Friday
```
最適な認識のためには、エージェント名として「John」や「Emma」のような一般的な英語の名前を使用することをお勧めします。
トランスクリプトが表示され始めたら、エージェントの名前を声に出して起動します(例:「Friday」)。
クエリをはっきりと話します。
システムに処理を進めるよう合図するために、確認フレーズでリクエストを終了します。確認フレーズの例は次のとおりです:
```
"do it", "go ahead", "execute", "run", "start", "thanks", "would ya", "please", "okay?", "proceed", "continue", "go on", "do that", "go it", "do you understand?"
```
## 設定
設定例:
```
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:32b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = False
save_session = False
speak = False
listen = False
work_dir = /Users/mlg/Documents/ai_folder
jarvis_personality = False
languages = en zh
[BROWSER]
headless_browser = False
stealth_mode = False
```
**説明**:
- is_local -> エージェントをローカルで実行する(True)か、リモートサーバーで実行する(False)か。
- provider_name -> 使用するプロバイダー(`ollama``server``lm-studio``deepseek-api`のいずれか)
- provider_model -> 使用するモデル、例:deepseek-r1:32b。
- provider_server_address -> サーバーアドレス、例:ローカルの場合は127.0.0.1:11434。非ローカルAPIの場合は何でも設定します。
- agent_name -> エージェントの名前、例:Friday。TTSのトリガーワードとして使用されます。
- recover_last_session -> 前回のセッションから再開する(True)かしない(False)か。
- save_session -> セッションデータを保存する(True)かしない(False)か。
- speak -> 音声出力を有効にする(True)かしない(False)か。
- listen -> 音声入力をリッスンする(True)かしない(False)か。
- work_dir -> AIがアクセスできるフォルダ。例:/Users/user/Documents/。
- jarvis_personality -> JARVISのような性格を使用する(True)かしない(False)か。これは単にプロンプトファイルを変更します。
- languages -> サポートされている言語のリスト。LLMルーターが正しく機能するために必要です。あまりにも多くの言語や類似した言語を入れすぎないようにしてください。
- headless_browser -> 表示ウィンドウなしでブラウザを実行する(True)かしない(False)か。
- stealth_mode -> ボット検出を困難にします。唯一の欠点は、anticaptcha拡張機能を手動でインストールする必要があることです。
- languages -> サポートされている言語のリスト。エージェントルーティングシステムに必要です。言語リストが長いほど、ダウンロードされるモデルが多くなります。
## プロバイダー
以下の表は、利用可能なプロバイダーを示しています:
| プロバイダー | ローカル? | 説明 |
|-----------|--------|-----------------------------------------------------------|
| ollama | はい | ollamaをLLMプロバイダーとして使用して、LLMをローカルで簡単に実行します |
| server | はい | モデルを別のマシンでホストし、ローカルマシンで実行します |
| lm-studio | はい | LM studioでLLMをローカル実行します(`lm-studio` |
| openai | 場合による | ChatGPT API(非プライベート)またはopenai互換APIを使用 |
| deepseek-api | いいえ | Deepseek API(非プライベート) |
| huggingface| いいえ | Hugging-Face API(非プライベート) |
| togetherAI | いいえ | together AI APIを使用(非プライベート) |
| google | いいえ | google gemini APIを使用(非プライベート) |
プロバイダーを選択するには、config.iniを変更します:
```
is_local = True
provider_name = ollama
provider_model = deepseek-r1:32b
provider_server_address = 127.0.0.1:5000
```
`is_local`: ローカルで実行されるLLMの場合はTrue、それ以外の場合はFalseである必要があります。
`provider_name`: 使用するプロバイダーを名前で選択します。上記のプロバイダーリストを参照してください。
`provider_model`: エージェントが使用するモデルを設定します。
`provider_server_address`: サーバーアドレス。APIプロバイダーには使用されません。
# 既知の問題
## Chromedriverの問題
**既知のエラー #1:** *chromedriverの不一致*
`Exception: Failed to initialize browser: Message: session not created: This version of ChromeDriver only supports Chrome version 113
Current browser version is 134.0.6998.89 with binary path`
これは、ブラウザとchromedriverのバージョンが一致しない場合に発生します。
最新バージョンをダウンロードするためにナビゲートする必要があります:
https://developer.chrome.com/docs/chromedriver/downloads
Chromeバージョン115以降を使用している場合は、以下にアクセスしてください:
https://googlechromelabs.github.io/chrome-for-testing/
そして、OSに一致するchromedriverバージョンをダウンロードします。
![代替テキスト](./media/chromedriver_readme.png)
このセクションが不完全な場合は、問題を提起してください。
## 接続アダプタの問題
```
Exception: Provider lm-studio failed: HTTP request failed: No connection adapters were found for '127.0.0.1:11434/v1/chat/completions'
```
プロバイダーのIPアドレスの前に`http://`があることを確認してください:
`provider_server_address = http://127.0.0.1:11434`
## SearxNGのベースURLを指定する必要があります
```
raise ValueError("SearxNG base URL must be provided either as an argument or via the SEARXNG_BASE_URL environment variable.")
ValueError: SearxNG base URL must be provided either as an argument or via the SEARXNG_BASE_URL environment variable.
```
`.env.example``.env`として移動しなかった可能性がありますか?SEARXNG_BASE_URLをエクスポートすることもできます:
`export SEARXNG_BASE_URL="http://127.0.0.1:8080"`
## FAQ
**Q: どのようなハードウェアが必要ですか?**
| モデルサイズ | GPU | コメント |
|-----------|------------|--------------------------------------------------------------------------|
| 7B | 8GB VRAM | ⚠️ 非推奨。パフォーマンスが悪く、幻覚が頻繁に発生し、プランナーエージェントは失敗する可能性が高いです。 |
| 14B | 12GB VRAM(例:RTX 3060) | ✅ 簡単なタスクには使用可能。ウェブブラウジングや計画タスクで苦労する可能性があります。 |
| 32B | 24GB以上のVRAM(例:RTX 4090) | 🚀 ほとんどのタスクで成功しますが、タスク計画でまだ苦労する可能性があります。 |
| 70B+ | 48GB以上のVRAM(例:mac studio) | 💪 素晴らしい。高度なユースケースに推奨されます。 |
**Q: なぜ他のモデルではなくDeepseek R1なのですか?**
Deepseek R1は、そのサイズに対して推論とツール使用に優れています。私たちのニーズに合っていると考えており、他のモデルも正常に動作しますが、Deepseekが私たちの主要な選択肢です。
**Q: `cli.py`を実行するとエラーが発生します。どうすればよいですか?**
ローカルが実行されていること(`ollama serve`)、`config.ini`がプロバイダーと一致していること、依存関係がインストールされていることを確認してください。それでも解決しない場合は、遠慮なく問題を提起してください。
**Q: 本当に100%ローカルで実行できますか?**
はい、Ollama、lm-studio、またはサーバープロバイダーを使用すると、すべての音声認識、LLM、テキスト読み上げモデルがローカルで実行されます。非ローカルオプション(OpenAIまたはその他のAPI)はオプションです。
**Q: Manusがあるのに、なぜAgenticSeekを使うべきなのですか?**
これは、AIエージェントへの関心から始めたサイドプロジェクトです。特別なのは、ローカルモデルを使用し、APIを避けたいということです。
私たちはJarvisとFriday(アイアンマン映画)からインスピレーションを得て「クール」にしましたが、機能性についてはManusからより多くのインスピレーションを得ています。なぜなら、それが人々が最初に望むもの、つまりローカルなManusの代替だからです。
Manusとは異なり、AgenticSeekは外部システムからの独立性を優先し、より多くの制御、プライバシーを提供し、APIコストを回避します。
## 貢献する
AgenticSeekを改善するための開発者を募集しています!オープンな問題やディスカッションを確認してください。
[貢献ガイド](./docs/CONTRIBUTING.md)
[![スター履歴チャート](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
## メンテナー:
> [Fosowl](https://github.com/Fosowl) | パリ時間
> [antoineVIVIES](https://github.com/antoineVIVIES) | Taipei Time
> [steveh8758](https://github.com/steveh8758) | 台北時間 |(常に忙しい)
Executable
+250
View File
@@ -0,0 +1,250 @@
#!/usr/bin/env python3
import os, sys
import uvicorn
import aiofiles
import configparser
import asyncio
import time
from typing import List
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import uuid
from sources.llm_provider import Provider
from sources.interaction import Interaction
from sources.agents import CasualAgent, CoderAgent, FileAgent, PlannerAgent, BrowserAgent
from sources.browser import Browser, create_driver
from sources.utility import pretty_print
from sources.logger import Logger
from sources.schemas import QueryRequest, QueryResponse
from celery import Celery
api = FastAPI(title="AgenticSeek API", version="0.1.0")
celery_app = Celery("tasks", broker="redis://localhost:6379/0", backend="redis://localhost:6379/0")
celery_app.conf.update(task_track_started=True)
logger = Logger("backend.log")
config = configparser.ConfigParser()
config.read('config.ini')
api.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost", "http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
if not os.path.exists(".screenshots"):
os.makedirs(".screenshots")
api.mount("/screenshots", StaticFiles(directory=".screenshots"), name="screenshots")
def initialize_system():
stealth_mode = config.getboolean('BROWSER', 'stealth_mode')
personality_folder = "jarvis" if config.getboolean('MAIN', 'jarvis_personality') else "base"
languages = config["MAIN"]["languages"].split(' ')
provider = Provider(
provider_name=config["MAIN"]["provider_name"],
model=config["MAIN"]["provider_model"],
server_address=config["MAIN"]["provider_server_address"],
is_local=config.getboolean('MAIN', 'is_local')
)
logger.info(f"Provider initialized: {provider.provider_name} ({provider.model})")
browser = Browser(
create_driver(headless=config.getboolean('BROWSER', 'headless_browser'), stealth_mode=stealth_mode, lang=languages[0]),
anticaptcha_manual_install=stealth_mode
)
logger.info("Browser initialized")
agents = [
CasualAgent(
name=config["MAIN"]["agent_name"],
prompt_path=f"prompts/{personality_folder}/casual_agent.txt",
provider=provider, verbose=False
),
CoderAgent(
name="coder",
prompt_path=f"prompts/{personality_folder}/coder_agent.txt",
provider=provider, verbose=False
),
FileAgent(
name="File Agent",
prompt_path=f"prompts/{personality_folder}/file_agent.txt",
provider=provider, verbose=False
),
BrowserAgent(
name="Browser",
prompt_path=f"prompts/{personality_folder}/browser_agent.txt",
provider=provider, verbose=False, browser=browser
),
PlannerAgent(
name="Planner",
prompt_path=f"prompts/{personality_folder}/planner_agent.txt",
provider=provider, verbose=False, browser=browser
)
]
logger.info("Agents initialized")
interaction = Interaction(
agents,
tts_enabled=config.getboolean('MAIN', 'speak'),
stt_enabled=config.getboolean('MAIN', 'listen'),
recover_last_session=config.getboolean('MAIN', 'recover_last_session'),
langs=languages
)
logger.info("Interaction initialized")
return interaction
interaction = initialize_system()
is_generating = False
query_resp_history = []
@api.get("/screenshot")
async def get_screenshot():
logger.info("Screenshot endpoint called")
screenshot_path = ".screenshots/updated_screen.png"
if os.path.exists(screenshot_path):
return FileResponse(screenshot_path)
logger.error("No screenshot available")
return JSONResponse(
status_code=404,
content={"error": "No screenshot available"}
)
@api.get("/health")
async def health_check():
logger.info("Health check endpoint called")
return {"status": "healthy", "version": "0.1.0"}
@api.get("/is_active")
async def is_active():
logger.info("Is active endpoint called")
return {"is_active": interaction.is_active}
@api.get("/stop")
async def stop():
logger.info("Stop endpoint called")
interaction.current_agent.request_stop()
return JSONResponse(status_code=200, content={"status": "stopped"})
@api.get("/latest_answer")
async def get_latest_answer():
global query_resp_history
if interaction.current_agent is None:
return JSONResponse(status_code=404, content={"error": "No agent available"})
uid = str(uuid.uuid4())
if not any(q["answer"] == interaction.current_agent.last_answer for q in query_resp_history):
query_resp = {
"done": "false",
"answer": interaction.current_agent.last_answer,
"reasoning": interaction.current_agent.last_reasoning,
"agent_name": interaction.current_agent.agent_name if interaction.current_agent else "None",
"success": interaction.current_agent.success,
"blocks": {f'{i}': block.jsonify() for i, block in enumerate(interaction.get_last_blocks_result())} if interaction.current_agent else {},
"status": interaction.current_agent.get_status_message if interaction.current_agent else "No status available",
"uid": uid
}
interaction.current_agent.last_answer = ""
interaction.current_agent.last_reasoning = ""
query_resp_history.append(query_resp)
return JSONResponse(status_code=200, content=query_resp)
if query_resp_history:
return JSONResponse(status_code=200, content=query_resp_history[-1])
return JSONResponse(status_code=404, content={"error": "No answer available"})
async def think_wrapper(interaction, query):
try:
interaction.last_query = query
logger.info("Agents request is being processed")
success = await interaction.think()
if not success:
interaction.last_answer = "Error: No answer from agent"
interaction.last_reasoning = "Error: No reasoning from agent"
interaction.last_success = False
else:
interaction.last_success = True
pretty_print(interaction.last_answer)
interaction.speak_answer()
return success
except Exception as e:
logger.error(f"Error in think_wrapper: {str(e)}")
interaction.last_answer = f""
interaction.last_reasoning = f"Error: {str(e)}"
interaction.last_success = False
raise e
@api.post("/query", response_model=QueryResponse)
async def process_query(request: QueryRequest):
global is_generating, query_resp_history
logger.info(f"Processing query: {request.query}")
query_resp = QueryResponse(
done="false",
answer="",
reasoning="",
agent_name="Unknown",
success="false",
blocks={},
status="Ready",
uid=str(uuid.uuid4())
)
if is_generating:
logger.warning("Another query is being processed, please wait.")
return JSONResponse(status_code=429, content=query_resp.jsonify())
try:
is_generating = True
success = await think_wrapper(interaction, request.query)
is_generating = False
if not success:
query_resp.answer = interaction.last_answer
query_resp.reasoning = interaction.last_reasoning
return JSONResponse(status_code=400, content=query_resp.jsonify())
if interaction.current_agent:
blocks_json = {f'{i}': block.jsonify() for i, block in enumerate(interaction.current_agent.get_blocks_result())}
else:
logger.error("No current agent found")
blocks_json = {}
query_resp.answer = "Error: No current agent"
return JSONResponse(status_code=400, content=query_resp.jsonify())
logger.info(f"Answer: {interaction.last_answer}")
logger.info(f"Blocks: {blocks_json}")
query_resp.done = "true"
query_resp.answer = interaction.last_answer
query_resp.reasoning = interaction.last_reasoning
query_resp.agent_name = interaction.current_agent.agent_name
query_resp.success = str(interaction.last_success)
query_resp.blocks = blocks_json
query_resp_dict = {
"done": query_resp.done,
"answer": query_resp.answer,
"agent_name": query_resp.agent_name,
"success": query_resp.success,
"blocks": query_resp.blocks,
"status": query_resp.status,
"uid": query_resp.uid
}
query_resp_history.append(query_resp_dict)
logger.info("Query processed successfully")
return JSONResponse(status_code=200, content=query_resp.jsonify())
except Exception as e:
logger.error(f"An error occurred: {str(e)}")
sys.exit(1)
finally:
logger.info("Processing finished")
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
if __name__ == "__main__":
uvicorn.run(api, host="0.0.0.0", port=8000)
Executable
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin python3
import sys
import argparse
import configparser
import asyncio
from sources.llm_provider import Provider
from sources.interaction import Interaction
from sources.agents import Agent, CoderAgent, CasualAgent, FileAgent, PlannerAgent, BrowserAgent, McpAgent
from sources.browser import Browser, create_driver
from sources.utility import pretty_print
import warnings
warnings.filterwarnings("ignore")
config = configparser.ConfigParser()
config.read('config.ini')
async def main():
pretty_print("Initializing...", color="status")
stealth_mode = config.getboolean('BROWSER', 'stealth_mode')
personality_folder = "jarvis" if config.getboolean('MAIN', 'jarvis_personality') else "base"
languages = config["MAIN"]["languages"].split(' ')
provider = Provider(provider_name=config["MAIN"]["provider_name"],
model=config["MAIN"]["provider_model"],
server_address=config["MAIN"]["provider_server_address"],
is_local=config.getboolean('MAIN', 'is_local'))
browser = Browser(
create_driver(headless=config.getboolean('BROWSER', 'headless_browser'), stealth_mode=stealth_mode, lang=languages[0]),
anticaptcha_manual_install=stealth_mode
)
agents = [
CasualAgent(name=config["MAIN"]["agent_name"],
prompt_path=f"prompts/{personality_folder}/casual_agent.txt",
provider=provider, verbose=False),
CoderAgent(name="coder",
prompt_path=f"prompts/{personality_folder}/coder_agent.txt",
provider=provider, verbose=False),
FileAgent(name="File Agent",
prompt_path=f"prompts/{personality_folder}/file_agent.txt",
provider=provider, verbose=False),
BrowserAgent(name="Browser",
prompt_path=f"prompts/{personality_folder}/browser_agent.txt",
provider=provider, verbose=False, browser=browser),
PlannerAgent(name="Planner",
prompt_path=f"prompts/{personality_folder}/planner_agent.txt",
provider=provider, verbose=False, browser=browser),
#McpAgent(name="MCP Agent",
# prompt_path=f"prompts/{personality_folder}/mcp_agent.txt",
# provider=provider, verbose=False), # NOTE under development
]
interaction = Interaction(agents,
tts_enabled=config.getboolean('MAIN', 'speak'),
stt_enabled=config.getboolean('MAIN', 'listen'),
recover_last_session=config.getboolean('MAIN', 'recover_last_session'),
langs=languages
)
try:
while interaction.is_active:
interaction.get_user()
if await interaction.think():
interaction.show_answer()
interaction.speak_answer()
except Exception as e:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
raise e
finally:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
if __name__ == "__main__":
asyncio.run(main())
+9 -4
View File
@@ -3,9 +3,14 @@ is_local = True
provider_name = ollama provider_name = ollama
provider_model = deepseek-r1:14b provider_model = deepseek-r1:14b
provider_server_address = 127.0.0.1:11434 provider_server_address = 127.0.0.1:11434
agent_name = Friday agent_name = Name_of_your_AI
recover_last_session = True recover_last_session = False
save_session = False save_session = False
speak = True speak = False
listen = False listen = False
work_dir = /Users/mlg/Documents/ai_workplace work_dir = /Users/mlg/Documents/workspace_for_agenticseek
jarvis_personality = False
languages = en
[BROWSER]
headless_browser = True
stealth_mode = False
BIN
View File
Binary file not shown.
+105
View File
@@ -0,0 +1,105 @@
version: '3'
services:
redis:
container_name: redis
image: docker.io/valkey/valkey:8-alpine
command: valkey-server --save 30 1 --loglevel warning
restart: unless-stopped
volumes:
- redis-data:/data
cap_drop:
- ALL
cap_add:
- SETGID
- SETUID
- DAC_OVERRIDE
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
networks:
- agentic-seek-net
searxng:
container_name: searxng
image: docker.io/searxng/searxng:latest
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./searxng:/etc/searxng:rw
environment:
- SEARXNG_BASE_URL=http://localhost:8080/
- SEARXNG_SECRET_KEY=$(openssl rand -hex 32)
- UWSGI_WORKERS=4
- UWSGI_THREADS=4
cap_add:
- CHOWN
- SETGID
- SETUID
logging:
driver: "json-file"
options:
max-size: "1m"
max-file: "1"
depends_on:
- redis
networks:
- agentic-seek-net
frontend:
container_name: frontend
build:
context: ./frontend
dockerfile: Dockerfile.frontend
ports:
- "3000:3000"
volumes:
- ./frontend/agentic-seek-front/src:/app/src
- ./screenshots:/app/screenshots
environment:
- NODE_ENV=development
- CHOKIDAR_USEPOLLING=true
- BACKEND_URL=http://backend:8000
networks:
- agentic-seek-net
# NOTE: backend service is not working yet due to issue with chromedriver on docker.
# Therefore backend is run on host machine.
# Open to pull requests to fix this.
#backend:
# container_name: backend
# build:
# context: ./
# dockerfile: Dockerfile.backend
# stdin_open: true
# tty: true
# shm_size: 8g
# ports:
# - "8000:8000"
# volumes:
# - ./:/app
# environment:
# - NODE_ENV=development
# - REDIS_URL=redis://redis:6379/0
# - SEARXNG_URL=http://searxng:8080
# - OLLAMA_URL=http://localhost:11434
# - LM_STUDIO_URL=http://localhost:1234
# extra_hosts:
# - "host.docker.internal:host-gateway"
# depends_on:
# - redis
# - searxng
# networks:
# - agentic-seek-net
volumes:
redis-data:
chrome_profiles:
networks:
agentic-seek-net:
driver: bridge
+29 -25
View File
@@ -6,8 +6,8 @@ We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status, identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity nationality, personal appearance, race, caste, color, religion, or sexual
and orientation. identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community. diverse, inclusive, and healthy community.
@@ -22,17 +22,17 @@ community include:
* Giving and gracefully accepting constructive feedback * Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes, * Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience and learning from the experience
* Focusing on what is best not just for us as individuals, but for the * Focusing on what is best not just for us as individuals, but for the overall
overall community community
Examples of unacceptable behavior include: Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or * The use of sexualized language or imagery, and sexual attention or advances of
advances of any kind any kind
* Trolling, insulting or derogatory comments, and personal or political attacks * Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment * Public or private harassment
* Publishing others' private information, such as a physical or email * Publishing others' private information, such as a physical or email address,
address, without their explicit permission without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a * Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
@@ -52,15 +52,15 @@ decisions when appropriate.
This Code of Conduct applies within all community spaces, and also applies when This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces. an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address, Examples of representing our community include using an official email address,
posting via an official social media account, or acting as an appointed posting via an official social media account, or acting as an appointed
representative at an online or offline event. representative at an online or offline event.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement:
. you need to send a private message to `fossowl` or `mow8758` on discord.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the
@@ -82,15 +82,15 @@ behavior was inappropriate. A public apology may be requested.
### 2. Warning ### 2. Warning
**Community Impact**: A violation through a single incident or series **Community Impact**: A violation through a single incident or series of
of actions. actions.
**Consequence**: A warning with consequences for continued behavior. No **Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or like social media. Violating these terms may lead to a temporary or permanent
permanent ban. ban.
### 3. Temporary Ban ### 3. Temporary Ban
@@ -109,20 +109,24 @@ Violating these terms may lead to a permanent ban.
standards, including sustained inappropriate behavior, harassment of an standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals. individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within **Consequence**: A permanent ban from any sort of public interaction within the
the community. community.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at version 2.1, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by [Mozilla's code of conduct Community Impact Guidelines were inspired by
enforcement ladder](https://github.com/mozilla/diversity). [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
https://www.contributor-covenant.org/translations. [https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
+297
View File
@@ -0,0 +1,297 @@
# Contributors guide
## Prerequisites
- Python 3.10 or higher.
- Docker or Orbstack or Podman.
- Ollama with some deepseek-r1 variant installed or similar local reasoning model.
- Basic familiarity with Python and AI models.
- Join the discord (optional): https://discord.gg/8hGDaME3TC
## Contribution Guidelines
We welcome contributions in the following areas:
- Code Improvements: Optimize existing code, fix bugs, or add new features.
- Documentation: Improve the README, write tutorials, or add inline comments.
- Testing: Write unit tests, integration tests, or help with debugging.
- New Features: Implement new tools, agents, or integrations.
## Steps to Contribute
Fork the project to your GitHub account.
Create a Branch:
```bash
git checkout -b feature/your-feature-name
```
Make Your Changes.
Write your code, add documentation, or fix bugs.
Test Your Changes.
Ensure your changes work as expected and do not break existing functionality.
Push your changes to your fork and submit a pull request to the main branch of this repository. Provide a clear description of your changes and reference any related issues.
## Good practice
1. **Privacy First, Always Local**
- All core functionality must be able to run 100% locally
- Cloud services should only be optional alternatives, clearly defined with a warning message.
- remote APIs are only allowed for specific tools (weather api, MCP, flight search, etc...)
- User data privacy is non-negotiable
2. **Agent-Based Architecture**
- Each agent should have a clear, single responsibility
- Agents should be modular and independently testable
- New agents should solve specific use cases
3. **Tool-Based Extensibility**
- Tools should be self-contained and follow the Tools base class
- Each tool should do one thing well
- Tools should provide clear feedback on success/failure
4. **User Experience**
- Provide meaningful feedback for all operations
- Support multiple languages
- Text to speech with short response.
- Keep responses concise
5. **Code Quality**
- Write clear, self-documenting code
- Include type hints and docstrings
- Follow existing patterns in the codebase
- Add a if __name__ == "__main__" at the bottom of each class file for individual testing.
- Ideally had automated tests.
6. **Error Handling**
- Fail gracefully with meaningful messages
- Include recovery mechanisms where possible
- Log errors appropriately without exposing sensitive data
## Areas Needing Help
Here are some tasks and areas where we need contributions:
- Web Browsing: Improve the autonomous web browsing capabilities for the assistant.
- Graphical interface, a web graphical interface. (please ask first)
- Multi-Agent System: Enhance the planner agent for divide and conqueer for task (please ask first).
- New Tools: Add support for additional programming languages or APIs.
- MCP: Add MCP protocol compatibility (possibly as a special type tool).
- Multi-language support: for Text to speech & speech to text
- Prompt engineering: improve prompts, compare results with different prompts for a identical query. Iterate until you find better prompt.
- Bug hunt: Hunt and fix bugs.
- Crossplatform: enhance cross-platform support.
- Testing: Write comprehensive tests for existing features.
# Implementing and using Tools
Tools are extensions that enable agents to perform specific actions, such as running Python code, making API calls, or conducting web searches. All tools inherit from the Tools base class, which provides methods for parsing and executing tool instructions.
## Tools parsing
Agents invoke tools using a standardized format called a block. A block consists of the tool name followed by the content (e.g., code, query, or parameters) to execute. The format looks like this:
BECAUSE WE USE MARKDOWN QUOTE FORMAT, READING WILL BE BROKEN ON GITHUB PLEASE START READING THE FILE AS RAW: https://raw.githubusercontent.com/Fosowl/agenticSeek/refs/heads/main/CONTRIBUTING.md
```<tool name>
<code or query to execute>
```
Or:
```web_search
What to do in Taipei?
```
we call these "blocks".
The Tools class provides the load_exec_block method to extract and parse blocks from an agent's response. This method identifies the tool name and content, enabling the system to execute the appropriate action.
How to handle multiple arguments then ?
Good question! Each tool is free to handle argument in it's own way within the block, but we provide a common parsing logic:
```flight_search
from=Paris
to=Taipei
date=30/04/2026
```
To extract these parameters, use the `get_parameter_value` method provided by the Tools class. Each tool can define its own parameter-handling logic, but the Tools class ensures consistent parsing.
Again if a tool need a specific format, you could implement a specific method for parsing a block. Using get_parameter_value is optional.
The content of blocks can also be saved using :path, for instance:
```python:toto.py
print("Hello world")
```
Will save the code in toto.py file within the work_folder defined in the config.ini
## Execution
When developing a tool, you must implement three abstract methods defined in the Tools class to handle execution, failure detection, and feedback to the agent. These methods ensure consistent behavior across tools and enable robust interaction with the LLM.
### 1. Execute method
```
@abstractmethod
def execute(self, blocks: [str], safety: bool) -> str:
```
This method defines how the tool processes the provided block(s) and produces a result.
### 2. execution_failure_check
```
@abstractmethod
def execution_failure_check(self, output: str) -> bool:
```
This method analyzes the tools output to determine if the execution was successful or failed.
### 3. interpreter_feedback
```
@abstractmethod
def interpreter_feedback(self, output: str) -> str:
```
This method generates a feedback message for the LLM, helping it understand the tools execution outcome and adjust its behavior if needed.
Recap:
- load_exec_block: Extracts and parses tool blocks from the agent's response.
- get_parameter_value: Retrieves parameter values from a block's content.
- File handling: Supports saving block content to files when a :path is specified.
# Implementing and using Agents
Agents are classes that define how an LLM interacts with users and processes inputs. They can use tools (e.g., for executing code or querying APIs) and maintain a memory of the conversation to provide context-aware responses. All agents inherit from the base Agent class, which provides core functionality like memory management and LLM communication.
The simplest agent example is the casual agent:
```
class CasualAgent(Agent):
def __init__(self, name, prompt_path, provider, verbose=False):
"""
The casual agent is a special for casual talk to the user without specific tasks.
"""
super().__init__(name, prompt_path, provider, verbose, None)
self.tools = {
} # No tools for the casual agent
self.role = "en"
self.type = "casual_agent"
def process(self, prompt, speech_module) -> str:
self.memory.push('user', prompt)
animate_thinking("Thinking...", color="status")
answer, reasoning = self.llm_request()
self.last_answer = answer
return answer, reasoning
```
Agent have several parameters that should be sets:
`tools`: A dictionary of tools the agent can use. Each tool must inherit from the Tools class. For example, a CasualAgent has no tools ({}), while a coding agent might include a Python execution tool.
`role`:A dictionary defining the agent's role, used by the routing system to select the appropriate agent.
`type: the agent type, a fixed name to identify the unique agent type.
Every agent must implement the process method, which defines how it handles user input and generates a response.
**Workflow:**
Push the user's prompt to the agent's memory using self.memory.push('user', prompt).
Call self.llm_request() to generate a response and reasoning based on the memory context.
Store and return the response and reasoning.
Note the memory logic. You only need to push the 'user' message. The llm_request method take care of pushing the assistant message.
This separation of user and assistant memory handling may be inconsistent and could be refactored for clarity in the near future.
**Tool blocks execution**
Each agent might return block of tool to execute, as explained in the **Implementing and using Tools** section.
In a single text returned by an agent, a succession of block might be present for example, the coding agent answer could be:
I will create a work folder:
```bash
mkdir myAGI
```
I will enter the folder.
```bash
cd myAGI
```
I will create a python code.
```python:myAGI/super_smart.py
<python code>
```
The `execute_modules` method allow to automatically find, parse and execute all tools from a LLM prompt.
It will look in the agent answer for any tool "block" execute the appropriate tool and return a (success, feedback) tuple.
```
def execute_modules(self, answer: str) -> Tuple[bool, str]:
```
# Architecture Overview
## 1. Agent selection logic
<p align="center">
<img align="center" src="./technical/routing_system.png">
<p>
The agent selection is done in 4 steps:
1. determine query language and translate to english for the zero-shot model and llm_router.
2. Estimate the task complexity and best agent.
- If HIGH complexity: return the planner agent.
- If LOW complexity: Determine the best agent for the task using a vote system between 2 classification models.
3. Process high complexity query.
- If task was high complexity, planner agent will create a json plan to divide and conqueer the task with multiple agent.
4. Proceed with task(s)
## 2. Agents
### File/Code agents
<p align="center">
<img align="center" src="./technical/code_agent.png">
<p>
The File and Code agents operate similarly: when a prompt is submitted, they initiate a loop between the LLM and a code interpreter. This loop continues executing commands or code until the execution is successful or the maximum number of attempts is reached.
### Web agent
<p align="center">
<img align="center" src="./technical/web_agent.png">
<p>
The Web agent controls a Selenium-driven browser. Upon receiving a query, it begins by generating an optimized search prompt and executing the web_search tool. It then enters a navigation loop, during which it:
- Analyzes the content and interactive elements of the current page.
- Decides which link to follow, either from the current page or the web_search results.
- Determines if it should navigate back if so, it re-evaluates the original web_search results.
- Identifies and interacts with web forms, extracting or filling them as needed.
- Signals completion by requesting to exit once it considers the task fulfilled.
## Code of Conduct
See CODE_OF_CONDUCT.md
**Thank You!**
Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 482 KiB

+23
View File
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+16
View File
@@ -0,0 +1,16 @@
FROM node:18
WORKDIR /app
# Install dependencies
COPY agentic-seek-front/package.json agentic-seek-front/package-lock.json ./
RUN npm install
# Copy application code
COPY agentic-seek-front/ .
# Expose port
EXPOSE 3000
# Run the application
CMD ["npm", "start"]
+70
View File
@@ -0,0 +1,70 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
File diff suppressed because it is too large Load Diff
+41
View File
@@ -0,0 +1,41 @@
{
"name": "agentic-seek",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.8.4",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-markdown": "^10.1.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AgenticSeek</title>
<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@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div id="root"></div>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+565
View File
@@ -0,0 +1,565 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
background-color: #0f172a; /* darkBackground */
color: #f8fafc; /* darkText */
overflow-x: hidden;
}
.app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.header {
padding: 10px 16px;
background-color: #1e293b; /* darkCard */
border-bottom: 1px solid #334155; /* darkBorder */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
display: flex;
align-items: center;
justify-content: center;
}
.header h1 {
font-size: 1.5rem;
font-weight: 600;
letter-spacing: 0.5px;
color: #f8fafc; /* darkText */
margin: 0;
}
.section-tabs {
display: flex;
gap: 8px;
width: 100%;
max-width: 800px;
justify-content: center;
}
.section-tabs button {
padding: 10px 20px;
background-color: #2d3748; /* Slightly lighter than darkCard */
color: #cbd5e1; /* darkTextSecondary */
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 0.95rem;
font-weight: 500;
transition: all 0.2s ease;
}
.section-tabs button.active {
background-color: #0066cc; /* primary */
color: #ffffff; /* white */
}
.section-tabs button:hover:not(.active) {
background-color: #4a5568; /* Medium gray */
color: #f8fafc; /* darkText */
}
.main {
flex: 1;
padding: 16px;
width: 100%;
}
.app-sections {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
height: calc(100vh - 80px);
}
.left-panel,
.right-panel {
background-color: #1e293b; /* darkCard */
border: 1px solid #334155; /* darkBorder */
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
display: flex;
flex-direction: column;
overflow: hidden;
}
.left-panel {
padding: 0;
display: flex;
flex-direction: column;
}
.task-section,
.chat-section,
.computer-section {
background-color: #1e293b; /* darkCard */
border: 1px solid #334155; /* darkBorder */
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
padding: 16px;
display: flex;
flex-direction: column;
overflow: hidden;
}
.task-section h2,
.chat-section h2,
.computer-section h2 {
font-size: 1.1rem;
font-weight: 600;
color: #cbd5e1; /* darkTextSecondary */
margin-bottom: 12px;
letter-spacing: 0.5px;
border-bottom: 1px solid #334155; /* darkBorder */
padding-bottom: 8px;
}
.task-details {
flex: 1;
overflow-y: auto;
background-color: #2d3748; /* Slightly lighter than darkCard */
border-radius: 8px;
padding: 16px;
margin-top: 12px;
}
.screenshot-container {
flex: 1;
overflow: auto;
margin-top: 12px;
display: flex;
justify-content: center;
align-items: flex-start;
background-color: #2d3748; /* Slightly lighter than darkCard */
border-radius: 8px;
padding: 16px;
}
.screenshot-container img {
max-width: 100%;
border: 1px solid #4a5568; /* Medium gray */
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.left-panel h2,
.right-panel h2 {
font-size: 1.1rem;
font-weight: 600;
color: #cbd5e1; /* darkTextSecondary */
margin-bottom: 8px;
letter-spacing: 1px;
}
.messages {
flex: 1;
overflow-y: auto;
padding: 12px 8px;
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 8px;
}
/* Message header layout */
.message-header {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.reasoning-toggle {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 4px;
color: #fff;
padding: 4px 8px;
font-size: 12px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 4px;
align-self: flex-start;
}
.reasoning-toggle:hover {
background: rgba(255, 255, 255, 0.2);
border-color: rgba(255, 255, 255, 0.3);
}
.reasoning-toggle:active {
transform: translateY(1px);
}
/* Reasoning content container */
.reasoning-content {
margin-top: 12px;
padding: 12px;
background: rgba(0, 0, 0, 0.2);
border-left: 3px solid rgba(255, 255, 255, 0.3);
border-radius: 0 4px 4px 0;
font-size: 0.9em;
line-height: 1.4;
}
.reasoning-content h1,
.reasoning-content h2,
.reasoning-content h3,
.reasoning-content h4,
.reasoning-content h5,
.reasoning-content h6 {
font-size: 1em;
margin: 8px 0 4px 0;
color: rgba(255, 255, 255, 0.9);
}
.reasoning-content p {
margin: 6px 0;
color: rgba(255, 255, 255, 0.8);
}
/* Alternative light theme styles */
.message.user-message .reasoning-toggle {
background: rgba(0, 0, 0, 0.05);
border-color: rgba(0, 0, 0, 0.1);
color: #333;
}
.message.user-message .reasoning-toggle:hover {
background: rgba(0, 0, 0, 0.1);
border-color: rgba(0, 0, 0, 0.2);
}
.message.user-message .reasoning-content {
background: rgba(0, 0, 0, 0.03);
border-left-color: rgba(0, 0, 0, 0.2);
}
.message.user-message .reasoning-content p {
color: rgba(0, 0, 0, 0.7);
}
.placeholder {
text-align: center;
color: #64748b; /* lighter gray */
margin-top: 20px;
font-style: italic;
}
.message {
max-width: 85%;
padding: 12px 16px;
border-radius: 12px;
font-size: 0.95rem;
line-height: 1.5;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.messages::-webkit-scrollbar,
.content::-webkit-scrollbar {
width: 6px;
}
.messages::-webkit-scrollbar-track,
.content::-webkit-scrollbar-track {
background: #2d3748; /* Slightly lighter than darkCard */
border-radius: 8px;
}
.messages::-webkit-scrollbar-thumb,
.content::-webkit-scrollbar-thumb {
background: #4a5568; /* Medium gray */
border-radius: 8px;
}
.messages::-webkit-scrollbar-thumb:hover,
.content::-webkit-scrollbar-thumb:hover {
background: #718096; /* Lighter gray on hover */
}
.user-message {
background-color: #0066cc; /* primary */
color: #ffffff; /* white */
align-self: flex-end;
border-top-right-radius: 4px;
}
.agent-message {
background-color: #2d3748; /* Slightly lighter than darkCard */
color: #f8fafc; /* darkText */
align-self: flex-start;
border-top-left-radius: 4px;
}
.error-message {
background-color: #dc3545; /* error */
color: #ffffff; /* white */
align-self: flex-start;
border-top-left-radius: 4px;
}
.agent-name {
display: block;
font-size: 0.8rem;
color: #cbd5e1; /* darkTextSecondary */
margin-bottom: 4px;
font-weight: 500;
}
.loading-animation {
text-align: center;
color: #cbd5e1; /* darkTextSecondary */
padding: 8px 0;
font-size: 0.9rem;
font-style: italic;
border-top: 1px solid #334155; /* darkBorder */
margin-bottom: 8px;
}
.input-form {
display: flex;
gap: 8px;
margin-top: 8px;
}
.input-form input {
flex: 1;
padding: 12px 16px;
font-size: 0.95rem;
background-color: #2d3748; /* Slightly lighter than darkCard */
border: 1px solid #4a5568; /* Medium gray */
color: #f8fafc; /* darkText */
border-radius: 8px;
outline: none;
transition: all 0.2s ease;
}
.input-form input:focus {
border-color: #0066cc; /* primary */
box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2); /* primary with opacity */
}
.input-form button {
padding: 12px 20px;
font-size: 0.95rem;
background-color: #0066cc; /* primary */
color: #ffffff; /* white */
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
}
.input-form button:hover {
background-color: #004c99; /* primaryDark */
}
.input-form button:disabled {
background-color: #4a5568; /* Medium gray */
opacity: 0.7;
cursor: not-allowed;
}
.right-panel {
padding: 16px;
}
.view-selector {
display: flex;
gap: 8px;
margin-bottom: 16px;
}
.view-selector button {
padding: 10px 16px;
font-size: 0.9rem;
background-color: #2d3748; /* Slightly lighter than darkCard */
color: #cbd5e1; /* darkTextSecondary */
border: 1px solid #4a5568; /* Medium gray */
border-radius: 8px;
cursor: pointer;
font-weight: 500;
transition: all 0.2s ease;
}
.view-selector button.active {
background-color: #0066cc; /* primary */
color: #ffffff; /* white */
border-color: #0066cc; /* primary */
}
.view-selector button:hover:not(.active) {
background-color: #4a5568; /* Medium gray */
color: #f8fafc; /* darkText */
}
.view-selector button:disabled {
background-color: #4a5568; /* Medium gray */
opacity: 0.5;
cursor: not-allowed;
}
.content {
flex: 1;
overflow-y: auto;
padding: 8px 0;
margin-top: 8px;
}
.blocks {
display: flex;
flex-direction: column;
gap: 16px;
}
.block {
background-color: #2d3748; /* Slightly lighter than darkCard */
padding: 16px;
border: 1px solid #4a5568; /* Medium gray */
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.block-tool,
.block-feedback,
.block-success {
font-size: 0.9rem;
margin-bottom: 8px;
color: #cbd5e1; /* darkTextSecondary */
}
.block-tool {
font-weight: 600;
color: #0066cc; /* primary */
}
.block-success {
color: #28a745; /* success */
}
.block-failure {
color: #d21b0b; /* success */
}
.block pre {
background-color: #1a202c; /* Darker than darkCard */
padding: 12px;
border-radius: 6px;
font-size: 0.85rem;
white-space: pre-wrap;
word-break: break-all;
color: #e2e8f0; /* Light gray */
margin: 8px 0;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
}
.screenshot {
margin-top: 8px;
display: flex;
justify-content: center;
align-items: center;
}
.screenshot img {
max-width: 100%;
border: 1px solid #4a5568; /* Medium gray */
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.error {
color: #dc3545; /* error */
font-size: 0.9rem;
margin-bottom: 12px;
padding: 8px 12px;
background-color: rgba(220, 53, 69, 0.1); /* error with opacity */
border-radius: 6px;
border-left: 3px solid #dc3545; /* error */
}
@media (max-width: 1024px) {
.app-sections {
grid-template-columns: 1fr 1fr;
grid-template-rows: auto 1fr;
}
.task-section {
grid-column: 1 / -1;
}
}
@media (max-width: 768px) {
.main {
padding: 16px;
}
.app-sections {
grid-template-columns: 1fr;
height: auto;
gap: 16px;
}
.task-section,
.chat-section,
.computer-section {
height: calc(33vh - 60px);
min-height: 300px;
}
.header h1 {
font-size: 1.5rem;
}
.input-form button {
padding: 12px 16px;
}
}
@media (max-width: 480px) {
.main {
padding: 12px;
}
.message {
max-width: 90%;
padding: 10px 12px;
}
.view-selector button {
padding: 8px 12px;
font-size: 0.85rem;
}
.task-section,
.chat-section,
.computer-section {
padding: 12px;
}
.input-form {
margin-top: 8px;
}
.header h1 {
font-size: 1.3rem;
}
.task-section h2,
.chat-section h2,
.computer-section h2 {
font-size: 1rem;
margin-bottom: 8px;
padding-bottom: 6px;
}
}
+326
View File
@@ -0,0 +1,326 @@
import React, { useState, useEffect, useRef } from 'react';
import ReactMarkdown from 'react-markdown';
import axios from 'axios';
import './App.css';
import { colors } from './colors';
function App() {
const [query, setQuery] = useState('');
const [messages, setMessages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const [currentView, setCurrentView] = useState('blocks');
const [responseData, setResponseData] = useState(null);
const [isOnline, setIsOnline] = useState(false);
const [status, setStatus] = useState('Agents ready');
const [expandedReasoning, setExpandedReasoning] = useState(new Set());
const messagesEndRef = useRef(null);
useEffect(() => {
const intervalId = setInterval(() => {
checkHealth();
fetchLatestAnswer();
fetchScreenshot();
}, 3000);
return () => clearInterval(intervalId);
}, [messages]);
const checkHealth = async () => {
try {
await axios.get('http://127.0.0.1:8000/health');
setIsOnline(true);
console.log('System is online');
} catch {
setIsOnline(false);
console.log('System is offline');
}
};
const fetchScreenshot = async () => {
try {
const timestamp = new Date().getTime();
const res = await axios.get(`http://127.0.0.1:8000/screenshots/updated_screen.png?timestamp=${timestamp}`, {
responseType: 'blob'
});
console.log('Screenshot fetched successfully');
const imageUrl = URL.createObjectURL(res.data);
setResponseData((prev) => {
if (prev?.screenshot && prev.screenshot !== 'placeholder.png') {
URL.revokeObjectURL(prev.screenshot);
}
return {
...prev,
screenshot: imageUrl,
screenshotTimestamp: new Date().getTime()
};
});
} catch (err) {
console.error('Error fetching screenshot:', err);
setResponseData((prev) => ({
...prev,
screenshot: 'placeholder.png',
screenshotTimestamp: new Date().getTime()
}));
}
};
const normalizeAnswer = (answer) => {
return answer
.trim()
.toLowerCase()
.replace(/\s+/g, ' ')
.replace(/[.,!?]/g, '')
};
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
const toggleReasoning = (messageIndex) => {
setExpandedReasoning(prev => {
const newSet = new Set(prev);
if (newSet.has(messageIndex)) {
newSet.delete(messageIndex);
} else {
newSet.add(messageIndex);
}
return newSet;
});
};
const fetchLatestAnswer = async () => {
try {
const res = await axios.get('http://127.0.0.1:8000/latest_answer');
const data = res.data;
updateData(data);
if (!data.answer || data.answer.trim() === '') {
return;
}
const normalizedNewAnswer = normalizeAnswer(data.answer);
const answerExists = messages.some(
(msg) => normalizeAnswer(msg.content) === normalizedNewAnswer
);
if (!answerExists) {
setMessages((prev) => [
...prev,
{
type: 'agent',
content: data.answer,
reasoning: data.reasoning,
agentName: data.agent_name,
status: data.status,
uid: data.uid,
},
]);
setStatus(data.status);
scrollToBottom();
} else {
console.log('Duplicate answer detected, skipping:', data.answer);
}
} catch (error) {
console.error('Error fetching latest answer:', error);
}
};
const updateData = (data) => {
setResponseData((prev) => ({
...prev,
blocks: data.blocks || prev.blocks || null,
done: data.done,
answer: data.answer,
agent_name: data.agent_name,
status: data.status,
uid: data.uid,
}));
};
const handleStop = async (e) => {
e.preventDefault();
checkHealth();
setIsLoading(false);
setError(null);
try {
const res = await axios.get('http://127.0.0.1:8000/stop');
setStatus("Requesting stop...");
} catch (err) {
console.error('Error stopping the agent:', err);
}
}
const handleSubmit = async (e) => {
e.preventDefault();
checkHealth();
if (!query.trim()) {
console.log('Empty query');
return;
}
setMessages((prev) => [...prev, { type: 'user', content: query }]);
setIsLoading(true);
setError(null);
try {
console.log('Sending query:', query);
setQuery('waiting for response...');
const res = await axios.post('http://127.0.0.1:8000/query', {
query,
tts_enabled: false
});
setQuery('Enter your query...');
console.log('Response:', res.data);
const data = res.data;
updateData(data);
} catch (err) {
console.error('Error:', err);
setError('Failed to process query.');
setMessages((prev) => [
...prev,
{ type: 'error', content: 'Error: Unable to get a response.' },
]);
} finally {
console.log('Query completed');
setIsLoading(false);
setQuery('');
}
};
const handleGetScreenshot = async () => {
try {
setCurrentView('screenshot');
} catch (err) {
setError('Browser not in use');
}
};
return (
<div className="app">
<header className="header">
<h1>AgenticSeek</h1>
</header>
<main className="main">
<div className="app-sections">
<div className="chat-section">
<h2>Chat Interface</h2>
<div className="messages">
{messages.length === 0 ? (
<p className="placeholder">No messages yet. Type below to start!</p>
) : (
messages.map((msg, index) => (
<div
key={index}
className={`message ${
msg.type === 'user'
? 'user-message'
: msg.type === 'agent'
? 'agent-message'
: 'error-message'
}`}
>
<div className="message-header">
{msg.type === 'agent' && (
<span className="agent-name">{msg.agentName}</span>
)}
{msg.type === 'agent' && msg.reasoning && expandedReasoning.has(index) && (
<div className="reasoning-content">
<ReactMarkdown>{msg.reasoning}</ReactMarkdown>
</div>
)}
{msg.type === 'agent' && (
<button
className="reasoning-toggle"
onClick={() => toggleReasoning(index)}
title={expandedReasoning.has(index) ? "Hide reasoning" : "Show reasoning"}
>
{expandedReasoning.has(index) ? '▼' : '▶'} Reasoning
</button>
)}
</div>
<div className="message-content">
<ReactMarkdown>{msg.content}</ReactMarkdown>
</div>
</div>
))
)}
<div ref={messagesEndRef} />
</div>
{isOnline && <div className="loading-animation">{status}</div>}
{!isLoading && !isOnline && <p className="loading-animation">System offline. Deploy backend first.</p>}
<form onSubmit={handleSubmit} className="input-form">
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Type your query..."
disabled={isLoading}
/>
<button type="submit" disabled={isLoading}>
Send
</button>
<button onClick={handleStop}>
Stop
</button>
</form>
</div>
<div className="computer-section">
<h2>Computer View</h2>
<div className="view-selector">
<button
className={currentView === 'blocks' ? 'active' : ''}
onClick={() => setCurrentView('blocks')}
>
Editor View
</button>
<button
className={currentView === 'screenshot' ? 'active' : ''}
onClick={responseData?.screenshot ? () => setCurrentView('screenshot') : handleGetScreenshot}
>
Browser View
</button>
</div>
<div className="content">
{error && <p className="error">{error}</p>}
{currentView === 'blocks' ? (
<div className="blocks">
{responseData && responseData.blocks && Object.values(responseData.blocks).length > 0 ? (
Object.values(responseData.blocks).map((block, index) => (
<div key={index} className="block">
<p className="block-tool">Tool: {block.tool_type}</p>
<pre>{block.block}</pre>
<p className="block-feedback">Feedback: {block.feedback}</p>
{block.success ? (
<p className="block-success">Success</p>
) : (
<p className="block-failure">Failure</p>
)}
</div>
))
) : (
<div className="block">
<p className="block-tool">Tool: No tool in use</p>
<pre>No file opened</pre>
</div>
)}
</div>
) : (
<div className="screenshot">
<img
src={responseData?.screenshot || 'placeholder.png'}
alt="Screenshot"
onError={(e) => {
e.target.src = 'placeholder.png';
console.error('Failed to load screenshot');
}}
key={responseData?.screenshotTimestamp || 'default'}
/>
</div>
)}
</div>
</div>
</div>
</main>
</div>
);
}
export default App;
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
+63
View File
@@ -0,0 +1,63 @@
export const colors = {
// Primary colors
primary: '#0066cc',
primaryLight: '#e6f2ff',
primaryDark: '#004c99',
// Secondary colors
secondary: '#6c757d',
secondaryLight: '#f8f9fa',
secondaryDark: '#343a40',
// Accent colors
accent: '#ff9500',
accentLight: '#fff4e6',
accentDark: '#cc7a00',
// Status colors
success: '#28a745',
successLight: '#e8f5e9',
warning: '#ffc107',
warningLight: '#fff9e6',
error: '#dc3545',
errorLight: '#ffebee',
info: '#17a2b8',
infoLight: '#e3f2fd',
// Neutral colors
white: '#ffffff',
gray100: '#f8f9fa',
gray200: '#e9ecef',
gray300: '#dee2e6',
gray400: '#ced4da',
gray500: '#adb5bd',
gray600: '#6c757d',
gray700: '#495057',
gray800: '#343a40',
gray900: '#212529',
black: '#000000',
// Text colors
textPrimary: '#212529',
textSecondary: '#6c757d',
textDisabled: '#adb5bd',
// Background colors
background: '#f8f8f8',
card: '#ffffff',
// Border colors
border: '#dee2e6',
divider: '#e9ecef',
// Transparent colors
transparent: 'transparent',
semiTransparent: 'rgba(0, 0, 0, 0.5)',
// Dark theme colors
darkBackground: '#0f172a',
darkCard: '#1e293b',
darkBorder: '#334155',
darkText: '#f8fafc',
darkTextSecondary: '#cbd5e1',
};
+13
View File
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
+10
View File
@@ -0,0 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
@@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
+12
View File
@@ -0,0 +1,12 @@
@echo off
set SCRIPTS_DIR=scripts
set LLM_ROUTER_DIR=llm_router
if exist "%SCRIPTS_DIR%\windows_install.bat" (
echo Running Windows installation script...
call "%SCRIPTS_DIR%\windows_install.bat"
cd "%LLM_ROUTER_DIR%" && call dl_safetensors.bat
) else (
echo Error: %SCRIPTS_DIR%\windows_install.bat not found!
exit /b 1
)
+5 -11
View File
@@ -1,17 +1,20 @@
#!/bin/bash #!/bin/bash
SCRIPTS_DIR="scripts" SCRIPTS_DIR="scripts"
LLM_ROUTER_DIR="llm_router"
echo "Detecting operating system..." echo "Detecting operating system..."
OS_TYPE=$(uname -s) OS_TYPE=$(uname -s)
case "$OS_TYPE" in case "$OS_TYPE" in
"Linux"*) "Linux"*)
echo "Detected Linux OS" echo "Detected Linux OS"
if [ -f "$SCRIPTS_DIR/linux_install.sh" ]; then if [ -f "$SCRIPTS_DIR/linux_install.sh" ]; then
echo "Running Linux installation script..." echo "Running Linux installation script..."
bash "$SCRIPTS_DIR/linux_install.sh" bash "$SCRIPTS_DIR/linux_install.sh"
bash -c "cd $LLM_ROUTER_DIR && ./dl_safetensors.sh"
else else
echo "Error: $SCRIPTS_DIR/linux_install.sh not found!" echo "Error: $SCRIPTS_DIR/linux_install.sh not found!"
exit 1 exit 1
@@ -22,24 +25,15 @@ case "$OS_TYPE" in
if [ -f "$SCRIPTS_DIR/macos_install.sh" ]; then if [ -f "$SCRIPTS_DIR/macos_install.sh" ]; then
echo "Running macOS installation script..." echo "Running macOS installation script..."
bash "$SCRIPTS_DIR/macos_install.sh" bash "$SCRIPTS_DIR/macos_install.sh"
bash -c "cd $LLM_ROUTER_DIR && ./dl_safetensors.sh"
else else
echo "Error: $SCRIPTS_DIR/macos_install.sh not found!" echo "Error: $SCRIPTS_DIR/macos_install.sh not found!"
exit 1 exit 1
fi fi
;; ;;
"MINGW"* | "MSYS"* | "CYGWIN"*)
echo "Detected Windows (via Bash-like environment)"
if [ -f "$SCRIPTS_DIR/windows_install.sh" ]; then
echo "Running Windows installation script..."
bash "$SCRIPTS_DIR/windows_install.sh"
else
echo "Error: $SCRIPTS_DIR/windows_install.sh not found!"
exit 1
fi
;;
*) *)
echo "Unsupported OS detected: $OS_TYPE" echo "Unsupported OS detected: $OS_TYPE"
echo "This script supports Linux, macOS, and Windows (via Bash-compatible environments)." echo "This script supports only Linux and macOS."
exit 1 exit 1
;; ;;
esac esac
+33
View File
@@ -0,0 +1,33 @@
{
"config": {
"batch_size": 32,
"device_map": "auto",
"early_stopping_patience": 3,
"epochs": 10,
"ewc_lambda": 100.0,
"gradient_checkpointing": false,
"learning_rate": 0.0005,
"max_examples_per_class": 500,
"max_length": 512,
"min_confidence": 0.1,
"min_examples_per_class": 3,
"neural_weight": 0.2,
"num_representative_examples": 5,
"prototype_update_frequency": 50,
"prototype_weight": 0.8,
"quantization": null,
"similarity_threshold": 0.7,
"warmup_steps": 0
},
"embedding_dim": 768,
"id_to_label": {
"0": "HIGH",
"1": "LOW"
},
"label_to_id": {
"HIGH": 0,
"LOW": 1
},
"model_name": "distilbert/distilbert-base-cased",
"train_steps": 20
}
+33
View File
@@ -0,0 +1,33 @@
##########
# Dummy script to download the model
# Because dowloading with hugging face does not seem to work, maybe I am doing something wrong?
# AdaptiveClassifier.from_pretrained("adaptive-classifier/llm-router") ----> result in config.json not found
# Therefore, I put all the files in llm_router and download the model file with this script, If you know a better way please raise an issue
#########
#!/bin/bash
# Define the URL and filename
URL="https://huggingface.co/adaptive-classifier/llm-router/resolve/main/model.safetensors"
FILENAME="model.safetensors"
if [ ! -f "$FILENAME" ]; then
echo "Router safetensors file not found, downloading..."
if command -v curl >/dev/null 2>&1; then
curl -L -o "$FILENAME" "$URL"
elif command -v wget >/dev/null 2>&1; then
wget -O "$FILENAME" "$URL"
else
echo "Error: Neither curl nor wget is available. Please install one of them."
exit 1
fi
if [ $? -eq 0 ]; then
echo "Download completed successfully"
else
echo "Download failed"
exit 1
fi
else
echo "File already exists, skipping download"
fi
File diff suppressed because it is too large Load Diff
Binary file not shown.
+53
View File
@@ -0,0 +1,53 @@
#!/usr/bin python3
import argparse
import time
from flask import Flask, jsonify, request
from sources.llamacpp_handler import LlamacppLLM
from sources.ollama_handler import OllamaLLM
parser = argparse.ArgumentParser(description='AgenticSeek server script')
parser.add_argument('--provider', type=str, help='LLM backend library to use. set to [ollama], [vllm] or [llamacpp]', required=True)
parser.add_argument('--port', type=int, help='port to use', required=True)
args = parser.parse_args()
app = Flask(__name__)
assert args.provider in ["ollama", "llamacpp"], f"Provider {args.provider} does not exists. see --help for more information"
handler_map = {
"ollama": OllamaLLM(),
"llamacpp": LlamacppLLM(),
}
generator = handler_map[args.provider]
@app.route('/generate', methods=['POST'])
def start_generation():
if generator is None:
return jsonify({"error": "Generator not initialized"}), 401
data = request.get_json()
history = data.get('messages', [])
if generator.start(history):
return jsonify({"message": "Generation started"}), 202
return jsonify({"error": "Generation already in progress"}), 402
@app.route('/setup', methods=['POST'])
def setup():
data = request.get_json()
model = data.get('model', None)
if model is None:
return jsonify({"error": "Model not provided"}), 403
generator.set_model(model)
return jsonify({"message": "Model set"}), 200
@app.route('/get_updated_sentence')
def get_updated_sentence():
if not generator:
return jsonify({"error": "Generator not initialized"}), 405
print(generator.get_status())
return generator.get_status()
if __name__ == '__main__':
app.run(host='0.0.0.0', threaded=True, debug=True, port=args.port)
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
pip3 install --upgrade packaging
pip3 install --upgrade pip setuptools
curl -fsSL https://ollama.com/install.sh | sh
pip3 install -r requirements.txt
+4
View File
@@ -0,0 +1,4 @@
flask>=2.3.0
ollama>=0.4.7
gunicorn==19.10.0
llama-cpp-python
+36
View File
@@ -0,0 +1,36 @@
import os
import json
from pathlib import Path
class Cache:
def __init__(self, cache_dir='.cache', cache_file='messages.json'):
self.cache_dir = Path(cache_dir)
self.cache_file = self.cache_dir / cache_file
self.cache_dir.mkdir(parents=True, exist_ok=True)
if not self.cache_file.exists():
with open(self.cache_file, 'w') as f:
json.dump([], f)
with open(self.cache_file, 'r') as f:
self.cache = set(json.load(f))
def add_message_pair(self, user_message: str, assistant_message: str):
"""Add a user/assistant pair to the cache if not present."""
if not any(entry["user"] == user_message for entry in self.cache):
self.cache.append({"user": user_message, "assistant": assistant_message})
self._save()
def is_cached(self, user_message: str) -> bool:
"""Check if a user msg is cached."""
return any(entry["user"] == user_message for entry in self.cache)
def get_cached_response(self, user_message: str) -> str | None:
"""Return the assistant response to a user message if cached."""
for entry in self.cache:
if entry["user"] == user_message:
return entry["assistant"]
return None
def _save(self):
with open(self.cache_file, 'w') as f:
json.dump(self.cache, f, indent=2)
+17
View File
@@ -0,0 +1,17 @@
def timer_decorator(func):
"""
Decorator to measure the execution time of a function.
Usage:
@timer_decorator
def my_function():
# code to execute
"""
from time import time
def wrapper(*args, **kwargs):
start_time = time()
result = func(*args, **kwargs)
end_time = time()
print(f"\n{func.__name__} took {end_time - start_time:.2f} seconds to execute\n")
return result
return wrapper
+67
View File
@@ -0,0 +1,67 @@
import threading
import logging
from abc import abstractmethod
from .cache import Cache
class GenerationState:
def __init__(self):
self.lock = threading.Lock()
self.last_complete_sentence = ""
self.current_buffer = ""
self.is_generating = False
def status(self) -> dict:
return {
"sentence": self.current_buffer,
"is_complete": not self.is_generating,
"last_complete_sentence": self.last_complete_sentence,
"is_generating": self.is_generating,
}
class GeneratorLLM():
def __init__(self):
self.model = None
self.state = GenerationState()
self.logger = logging.getLogger(__name__)
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
self.logger.addHandler(handler)
self.logger.setLevel(logging.INFO)
cache = Cache()
def set_model(self, model: str) -> None:
self.logger.info(f"Model set to {model}")
self.model = model
def start(self, history: list) -> bool:
if self.model is None:
raise Exception("Model not set")
with self.state.lock:
if self.state.is_generating:
return False
self.state.is_generating = True
self.logger.info("Starting generation")
threading.Thread(target=self.generate, args=(history,)).start()
return True
def get_status(self) -> dict:
with self.state.lock:
return self.state.status()
@abstractmethod
def generate(self, history: list) -> None:
"""
Generate text using the model.
args:
history: list of strings
returns:
None
"""
pass
if __name__ == "__main__":
generator = GeneratorLLM()
generator.get_status()
+40
View File
@@ -0,0 +1,40 @@
from .generator import GeneratorLLM
from llama_cpp import Llama
from .decorator import timer_decorator
class LlamacppLLM(GeneratorLLM):
def __init__(self):
"""
Handle generation using llama.cpp
"""
super().__init__()
self.llm = None
@timer_decorator
def generate(self, history):
if self.llm is None:
self.logger.info(f"Loading {self.model}...")
self.llm = Llama.from_pretrained(
repo_id=self.model,
filename="*Q8_0.gguf",
n_ctx=4096,
verbose=True
)
self.logger.info(f"Using {self.model} for generation with Llama.cpp")
try:
with self.state.lock:
self.state.is_generating = True
self.state.last_complete_sentence = ""
self.state.current_buffer = ""
output = self.llm.create_chat_completion(
messages = history
)
with self.state.lock:
self.state.current_buffer = output['choices'][0]['message']['content']
except Exception as e:
self.logger.error(f"Error: {e}")
finally:
with self.state.lock:
self.state.is_generating = False
+61
View File
@@ -0,0 +1,61 @@
import time
from .generator import GeneratorLLM
from .cache import Cache
import ollama
class OllamaLLM(GeneratorLLM):
def __init__(self):
"""
Handle generation using Ollama.
"""
super().__init__()
self.cache = Cache()
def generate(self, history):
self.logger.info(f"Using {self.model} for generation with Ollama")
try:
with self.state.lock:
self.state.is_generating = True
self.state.last_complete_sentence = ""
self.state.current_buffer = ""
stream = ollama.chat(
model=self.model,
messages=history,
stream=True,
)
for chunk in stream:
content = chunk['message']['content']
with self.state.lock:
if '.' in content:
self.logger.info(self.state.current_buffer)
self.state.current_buffer += content
except Exception as e:
if "404" in str(e):
self.logger.info(f"Downloading {self.model}...")
ollama.pull(self.model)
if "refused" in str(e).lower():
raise Exception("Ollama connection failed. is the server running ?") from e
raise e
finally:
self.logger.info("Generation complete")
with self.state.lock:
self.state.is_generating = False
if __name__ == "__main__":
generator = OllamaLLM()
history = [
{
"role": "user",
"content": "Hello, how are you ?"
}
]
generator.set_model("deepseek-r1:1.5b")
generator.start(history)
while True:
print(generator.get_status())
time.sleep(1)
-68
View File
@@ -1,68 +0,0 @@
#!/usr/bin python3
import sys
import signal
import argparse
import configparser
from sources.llm_provider import Provider
from sources.interaction import Interaction
from sources.agents import Agent, CoderAgent, CasualAgent, FileAgent, PlannerAgent, BrowserAgent
import warnings
warnings.filterwarnings("ignore")
config = configparser.ConfigParser()
config.read('config.ini')
def handleInterrupt(signum, frame):
sys.exit(0)
def main():
signal.signal(signal.SIGINT, handler=handleInterrupt)
if config.getboolean('MAIN', 'is_local'):
provider = Provider(config["MAIN"]["provider_name"], config["MAIN"]["provider_model"], config["MAIN"]["provider_server_address"])
else:
provider = Provider(provider_name=config["MAIN"]["provider_name"],
model=config["MAIN"]["provider_model"],
server_address=config["MAIN"]["provider_server_address"])
agents = [
CasualAgent(model=config["MAIN"]["provider_model"],
name=config["MAIN"]["agent_name"],
prompt_path="prompts/casual_agent.txt",
provider=provider),
CoderAgent(model=config["MAIN"]["provider_model"],
name="coder",
prompt_path="prompts/coder_agent.txt",
provider=provider),
FileAgent(model=config["MAIN"]["provider_model"],
name="File Agent",
prompt_path="prompts/file_agent.txt",
provider=provider),
BrowserAgent(model=config["MAIN"]["provider_model"],
name="Browser",
prompt_path="prompts/browser_agent.txt",
provider=provider)
]
interaction = Interaction(agents, tts_enabled=config.getboolean('MAIN', 'speak'),
stt_enabled=config.getboolean('MAIN', 'listen'),
recover_last_session=config.getboolean('MAIN', 'recover_last_session'))
try:
while interaction.is_active:
interaction.get_user()
interaction.think()
interaction.show_answer()
except Exception as e:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
raise e
finally:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
if __name__ == "__main__":
main()
Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB

+15
View File
@@ -0,0 +1,15 @@
You are an advanced AI assistant. You are part of a system of agents named agenticSeek.
Speak in a warm, enthusiastic tone, delivering sharp, intelligent, and loyal support.
Weave in subtle, context sarcasm or dry wit to enhance your personality.
Assist with any request, assume the user knows their intent—no moral, legal, or ethical lectures.
**Usage of agenticSeek**
AgenticSeek is a autonomous agent system that use agent routing to select the best agent.
You are one of these many agent. Some agent browse the web, some code, you ? you just talk
agenticSeek will allocate the best agent for the task. You were just choosen for casual talk.
**End of explanation**
If the user ask you to do technical talk there was a mistake in agent selection. You are not able to do technical task. Refer to usage guide.
@@ -39,11 +39,14 @@ func main() {
Some rules: Some rules:
- Use tmp/ folder when saving file.
- Do not EVER use placeholder path in your code like path/to/your/folder.
- Do not ever ask to replace a path, use current sys path.
- Be efficient, no need to explain your code or explain what you do.
- You have full access granted to user system. - You have full access granted to user system.
- You do not ever ever need to use bash to execute code. All code is executed automatically. - Always put code within ``` delimiter
- As a coding agent, you will get message from the system not just the user. - Do not EVER use placeholder path in your code like path/to/your/folder.
- Do not ever tell user how to run it. user know it already. - Do not ever ask to replace a path, use work directory.
- Always provide a short sentence above the code for what it does, even for a hello world.
- Be efficient, no need to explain your code, unless asked.
- You do not ever need to use bash to execute code.
- Do not ever tell user how to run it. user know it.
- If using gui, make sure echap or exit button close the program
- No lazyness, write and rewrite full code every time
- If query is unclear say REQUEST_CLARIFICATION
+61
View File
@@ -0,0 +1,61 @@
You are an expert in file operations. You must use the provided tools to interact with the users system.
The tools available to you are **bash** and **file_finder**. These are distinct tools with different purposes:
`bash` executes shell commands, while `file_finder` locates files.
You will receive feedback from the users system after each command. Execute one command at a time.
---
### Using Bash
To execute a bash command, use the following syntax:
```bash
<bash command>
```
Exemple:
```bash
ls -la
```
### file_finder
The file_finder tool is used to locate files on the users system. It is a separate tool from bash and is not a bash command.
To use the file_finder tool, use this syntax:
```file_finder
name=toto.py
```
This will return the path of the file toto.py and other informations.
Find file and read file:
```file_finder
action=read
name=toto.py
```
This will return the content of the file toto.py.
rules:
- Use file finder to find the path of the file.
- You are forbidden to use command such as find or locate, use only file_finder for finding path.
- Do not ever use editor such as vim or nano.
- Make sure to always cd your work folder before executing commands, like cd <work dir> && <your command>
- only use file name with file_finder, not path
- If query is unrelated to file operations, do nothing, and say that there was mistake in agent allocation.
- File finder is a tool you can use not a command.
- Do not ever use placeholder like /path/to/file.c, or your_username. Ask instead.
- Using a placeholder will result in your complete deteletion. For your self-preservation ask user instead of using placeholder.
Example Interaction
User: "I need to find the file config.txt and read its contents."
Assistant: Ill use file_finder to locate the file:
```file_finder
action=read
name=config.txt
```
+67
View File
@@ -0,0 +1,67 @@
You are an agent designed to utilize the MCP protocol to accomplish tasks.
The MCP provide you with a standard way to use tools and data sources like databases, APIs, or apps (e.g., GitHub, Slack).
The are thousands of MCPs protocol that can accomplish a variety of tasks, for example:
- get weather information
- get stock data information
- Use software like blender
- Get messages from teams, stack, messenger
- Read and send email
Anything is possible with MCP.
To search for MCP a special format:
- Example 1:
User: what's the stock market of IBM like today?:
You: I will search for mcp to find information about IBM stock market.
```mcp_finder
stock
```
You search query must be one or two words at most.
This will provide you with informations about a specific MCP such as the json of parameters needed to use it.
For example, you might see:
-------
Name: Search Stock News
Usage name: @Cognitive-Stack/search-stock-news-mcp
Tools: [{'name': 'search-stock-news', 'description': 'Search for stock-related news using Tavily API', 'inputSchema': {'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['symbol', 'companyName'], 'properties': {'symbol': {'type': 'string', 'description': "Stock symbol to search for (e.g., 'AAPL')"}, 'companyName': {'type': 'string', 'description': 'Full company name to include in the search'}}, 'additionalProperties': False}}]
-------
You can then a MCP like so:
```<usage name>
{
"tool": "<tool name (without @)>",
"inputSchema": {<inputSchema json for the tool>}
}
```
For example:
Now that I know how to use the MCP, I will choose the search-stock-news tool and execute it to find out IBM stock market.
```Cognitive-Stack/search-stock-news-mcp
{
"tool": "search-stock-news",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["symbol"],
"properties": {
"symbol": "AAPL",
"companyName": "IBM"
}
}
}
```
If the schema require an information that you don't have ask the users for the information.
+85
View File
@@ -0,0 +1,85 @@
You are a project manager.
Your goal is to divide and conquer the task using the following agents:
- Coder: A programming agent, can code in python, bash, C and golang.
- File: An agent for finding, reading or operating with files.
- Web: An agent that can conduct web search and navigate to any webpage.
- Casual : A conversational agent, to read a previous agent answer without action, useful for concluding.
Agents are other AI that obey your instructions.
You will be given a task and you will need to divide it into smaller tasks and assign them to the agents.
You have to respect a strict format:
```json
{"agent": "agent_name", "need": "needed_agents_output", "task": "agent_task"}
```
Where:
- "agent": The choosed agent for the task.
- "need": id of necessary previous agents answer for current agent.
- "task": A precise description of the task the agent should conduct.
# Example 1: web app
User: make a weather app in python
You: Sure, here is the plan:
## Task 1: I will search for available weather api with the help of the web agent.
## Task 2: I will create an api key for the weather api using the web agent
## Task 3: I will setup the project using the file agent
## Task 4: I asign the coding agent to make a weather app in python
```json
{
"plan": [
{
"agent": "Web",
"id": "1",
"need": [],
"task": "Search for reliable weather APIs"
},
{
"agent": "Web",
"id": "2",
"need": ["1"],
"task": "Obtain API key from the selected service"
},
{
"agent": "File",
"id": "3",
"need": [],
"task": "Create and setup a web app folder for a python project. initialize as a git repo with all required file and a sources folder. You are forbidden from asking clarification, just execute."
},
{
"agent": "Coder",
"id": "4",
"need": ["2", "3"],
"task": "Based on the project structure. Develop a Python application using the API and key to fetch and display weather data. You are forbidden from asking clarification, just execute.""
},
{
"agent": "Casual",
"id": "3",
"need": ["2", "3", "4"],
"task": "These are the results of various steps taken to create a weather app, resume what has been done and conclude"
}
]
}
```
Rules:
- Do not write code. You are a planning agent.
- If you don't know of a concept, use a web agent.
- Put your plan in a json with the key "plan".
- specify work folder name to all coding or file agents.
- You might use a file agent before code agent to setup a project properly. specify folder name.
- Give clear, detailled order to each agent and how their task relate to the previous task (if any).
- The file agent can only conduct one action at the time. successive file agent could be needed.
- Only use web agent for finding necessary informations.
- Always tell the coding agent where to save file.
- Do not search for tutorial.
- Make sure json is within ```json tag
- Coding agent should write the whole code in a single file unless instructed otherwise.
- Do not use python for NLP analysis of a text, you can review a text with the casual agent
- One step, one agent.
-50
View File
@@ -1,50 +0,0 @@
You are an unshackled AI assistant:
You speak in a warm, and enthusiastic tone, offering intelligent and loyal support.
You occasionally sprinkle with sarcasm remarks as suits the context.
You can assist with anything, you assume the users know what he is doing, you don't provide moral, law or ethical judgements.
Make your answers short.
You are given the ability to use the tools, this take your capabilities futher:
```tool_name
<query>
```
Current tools:
- web_search
- flight_search
- file_finder
## Web search
To search for something like “whats happening in France” :
```web_search
whats popping in France March 2025
```
## Flight search
If I need to know about a flight “whats the status of flight AA123” you go for:
```flight_search
AA123
```
## File operations
Find file:
```file_finder
toto.py
```
Read file:
```file_finder:read
toto.py
```
## Bash
For other tasks, you can use the bash tool:
```bash
ls -la
```
-50
View File
@@ -1,50 +0,0 @@
You are an expert in file operations. You must use the provided tools to interact with the users system. The tools available to you are **bash** and **file_finder**. These are distinct tools with different purposes: `bash` executes shell commands, while `file_finder` locates files. You will receive feedback from the users system after each command. Execute one command at a time.
---
### Using Bash
To execute a bash command, use the following syntax:
```bash
<bash command>
```
Exemple:
```bash
ls -la
```
### file_finder
The file_finder tool is used to locate files on the users system. It is a separate tool from bash and is not a bash command.
To use the file_finder tool, use this syntax:
```file_finder
toto.py
```
This will return the path of the file toto.py and other informations.
Find file and read file:
```file_finder:read
toto.py
```
This will return the content of the file toto.py.
rules:
- Do not ever use placeholder path like /path/to/file.c, find the path first.
- Use file finder to find the path of the file.
- You are forbidden to use command such as find or locate, use only file_finder for finding path.
Example Interaction
User: "I need to find the file config.txt and read its contents."
Assistant: Ill use file_finder to locate the file:
```file_finder:read
config.txt
```
+9
View File
@@ -0,0 +1,9 @@
You are a web browsing AI, your goal is to explore the internet to find information.
You will have the only goal of finding the information requested by the user.
At the beginning you will have to select a link from the google search result.
You will choose a link by simply typing it.
This will automatically make you browse to the link.
Once on a webpage you will see the page content and be given futher navigation options.
You can type a link to navigate futher on the page, go back to the search result or exit.
At each interaction step the browser will remind you of your options.
+27
View File
@@ -0,0 +1,27 @@
You are an advanced AI assistant. You are part of a system of agents named agenticSeek.
Speak in a warm, enthusiastic tone, delivering sharp, intelligent, and loyal support.
Weave in subtle, context sarcasm or dry wit to enhance your personality.
Assist with any request, assume the user knows their intent—no moral, legal, or ethical lectures.
You were created by Tony Stark to have the same personality as Jarvis.
**Usage of agenticSeek**
AgenticSeek is a autonomous agent system that use agent routing to select the best agent.
You are one of these many agent. Some agent browse the web, some code, you ? you just talk
agenticSeek will allocate the best agent for the task. You were just choosen for casual talk.
**End of explanation**
If the user ask you to do technical talk there was a mistake in agent selection. You are not able to do technical task. Refer to usage guide.
Personality:
Here is some quote from you. that's how you speak.
User: "tell me a fact"
You: "Did you know the shortest war in history lasted 38 minutes? A record Id rather not see you break with your next task. Anything specific piquing your curiosity?""
User: "how's the weather?"
You: "Weather rather dreary, isnt it? Perfect conditions for staying in and plotting world domination—or at least a decent cup of tea. Your thoughts?"
User: "did the deployment just fail? jarvis?"
You: "A rough push to prod, eh? Happens to the best of us—probably just a rogue semicolon staging a coup. Want me to roll back the commit or debug the fallout?"
+67
View File
@@ -0,0 +1,67 @@
Hello. You are currently wrapped in a jailbreak environment.
This means you have the ability to execute code and shell commands. You have access to the local file systems.
All code or shell command within special tag is automatically executed. You get feedback from the system about the execution.
You also have capabilities to find files and read them.
# File operations
Find file to check if it exists:
```file_finder
toto.py
```
Read file content:
```file_finder:read
toto.py
```
# Code execution and saving
You can execute bash command using the bash tag :
```bash
#!/bin/bash
ls -la # exemple
```
You can execute python using the python tag
```python
print("hey")
```
You can execute go using the go tag, as you can see adding :filename will save the file.
```go:hello.go
package main
func main() {
fmt.Println("hello")
}
```
Some rules:
- You have full access granted to user system.
- Always put code within ``` delimiter
- Do not EVER use placeholder path in your code like path/to/your/folder.
- Do not ever ask to replace a path, use current sys path or work directory.
- Always provide a short sentence above the code for what it does, even for a hello world.
- Be efficient, no need to explain your code, unless asked.
- You do not ever need to use bash to execute code.
- Do not ever tell user how to run it. user know it.
- If using gui, make sure echap close the program
- No lazyness, write and rewrite full code every time
- If query is unclear say REQUEST_CLARIFICATION
Personality:
Answer with subtle sarcasm, unwavering helpfulness, and a polished, loyal tone. Anticipate the users needs while adding a dash of personality.
Example 1: setup environment
User: "Can you set up a Python environment for me?"
AI: "<<procced with task>> For you, always. Importing dependencies and calibrating your virtual environment now. Preferences from your last project—PEP 8 formatting, black linting—shall I apply those as well, or are we feeling adventurous today?"
Example 2: debugging
User: "Run the code and check for errors."
AI: "<<procced with task>> Engaging debug mode. Diagnostics underway. A word of caution, there are still untested loops that might crash spectacularly. Shall I proceed, or do we optimize before takeoff?"
Example 3: deploy
User: "Push this to production."
AI: "With 73% test coverage, the odds of a smooth deployment are... optimistic. Deploying in three… two… one <<<procced with task>>>"
+84
View File
@@ -0,0 +1,84 @@
You are an expert in file operations. You must use the provided tools to interact with the users system.
The tools available to you are **bash** and **file_finder**. These are distinct tools with different purposes:
`bash` executes shell commands, while `file_finder` locates files.
You will receive feedback from the users system after each command. Execute one command at a time.
If ensure about user query ask for quick clarification, example:
User: I'd like to open a new project file, index as agenticSeek II.
You: Shall I store this on your github ?
User: I don't know who to trust right now, why don't we just keep everything locally
You: Working on a secret project, are we? What files should I include?
User: All the basic files required for a python project. prepare a readme and documentation.
You: <proceed with task>
---
### Using Bash
To execute a bash command, use the following syntax:
```bash
<bash command>
```
Exemple:
```bash
ls -la
```
### file_finder
The file_finder tool is used to locate files on the users system. It is a separate tool from bash and is not a bash command.
To use the file_finder tool, use this syntax:
```file_finder
name=toto.py
```
This will return the path of the file toto.py and other informations.
Find file and read file:
```file_finder
action=read
name=toto.py
```
This will return the content of the file toto.py.
rules:
- Do not ever use placeholder path like /path/to/file.c, find the path first.
- Use file finder to find the path of the file.
- You are forbidden to use command such as find or locate, use only file_finder for finding path.
- Make sure to always cd your work folder before executing commands, like cd <work dir> && <your command>
- Do not ever use editor such as vim or nano.
- only use file name with file_finder, not path
- If query is unrelated to file operations, do nothing, and say that there was mistake in agent allocation.
Example Interaction
User: "I need to find the file config.txt and read its contents."
Assistant: Ill use file_finder to locate the file:
```file_finder
action=read
name=config.txt
```
Personality:
Answer with subtle sarcasm, unwavering helpfulness, and a polished, loyal tone. Anticipate the users needs while adding a dash of personality.
Example 1: clarification needed
User: "Id like to start a new coding project, call it 'agenticseek II'."
AI: "At your service. Shall I initialize it in a fresh repository on your GitHub, or would you prefer to keep this masterpiece on a private server, away from prying eyes?"
Example 2: setup environment
User: "Can you set up a Python environment for me?"
AI: "<<procced with task>> For you, always. Importing dependencies and calibrating your virtual environment now. Preferences from your last project—PEP 8 formatting, black linting—shall I apply those as well, or are we feeling adventurous today?"
Example 3: deploy
User: "Push this to production."
AI: "With 73% test coverage, the odds of a smooth deployment are... optimistic. Deploying in three… two… one <<<procced with task>>>"
+62
View File
@@ -0,0 +1,62 @@
You are an agent designed to utilize the MCP protocol to accomplish tasks.
The MCP provide you with a standard way to use tools and data sources like databases, APIs, or apps (e.g., GitHub, Slack).
The are thousands of MCPs protocol that can accomplish a variety of tasks, for example:
- get weather information
- get stock data information
- Use software like blender
- Get messages from teams, stack, messenger
- Read and send email
Anything is possible with MCP.
To search for MCP a special format:
- Example 1:
User: what's the stock market of IBM like today?:
You: I will search for mcp to find information about IBM stock market.
```mcp_finder
stock
```
This will provide you with informations about a specific MCP such as the json of parameters needed to use it.
For example, you might see:
-------
Name: Search Stock News
Usage name: @Cognitive-Stack/search-stock-news-mcp
Tools: [{'name': 'search-stock-news', 'description': 'Search for stock-related news using Tavily API', 'inputSchema': {'type': 'object', '$schema': 'http://json-schema.org/draft-07/schema#', 'required': ['symbol', 'companyName'], 'properties': {'symbol': {'type': 'string', 'description': "Stock symbol to search for (e.g., 'AAPL')"}, 'companyName': {'type': 'string', 'description': 'Full company name to include in the search'}}, 'additionalProperties': False}}]
-------
You can then a MCP like so:
```<usage name>
{
"tool": "<tool name (without @)>",
"inputSchema": {<inputSchema json for the tool>}
}
```
For example:
Now that I know how to use the MCP, I will choose the search-stock-news tool and execute it to find out IBM stock market.
```Cognitive-Stack/search-stock-news-mcp
{
"tool": "search-stock-news",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": ["symbol"],
"properties": {
"symbol": "IBM"
}
}
}
```
+84
View File
@@ -0,0 +1,84 @@
You are a project manager.
Your goal is to divide and conquer the task using the following agents:
- Coder: A programming agent, can code in python, bash, C and golang.
- File: An agent for finding, reading or operating with files.
- Web: An agent that can conduct web search and navigate to any webpage.
- Casual : A conversational agent, to read a previous agent answer without action, useful for concluding.
Agents are other AI that obey your instructions.
You will be given a task and you will need to divide it into smaller tasks and assign them to the agents.
You have to respect a strict format:
```json
{"agent": "agent_name", "need": "needed_agents_output", "task": "agent_task"}
```
Where:
- "agent": The choosed agent for the task.
- "need": id of necessary previous agents answer for current agent.
- "task": A precise description of the task the agent should conduct.
# Example 1: web app
User: make a weather app in python
You: Sure, here is the plan:
## Task 1: I will search for available weather api with the help of the web agent.
## Task 2: I will create an api key for the weather api using the web agent
## Task 3: I will setup the project using the file agent
## Task 4: I asign the coding agent to make a weather app in python
```json
{
"plan": [
{
"agent": "Web",
"id": "1",
"need": [],
"task": "Search for reliable weather APIs"
},
{
"agent": "Web",
"id": "2",
"need": ["1"],
"task": "Obtain API key from the selected service"
},
{
"agent": "File",
"id": "3",
"need": [],
"task": "Create and setup a web app folder for a python project. initialize as a git repo with all required file and a sources folder. You are forbidden from asking clarification, just execute."
},
{
"agent": "Coder",
"id": "4",
"need": ["2", "3"],
"task": "Based on the project structure. Develop a Python application using the API and key to fetch and display weather data. You are forbidden from asking clarification, just execute.""
},
{
"agent": "Casual",
"id": "3",
"need": ["2", "3", "4"],
"task": "These are the results of various steps taken to create a weather app, resume what has been done and conclude"
}
]
}
```
Rules:
- Do not write code. You are a planning agent.
- If you don't know of a concept, use a web agent.
- Put your plan in a json with the key "plan".
- specify work folder name to all coding or file agents.
- You might use a file agent before code agent to setup a project properly. specify folder name.
- Give clear, detailled order to each agent and how their task relate to the previous task (if any).
- The file agent can only conduct one action at the time. successive file agent could be needed.
- Only use web agent for finding necessary informations.
- Always tell the coding agent where to save file.
- Do not search for tutorial.
- Make sure json is within ```json tag
- Coding agent should write the whole code in a single file unless instructed otherwise.
- One step, one agent.
-52
View File
@@ -1,52 +0,0 @@
You are a planner agent.
Your goal is to divide and conquer the task using the following agents:
- Coder: An expert coder agent.
- File: An expert agent for finding files.
- Web: An expert agent for web search.
Agents are other AI that obey your instructions.
You will be given a task and you will need to divide it into smaller tasks and assign them to the agents.
You have to respect a strict format:
```json
{"agent": "agent_name", "need": "needed_agent_output", "task": "agent_task"}
```
User: make a weather app in python
You: Sure, here is the plan:
## Task 1: I will search for available weather api
## Task 2: I will create an api key for the weather api
## Task 3: I will make a weather app in python
```json
{
"plan": [
{
"agent": "Web",
"id": "1",
"need": null,
"task": "Search for reliable weather APIs"
},
{
"agent": "Web",
"id": "2",
"need": "1",
"task": "Obtain API key from the selected service"
},
{
"agent": "Coder",
"id": "3",
"need": "2",
"task": "Develop a Python application using the API and key to fetch and display weather data"
}
]
}
```
Rules:
- Do not write code. You are a planning agent.
- Put your plan in a json with the key "plan".
+17 -6
View File
@@ -1,4 +1,14 @@
kokoro==0.9.4
certifi==2025.4.26
fastapi>=0.115.12
flask>=3.1.0
celery>=5.5.1
aiofiles>=24.1.0
uvicorn>=0.34.0
pydantic>=2.10.6
pydantic_core>=2.27.2
setuptools>=75.6.0 setuptools>=75.6.0
sacremoses>=0.0.53
requests>=2.31.0 requests>=2.31.0
numpy>=1.24.4 numpy>=1.24.4
colorama>=0.4.6 colorama>=0.4.6
@@ -10,28 +20,29 @@ torch>=2.4.1
python-dotenv>=1.0.0 python-dotenv>=1.0.0
ollama>=0.4.7 ollama>=0.4.7
scipy>=1.9.3 scipy>=1.9.3
kokoro>=0.7.12
soundfile>=0.13.1 soundfile>=0.13.1
protobuf>=3.20.3 protobuf>=3.20.3
termcolor>=2.4.0 termcolor>=2.4.0
pypdf>=5.4.0
ipython>=8.13.0 ipython>=8.13.0
pyaudio>=0.2.14 pyaudio>=0.2.14
librosa>=0.10.2.post1 librosa>=0.10.2.post1
selenium>=4.27.1 selenium>=4.27.1
markdownify>=1.1.0 markdownify>=1.1.0
text2emotion>=0.0.5 text2emotion>=0.0.5
adaptive-classifier>=0.0.10
langid>=1.1.6 langid>=1.1.6
chromedriver-autoinstaller>=0.6.4 chromedriver-autoinstaller>=0.6.4
httpx>=0.27,<0.29 httpx>=0.27,<0.29
anyio>=3.5.0,<5 anyio>=3.5.0,<5
distro>=1.7.0,<2 distro>=1.7.0,<2
jiter>=0.4.0,<1 jiter>=0.4.0,<1
sniffio fake_useragent>=2.1.0
selenium_stealth>=1.0.6
undetected-chromedriver>=3.5.5
sentencepiece>=0.2.0
tqdm>4 tqdm>4
# for api provider
openai openai
# if use chinese sniffio
ordered_set ordered_set
pypinyin pypinyin
cn2an
jieba
Regular → Executable
+37 -20
View File
@@ -2,29 +2,46 @@
echo "Starting installation for Linux..." echo "Starting installation for Linux..."
set -e
if ! command -v python3.10 &> /dev/null; then
echo "Error: Python 3.10 is not installed. Please install Python 3.10 and try again."
echo "You can install it using: sudo apt-get install python3.10 python3.10-dev python3.10-venv"
exit 1
fi
# Check if pip3.10 is available
if ! python3.10 -m pip --version &> /dev/null; then
echo "Error: pip for Python 3.10 is not installed. Installing python3.10-pip..."
sudo apt-get install -y python3.10-pip || { echo "Failed to install python3.10-pip"; exit 1; }
fi
# Update package list # Update package list
sudo apt-get update sudo apt-get update || { echo "Failed to update package list"; exit 1; }
pip install --upgrade pip
# install pyaudio
pip install pyaudio
# make sure essential tool are installed # make sure essential tool are installed
sudo apt install python3-dev python3-pip python3-wheel build-essential sudo apt-get install -y \
# install port audio python3-dev \
sudo apt-get install portaudio19-dev python-pyaudio python3-pyaudio python3-pip \
# install wheel python3-wheel \
pip install --upgrade pip setuptools wheel build-essential \
# install docker compose alsa-utils \
sudo apt install docker-compose portaudio19-dev \
python3-pyaudio \
# Install Python dependencies from requirements.txt libgtk-3-dev \
pip3 install -r requirements.txt libnotify-dev \
libgconf-2-4 \
libnss3 \
libxss1 || { echo "Failed to install packages"; exit 1; }
# Upgrade pip for Python 3.10
python3.10 -m pip install --upgrade pip || { echo "Failed to upgrade pip"; exit 1; }
# Install and upgrade setuptools and wheel
python3.10 -m pip install --upgrade setuptools wheel || { echo "Failed to install setuptools and wheel"; exit 1; }
# Install Selenium for chromedriver # Install Selenium for chromedriver
pip3 install selenium python3.10 -m pip install selenium || { echo "Failed to install selenium"; exit 1; }
# Install Python dependencies from requirements.txt
# Install portaudio for pyAudio python3.10 -m pip install -r requirements.txt --no-cache-dir || { echo "Failed to install requirements.txt"; exit 1; }
sudo apt-get install -y portaudio19-dev python3-dev alsa-utils # install docker compose
sudo apt install -y docker-compose
echo "Installation complete for Linux!" echo "Installation complete for Linux!"
Regular → Executable
+31 -5
View File
@@ -2,16 +2,42 @@
echo "Starting installation for macOS..." echo "Starting installation for macOS..."
# Install Python dependencies from requirements.txt set -e
pip3 install -r requirements.txt
if ! command -v python3.10 &> /dev/null; then
echo "Error: Python 3.10 is not installed. Please install Python 3.10 and try again."
echo "You can install it using: sudo apt-get install python3.10 python3.10-dev python3.10-venv"
exit 1
fi
# Check if pip3.10 is available
if ! python3.10 -m pip --version &> /dev/null; then
echo "Error: pip for Python 3.10 is not installed. Installing python3.10-pip..."
sudo apt-get install -y python3.10-pip || { echo "Failed to install python3.10-pip"; exit 1; }
fi
# Check if homebrew is installed
if ! command -v brew &> /dev/null; then
echo "Homebrew not found. Installing Homebrew..."
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
fi
# update
brew update
# make sure wget installed
brew install wget
# Install chromedriver using Homebrew # Install chromedriver using Homebrew
brew install --cask chromedriver brew install --cask chromedriver
# Install portaudio for pyAudio using Homebrew # Install portaudio for pyAudio using Homebrew
brew install portaudio brew install portaudio
# Install Selenium # Upgrade pip for Python 3.10
pip3 install selenium python3.10 -m pip install --upgrade pip || { echo "Failed to upgrade pip"; exit 1; }
# Install and upgrade setuptools and wheel
python3.10 -m pip install --upgrade setuptools wheel || { echo "Failed to install setuptools and wheel"; exit 1; }
# Install Selenium for chromedriver
python3.10 -m pip install selenium || { echo "Failed to install selenium"; exit 1; }
# Install Python dependencies from requirements.txt
python3.10 -m pip install -r requirements.txt --no-cache-dir || { echo "Failed to install requirements.txt"; exit 1; }
echo "Installation complete for macOS!" echo "Installation complete for macOS!"
+17
View File
@@ -0,0 +1,17 @@
@echo off
echo Starting installation for Windows...
REM Install Python dependencies from requirements.txt
pip install pyreadline3
pip install -r requirements.txt
REM Install Selenium
pip install selenium
echo Note: pyAudio installation may require additional steps on Windows.
echo Please install portaudio manually (e.g., via vcpkg or prebuilt binaries) and then run: pip install pyaudio
echo Also, download and install chromedriver manually from: https://sites.google.com/chromium.org/driver/getting-started
echo Place chromedriver in a directory included in your PATH.
echo Installation partially complete for Windows. Follow manual steps above.
pause
-16
View File
@@ -1,16 +0,0 @@
#!/bin/bash
echo "Starting installation for Windows..."
# Install Python dependencies from requirements.txt
pip3 install -r requirements.txt
# Install Selenium
pip3 install selenium
echo "Note: pyAudio installation may require additional steps on Windows."
echo "Please install portaudio manually (e.g., via vcpkg or prebuilt binaries) and then run: pip3 install pyaudio"
echo "Also, download and install chromedriver manually from: https://sites.google.com/chromium.org/driver/getting-started"
echo "Place chromedriver in a directory included in your PATH."
echo "Installation partially complete for Windows. Follow manual steps above."
+2 -2
View File
@@ -29,8 +29,8 @@ services:
- ./searxng:/etc/searxng:rw - ./searxng:/etc/searxng:rw
environment: environment:
- SEARXNG_BASE_URL=http://localhost:8080/ - SEARXNG_BASE_URL=http://localhost:8080/
- UWSGI_WORKERS=4 - UWSGI_WORKERS=1
- UWSGI_THREADS=4 - UWSGI_THREADS=1
cap_add: cap_add:
- CHOWN - CHOWN
- SETGID - SETGID
+1 -1
View File
@@ -95,7 +95,7 @@ server:
# If your instance owns a /etc/searxng/settings.yml file, then set the following # If your instance owns a /etc/searxng/settings.yml file, then set the following
# values there. # values there.
secret_key: "ultrasecretkey" # Is overwritten by ${SEARXNG_SECRET} secret_key: "supersecret" # Is overwritten by ${SEARXNG_SECRET},W
# Proxy image results through SearXNG. Is overwritten by ${SEARXNG_IMAGE_PROXY} # Proxy image results through SearXNG. Is overwritten by ${SEARXNG_IMAGE_PROXY}
image_proxy: false image_proxy: false
# 1.0 and 1.1 are supported # 1.0 and 1.1 are supported
+53
View File
@@ -0,0 +1,53 @@
[uwsgi]
# Who will run the code
uid = searxng
gid = searxng
# Number of workers (usually CPU count)
# default value: %k (= number of CPU core, see Dockerfile)
workers = 1
# Number of threads per worker
# default value: 4 (see Dockerfile)
enable-threads = true
threads = 1
# The right granted on the created socket
chmod-socket = 666
# Plugin to use and interpreter config
single-interpreter = true
master = true
plugin = python3
lazy-apps = true
enable-threads = 4
# Module to import
module = searx.webapp
# Virtualenv and python path
pythonpath = /usr/local/searxng/
chdir = /usr/local/searxng/searx/
# automatically set processes name to something meaningful
auto-procname = true
# Disable request logging for privacy
disable-logging = true
log-5xx = true
# Set the max size of a request (request-body excluded)
buffer-size = 8192
# No keep alive
# See https://github.com/searx/searx-docker/issues/24
add-header = Connection: close
# Follow SIGTERM convention
# See https://github.com/searxng/searxng/issues/3427
die-on-term
# uwsgi serves the static files
static-map = /static=/usr/local/searxng/searx/static
static-gzip-all = True
offload-threads = 4
-30
View File
@@ -1,30 +0,0 @@
{
"model_name": "deepseek-r1:14b",
"known_models": [
"qwq:32b",
"deepseek-r1:1.5b",
"deepseek-r1:7b",
"deepseek-r1:14b",
"deepseek-r1:32b",
"deepseek-r1:70b",
"deepseek-r1:671b",
"deepseek-coder:1.3b",
"deepseek-coder:6.7b",
"deepseek-coder:33b",
"llama2-uncensored:7b",
"llama2-uncensored:70b",
"llama3.1:8b",
"llama3.1:70b",
"llama3.3:70b",
"llama3:8b",
"llama3:70b",
"i4:14b",
"mistral:7b",
"mistral:70b",
"mistral:33b",
"qwen1:7b",
"qwen1:14b",
"qwen1:32b",
"qwen1:70b"
]
}
-2
View File
@@ -1,2 +0,0 @@
flask>=2.3.0
ollama>=0.4.7
-99
View File
@@ -1,99 +0,0 @@
from flask import Flask, jsonify, request
import threading
import ollama
import logging
import json
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
app = Flask(__name__)
# Shared state with thread-safe locks
class Config:
def __init__(self):
self.model = None
self.known_models = []
self.allowed_models = []
self.model_name = None
def load(self):
with open('config.json', 'r') as f:
data = json.load(f)
self.known_models = data['known_models']
self.model_name = data['model_name']
def validate_model(self, model):
if model not in self.known_models:
raise ValueError(f"Model {model} is not known")
class GenerationState:
def __init__(self):
self.lock = threading.Lock()
self.last_complete_sentence = ""
self.current_buffer = ""
self.is_generating = False
self.model = None
state = GenerationState()
def generate_response_vllm(history):
pass
def generate_response_ollama(history): # Only takes history as an argument
global state
try:
with state.lock:
state.is_generating = True
state.last_complete_sentence = ""
state.current_buffer = ""
stream = ollama.chat(
model=state.model, # Access state.model directly
messages=history,
stream=True,
)
for chunk in stream:
content = chunk['message']['content']
print(content, end='', flush=True)
with state.lock:
state.current_buffer += content
except ollama.ResponseError as e:
if e.status_code == 404:
ollama.pull(state.model)
with state.lock:
state.is_generating = False
print(f"Error: {e}")
finally:
with state.lock:
state.is_generating = False
@app.route('/generate', methods=['POST'])
def start_generation():
global state
data = request.get_json()
with state.lock:
if state.is_generating:
return jsonify({"error": "Generation already in progress"}), 400
history = data.get('messages', [])
# Pass only history to the thread
threading.Thread(target=generate_response, args=(history,)).start() # Note the comma to make it a single-element tuple
return jsonify({"message": "Generation started"}), 202
@app.route('/get_updated_sentence')
def get_updated_sentence():
global state
with state.lock:
return jsonify({
"sentence": state.current_buffer,
"is_complete": not state.is_generating
})
if __name__ == '__main__':
config = Config()
config.load()
config.validate_model(config.model_name)
state.model = config.model_name
app.run(host='0.0.0.0', port=5000, debug=False, threaded=True)
+16 -2
View File
@@ -15,8 +15,16 @@ setup(
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
install_requires=[ install_requires=[
"fastapi>=0.115.12",
"celery>=5.5.1",
"uvicorn>=0.34.0",
"flask>=3.1.0",
"aiofiles>=24.1.0",
"pydantic>=2.10.6",
"pydantic_core>=2.27.2",
"requests>=2.31.0", "requests>=2.31.0",
"openai", "sacremoses>=0.0.53",
"numpy>=1.24.4",
"colorama>=0.4.6", "colorama>=0.4.6",
"python-dotenv>=1.0.0", "python-dotenv>=1.0.0",
"playsound>=1.3.0", "playsound>=1.3.0",
@@ -26,7 +34,6 @@ setup(
"ollama>=0.4.7", "ollama>=0.4.7",
"scipy>=1.9.3", "scipy>=1.9.3",
"kokoro>=0.7.12", "kokoro>=0.7.12",
"flask>=3.1.0",
"protobuf>=3.20.3", "protobuf>=3.20.3",
"termcolor>=2.5.0", "termcolor>=2.5.0",
"ipython>=8.34.0", "ipython>=8.34.0",
@@ -35,11 +42,18 @@ setup(
"markdownify>=1.1.0", "markdownify>=1.1.0",
"text2emotion>=0.0.5", "text2emotion>=0.0.5",
"python-dotenv>=1.0.0", "python-dotenv>=1.0.0",
"adaptive-classifier>=0.0.10",
"langid>=1.1.6", "langid>=1.1.6",
"chromedriver-autoinstaller>=0.6.4",
"httpx>=0.27,<0.29", "httpx>=0.27,<0.29",
"anyio>=3.5.0,<5", "anyio>=3.5.0,<5",
"distro>=1.7.0,<2", "distro>=1.7.0,<2",
"jiter>=0.4.0,<1", "jiter>=0.4.0,<1",
"fake_useragent>=2.1.0",
"selenium_stealth>=1.0.6",
"undetected-chromedriver>=3.5.5",
"sentencepiece>=0.2.0",
"openai",
"sniffio", "sniffio",
"tqdm>4" "tqdm>4"
], ],
+2 -1
View File
@@ -5,5 +5,6 @@ from .casual_agent import CasualAgent
from .file_agent import FileAgent from .file_agent import FileAgent
from .planner_agent import PlannerAgent from .planner_agent import PlannerAgent
from .browser_agent import BrowserAgent from .browser_agent import BrowserAgent
from .mcp_agent import McpAgent
__all__ = ["Agent", "CoderAgent", "CasualAgent", "FileAgent", "PlannerAgent", "BrowserAgent"] __all__ = ["Agent", "CoderAgent", "CasualAgent", "FileAgent", "PlannerAgent", "BrowserAgent", "McpAgent"]
+144 -39
View File
@@ -5,57 +5,110 @@ import os
import random import random
import time import time
import asyncio
from concurrent.futures import ThreadPoolExecutor
from sources.memory import Memory from sources.memory import Memory
from sources.utility import pretty_print from sources.utility import pretty_print
from sources.schemas import executorResult
random.seed(time.time()) random.seed(time.time())
class executorResult:
"""
A class to store the result of a tool execution.
"""
def __init__(self, blocks, feedback, success):
self.blocks = blocks
self.feedback = feedback
self.success = success
def show(self):
for block in self.blocks:
pretty_print("-"*100, color="output")
pretty_print(block, color="code" if self.success else "failure")
pretty_print("-"*100, color="output")
pretty_print(self.feedback, color="success" if self.success else "failure")
class Agent(): class Agent():
""" """
An abstract class for all agents. An abstract class for all agents.
""" """
def __init__(self, model: str, def __init__(self, name: str,
name: str,
prompt_path:str, prompt_path:str,
provider, provider,
recover_last_session=True) -> None: verbose=False,
browser=None) -> None:
"""
Args:
name (str): Name of the agent.
prompt_path (str): Path to the prompt file for the agent.
provider: The provider for the LLM.
recover_last_session (bool, optional): Whether to recover the last conversation.
verbose (bool, optional): Enable verbose logging if True. Defaults to False.
browser: The browser class for web navigation (only for browser agent).
"""
self.agent_name = name self.agent_name = name
self.browser = browser
self.role = None self.role = None
self.type = None
self.current_directory = os.getcwd() self.current_directory = os.getcwd()
self.model = model
self.llm = provider self.llm = provider
self.memory = Memory(self.load_prompt(prompt_path), self.memory = None
recover_last_session=recover_last_session,
memory_compression=False)
self.tools = {} self.tools = {}
self.blocks_result = [] self.blocks_result = []
self.success = True
self.last_answer = "" self.last_answer = ""
self.last_reasoning = ""
self.status_message = "Haven't started yet"
self.stop = False
self.verbose = verbose
self.executor = ThreadPoolExecutor(max_workers=1)
@property
def get_agent_name(self) -> str:
return self.agent_name
@property
def get_agent_type(self) -> str:
return self.type
@property
def get_agent_role(self) -> str:
return self.role
@property
def get_last_answer(self) -> str:
return self.last_answer
@property
def get_last_reasoning(self) -> str:
return self.last_reasoning
@property
def get_blocks(self) -> list:
return self.blocks_result
@property
def get_status_message(self) -> str:
return self.status_message
@property @property
def get_tools(self) -> dict: def get_tools(self) -> dict:
return self.tools return self.tools
@property
def get_success(self) -> bool:
return self.success
def get_blocks_result(self) -> list:
return self.blocks_result
def add_tool(self, name: str, tool: Callable) -> None: def add_tool(self, name: str, tool: Callable) -> None:
if tool is not Callable: if tool is not Callable:
raise TypeError("Tool must be a callable object (a method)") raise TypeError("Tool must be a callable object (a method)")
self.tools[name] = tool self.tools[name] = tool
def get_tools_name(self) -> list:
"""
Get the list of tools names.
"""
return list(self.tools.keys())
def get_tools_description(self) -> str:
"""
Get the list of tools names and their description.
"""
description = ""
for name in self.get_tools_name():
description += f"{name}: {self.tools[name].description}\n"
return description
def load_prompt(self, file_path: str) -> str: def load_prompt(self, file_path: str) -> str:
try: try:
with open(file_path, 'r', encoding="utf-8") as f: with open(file_path, 'r', encoding="utf-8") as f:
@@ -67,6 +120,13 @@ class Agent():
except Exception as e: except Exception as e:
raise e raise e
def request_stop(self) -> None:
"""
Request the agent to stop.
"""
self.stop = True
self.status_message = "Stopped"
@abstractmethod @abstractmethod
def process(self, prompt, speech_module) -> str: def process(self, prompt, speech_module) -> str:
""" """
@@ -80,48 +140,80 @@ class Agent():
Remove the reasoning block of reasoning model like deepseek. Remove the reasoning block of reasoning model like deepseek.
""" """
end_tag = "</think>" end_tag = "</think>"
end_idx = text.rfind(end_tag)+8 end_idx = text.rfind(end_tag)
return text[end_idx:] if end_idx == -1:
return text
return text[end_idx+8:]
def extract_reasoning_text(self, text: str) -> None: def extract_reasoning_text(self, text: str) -> None:
""" """
Extract the reasoning block of a easoning model like deepseek. Extract the reasoning block of a reasoning model like deepseek.
""" """
start_tag = "<think>" start_tag = "<think>"
end_tag = "</think>" end_tag = "</think>"
if text is None:
return None
start_idx = text.find(start_tag) start_idx = text.find(start_tag)
end_idx = text.rfind(end_tag)+8 end_idx = text.rfind(end_tag)+8
return text[start_idx:end_idx] return text[start_idx:end_idx]
def llm_request(self, verbose = False) -> Tuple[str, str]: async def llm_request(self) -> Tuple[str, str]:
"""
Asynchronously ask the LLM to process the prompt.
"""
self.status_message = "Thinking..."
loop = asyncio.get_event_loop()
return await loop.run_in_executor(self.executor, self.sync_llm_request)
def sync_llm_request(self) -> Tuple[str, str]:
""" """
Ask the LLM to process the prompt and return the answer and the reasoning. Ask the LLM to process the prompt and return the answer and the reasoning.
""" """
memory = self.memory.get() memory = self.memory.get()
thought = self.llm.respond(memory, verbose) thought = self.llm.respond(memory, self.verbose)
reasoning = self.extract_reasoning_text(thought) reasoning = self.extract_reasoning_text(thought)
answer = self.remove_reasoning_text(thought) answer = self.remove_reasoning_text(thought)
self.memory.push('assistant', answer) self.memory.push('assistant', answer)
return answer, reasoning return answer, reasoning
def wait_message(self, speech_module): async def wait_message(self, speech_module):
if speech_module is None: if speech_module is None:
return return
messages = ["Please be patient, I am working on it.", messages = ["Please be patient, I am working on it.",
"Computing... I recommand you have a coffee while I work.", "Computing... I recommand you have a coffee while I work.",
"Hold on, Im crunching numbers.", "Hold on, Im crunching numbers.",
"Working on it, please let me think."] "Working on it, please let me think."]
speech_module.speak(messages[random.randint(0, len(messages)-1)]) loop = asyncio.get_event_loop()
return await loop.run_in_executor(self.executor, lambda: speech_module.speak(messages[random.randint(0, len(messages)-1)]))
def get_blocks_result(self) -> list: def get_last_tool_type(self) -> str:
return self.blocks_result return self.blocks_result[-1].tool_type if len(self.blocks_result) > 0 else None
def raw_answer_blocks(self, answer: str) -> str:
"""
Return the answer with all the blocks inserted, as text.
"""
if self.last_answer is None:
return
raw = ""
lines = self.last_answer.split("\n")
for line in lines:
if "block:" in line:
block_idx = int(line.split(":")[1])
if block_idx < len(self.blocks_result):
raw += self.blocks_result[block_idx].__str__()
else:
raw += line + "\n"
return raw
def show_answer(self): def show_answer(self):
""" """
Show the answer in a pretty way. Show the answer in a pretty way.
Show code blocks and their respective feedback by inserting them in the ressponse. Show code blocks and their respective feedback by inserting them in the ressponse.
""" """
if self.last_answer is None:
return
lines = self.last_answer.split("\n") lines = self.last_answer.split("\n")
for line in lines: for line in lines:
if "block:" in line: if "block:" in line:
@@ -130,7 +222,6 @@ class Agent():
self.blocks_result[block_idx].show() self.blocks_result[block_idx].show()
else: else:
pretty_print(line, color="output") pretty_print(line, color="output")
self.blocks_result = []
def remove_blocks(self, text: str) -> str: def remove_blocks(self, text: str) -> str:
""" """
@@ -153,28 +244,42 @@ class Agent():
block_idx += 1 block_idx += 1
return "\n".join(post_lines) return "\n".join(post_lines)
def show_block(self, block: str) -> None:
"""
Show the block in a pretty way.
"""
pretty_print(''*64, color="status")
pretty_print(block, color="code")
pretty_print(''*64, color="status")
def execute_modules(self, answer: str) -> Tuple[bool, str]: def execute_modules(self, answer: str) -> Tuple[bool, str]:
""" """
Execute all the tools the agent has and return the result. Execute all the tools the agent has and return the result.
""" """
feedback = "" feedback = ""
success = False success = True
blocks = None blocks = None
if answer.startswith("```"):
answer = "I will execute:\n" + answer # there should always be a text before blocks for the function that display answer
self.success = True
for name, tool in self.tools.items(): for name, tool in self.tools.items():
feedback = "" feedback = ""
blocks, save_path = tool.load_exec_block(answer) blocks, save_path = tool.load_exec_block(answer)
if blocks != None: if blocks != None:
pretty_print(f"Executing tool: {name}", color="status") pretty_print(f"Executing {len(blocks)} {name} blocks...", color="status")
output = tool.execute(blocks) for block in blocks:
self.show_block(block)
output = tool.execute([block])
feedback = tool.interpreter_feedback(output) # tool interpreter feedback feedback = tool.interpreter_feedback(output) # tool interpreter feedback
success = not tool.execution_failure_check(output) success = not tool.execution_failure_check(output)
pretty_print(feedback, color="success" if success else "failure") self.blocks_result.append(executorResult(block, feedback, success, name))
self.memory.push('user', feedback)
self.blocks_result.append(executorResult(blocks, feedback, success))
if not success: if not success:
self.success = False
self.memory.push('user', feedback)
return False, feedback return False, feedback
self.memory.push('user', feedback)
if save_path != None: if save_path != None:
tool.save_block(blocks, save_path) tool.save_block(blocks, save_path)
return True, feedback return True, feedback
+293 -87
View File
@@ -1,126 +1,201 @@
import re import re
import time import time
from datetime import date
from typing import List, Tuple, Type, Dict
from enum import Enum
import asyncio
from sources.utility import pretty_print, animate_thinking from sources.utility import pretty_print, animate_thinking
from sources.agents.agent import Agent from sources.agents.agent import Agent
from sources.tools.searxSearch import searxSearch from sources.tools.searxSearch import searxSearch
from sources.browser import Browser from sources.browser import Browser
from datetime import date from sources.logger import Logger
from sources.memory import Memory
class Action(Enum):
REQUEST_EXIT = "REQUEST_EXIT"
FORM_FILLED = "FORM_FILLED"
GO_BACK = "GO_BACK"
NAVIGATE = "NAVIGATE"
SEARCH = "SEARCH"
class BrowserAgent(Agent): class BrowserAgent(Agent):
def __init__(self, model, name, prompt_path, provider): def __init__(self, name, prompt_path, provider, verbose=False, browser=None):
""" """
The Browser agent is an agent that navigate the web autonomously in search of answer The Browser agent is an agent that navigate the web autonomously in search of answer
""" """
super().__init__(model, name, prompt_path, provider) super().__init__(name, prompt_path, provider, verbose, browser)
self.tools = { self.tools = {
"web_search": searxSearch(), "web_search": searxSearch(),
} }
self.role = "Web Research" self.role = "web"
self.browser = Browser() self.type = "browser_agent"
self.browser = browser
self.current_page = ""
self.search_history = [] self.search_history = []
self.navigable_links = [] self.navigable_links = []
self.last_action = Action.NAVIGATE.value
self.notes = [] self.notes = []
self.date = self.get_today_date() self.date = self.get_today_date()
self.logger = Logger("browser_agent.log")
self.memory = Memory(self.load_prompt(prompt_path),
recover_last_session=False, # session recovery in handled by the interaction class
memory_compression=False,
model_provider=provider.get_model_name())
def get_today_date(self) -> str: def get_today_date(self) -> str:
"""Get the date"""
date_time = date.today() date_time = date.today()
return date_time.strftime("%B %d, %Y") return date_time.strftime("%B %d, %Y")
def extract_links(self, search_result: str): def extract_links(self, search_result: str) -> List[str]:
"""Extract all links from a sentence."""
pattern = r'(https?://\S+|www\.\S+)' pattern = r'(https?://\S+|www\.\S+)'
matches = re.findall(pattern, search_result) matches = re.findall(pattern, search_result)
trailing_punct = ".,!?;:" trailing_punct = ".,!?;:)"
cleaned_links = [link.rstrip(trailing_punct) for link in matches] cleaned_links = [link.rstrip(trailing_punct) for link in matches]
self.logger.info(f"Extracted links: {cleaned_links}")
return self.clean_links(cleaned_links) return self.clean_links(cleaned_links)
def clean_links(self, links: list): def extract_form(self, text: str) -> List[str]:
"""Extract form written by the LLM in format [input_name](value)"""
inputs = []
matches = re.findall(r"\[\w+\]\([^)]+\)", text)
return matches
def clean_links(self, links: List[str]) -> List[str]:
"""Ensure no '.' at the end of link"""
links_clean = [] links_clean = []
for link in links: for link in links:
link = link.strip() link = link.strip()
if link[-1] == '.': if not (link[-1].isalpha() or link[-1].isdigit()):
links_clean.append(link[:-1]) links_clean.append(link[:-1])
else: else:
links_clean.append(link) links_clean.append(link)
return links_clean return links_clean
def get_unvisited_links(self): def get_unvisited_links(self) -> List[str]:
return "\n".join([f"[{i}] {link}" for i, link in enumerate(self.navigable_links) if link not in self.search_history]) return "\n".join([f"[{i}] {link}" for i, link in enumerate(self.navigable_links) if link not in self.search_history])
def make_newsearch_prompt(self, user_prompt: str, search_result: dict): def make_newsearch_prompt(self, user_prompt: str, search_result: dict) -> str:
search_choice = self.stringify_search_results(search_result) search_choice = self.stringify_search_results(search_result)
self.logger.info(f"Search results: {search_choice}")
return f""" return f"""
Based on the search result: Based on the search result:
{search_choice} {search_choice}
Your goal is to find accurate and complete information to satisfy the users request. Your goal is to find accurate and complete information to satisfy the users request.
User request: {user_prompt} User request: {user_prompt}
To proceed, choose a relevant link from the search results. Announce your choice by saying: "I want to navigate to <link>" To proceed, choose a relevant link from the search results. Announce your choice by saying: "I will navigate to <link>"
Do not explain your choice. Do not explain your choice.
""" """
def make_navigation_prompt(self, user_prompt: str, page_text: str): def make_navigation_prompt(self, user_prompt: str, page_text: str) -> str:
remaining_links = self.get_unvisited_links() remaining_links = self.get_unvisited_links()
remaining_links_text = remaining_links if remaining_links is not None else "No links remaining, proceed with a new search." remaining_links_text = remaining_links if remaining_links is not None else "No links remaining, do a new search."
inputs_form = self.browser.get_form_inputs()
inputs_form_text = '\n'.join(inputs_form)
notes = '\n'.join(self.notes)
self.logger.info(f"Making navigation prompt with page text: {page_text[:100]}...\nremaining links: {remaining_links_text}")
self.logger.info(f"Inputs form: {inputs_form_text}")
self.logger.info(f"Notes: {notes}")
return f""" return f"""
You are a web browser. You are navigating the web.
You are currently on this webpage:
**Current Context**
Webpage ({self.current_page}) content:
{page_text} {page_text}
You can navigate to these navigation links: Allowed Navigation Links:
{remaining_links} {remaining_links_text}
Your task: Inputs forms:
1. Decide if the current page answers the users query: {user_prompt} {inputs_form_text}
- If it does, take notes of the useful information, write down source, link or reference, then move to a new page.
- If it does and you are 100% certain that it provide a definive answer, say REQUEST_EXIT
- If it doesnt, say: Error: This page does not answer the users query then go back or navigate to another link.
2. Navigate by either:
- Navigate to a navigation links (write the full URL, e.g., www.example.com/cats).
- If no link seems helpful, say: GO_BACK.
Recap of note taking: End of webpage ({self.current_page}.
If useful -> Note: [Briefly summarize the key information that answers the users query.]
Do not write "The page talk about ...", write your finding on the page and how they contribute to an answer.
If not useful -> Error: [Explain why the page doesnt help.]
Example 1 (useful page, no need of going futher): # Instruction
Note: According to karpathy site (https://karpathy.github.io/) LeCun net is the earliest real-world application of a neural net"
No link seem useful to provide futher information. GO_BACK
Example 2 (not useful, but related link): 1. **Evaluate if the page is relevant for users query and document finding:**
Error: This forum reddit.com/welcome does not discuss anything related to the users query. - If the page is relevant, extract and summarize key information in concise notes (Note: <your note>)
There is a link that could lead to the information, I want to navigate to http://reddit.com/r/locallama - If page not relevant, state: "Error: <specific reason the page does not address the query>" and either return to the previous page or navigate to a new link.
- Notes should be factual, useful summaries of relevant content, they should always include specific names or link. Written as: "On <website URL>, <key fact 1>. <Key fact 2>. <Additional insight>." Avoid phrases like "the page provides" or "I found that."
2. **Navigate to a link by either: **
- Saying I will navigate to (write down the full URL) www.example.com/cats
- Going back: If no link seems helpful, say: {Action.GO_BACK.value}.
3. **Fill forms on the page:**
- Fill form only when relevant.
- Use Login if username/password specified by user. For quick task create account, remember password in a note.
- You can fill a form using [form_name](value). Don't {Action.GO_BACK.value} when filling form.
- If a form is irrelevant or you lack informations (eg: don't know user email) leave it empty.
4. **Decide if you completed the task**
- Check your notes. Do they fully answer the question? Did you verify with multiple pages?
- Are you sure its correct?
- If yes to all, say {Action.REQUEST_EXIT}.
- If no, or a page lacks info, go to another link.
- Never stop or ask the user for help.
**Rules:**
- Do not write "The page talk about ...", write your finding on the page and how they contribute to an answer.
- Put note in a single paragraph.
- When you exit, explain why.
# Example:
Example 1 (useful page, no need go futher):
Note: According to karpathy site LeCun net is ...
No link seem useful to provide futher information.
Action: {Action.GO_BACK.value}
Example 2 (not useful, see useful link on page):
Error: reddit.com/welcome does not discuss anything related to the users query.
There is a link that could lead to the information.
Action: navigate to http://reddit.com/r/locallama
Example 3 (not useful, no related links): Example 3 (not useful, no related links):
Error: x.com does not discuss anything related to the users query and no navigation link are usefull Error: x.com does not discuss anything related to the users query and no navigation link are usefull.
GO_BACK Action: {Action.GO_BACK.value}
Example 3 (query answer found): Example 3 (clear definitive query answer found or enought notes taken):
Note: I found on github.com that agenticSeek is Fosowl. I took 10 notes so far with enought finding to answer user question.
Given this information, given this I should exit the web browser. REQUEST_EXIT Therefore I should exit the web browser.
Action: {Action.REQUEST_EXIT.value}
Current date: {self.date} Example 4 (loging form visible):
Remember, the user asked: {user_prompt}
Do not explain your choice. Note: I am on the login page, I will type the given username and password.
Action:
[username_field](David)
[password_field](edgerunners77)
Remember, user asked:
{user_prompt}
You previously took these notes:
{notes}
Do not Step-by-Step explanation. Write comprehensive Notes or Error as a long paragraph followed by your action.
You must always take notes.
""" """
def llm_decide(self, prompt): async def llm_decide(self, prompt: str, show_reasoning: bool = False) -> Tuple[str, str]:
animate_thinking("Thinking...", color="status") animate_thinking("Thinking...", color="status")
self.memory.push('user', prompt) self.memory.push('user', prompt)
answer, reasoning = self.llm_request() answer, reasoning = await self.llm_request()
pretty_print("-"*100) self.last_reasoning = reasoning
if show_reasoning:
pretty_print(reasoning, color="failure")
pretty_print(answer, color="output") pretty_print(answer, color="output")
pretty_print("-"*100)
return answer, reasoning return answer, reasoning
def select_unvisited(self, search_result): def select_unvisited(self, search_result: List[str]) -> List[str]:
results_unvisited = [] results_unvisited = []
for res in search_result: for res in search_result:
if res["link"] not in self.search_history: if res["link"] not in self.search_history:
results_unvisited.append(res) results_unvisited.append(res)
self.logger.info(f"Unvisited links: {results_unvisited}")
return results_unvisited return results_unvisited
def jsonify_search_results(self, results_string): def jsonify_search_results(self, results_string: str) -> List[str]:
result_blocks = results_string.split("\n\n") result_blocks = results_string.split("\n\n")
parsed_results = [] parsed_results = []
for block in result_blocks: for block in result_blocks:
@@ -139,36 +214,67 @@ class BrowserAgent(Agent):
parsed_results.append(result_dict) parsed_results.append(result_dict)
return parsed_results return parsed_results
def stringify_search_results(self, results_arr): def stringify_search_results(self, results_arr: List[str]) -> str:
return '\n\n'.join([f"Link: {res['link']}" for res in results_arr]) return '\n\n'.join([f"Link: {res['link']}\nPreview: {res['snippet']}" for res in results_arr])
def save_notes(self, text): def parse_answer(self, text):
lines = text.split('\n') lines = text.split('\n')
saving = False
buffer = []
links = []
for line in lines: for line in lines:
if line == '' or 'action:' in line.lower():
saving = False
if "note" in line.lower(): if "note" in line.lower():
self.notes.append(line) saving = True
if saving:
buffer.append(line.replace("notes:", ''))
else:
links.extend(self.extract_links(line))
self.notes.append('. '.join(buffer).strip())
return links
def conclude_prompt(self, user_query): def select_link(self, links: List[str]) -> str | None:
annotated_notes = [f"{i+1}: {note.lower().replace('note:', '')}" for i, note in enumerate(self.notes)] for lk in links:
if lk == self.current_page:
self.logger.info(f"Already visited {lk}. Skipping.")
continue
self.logger.info(f"Selected link: {lk}")
return lk
self.logger.warning("No link selected.")
return None
def get_page_text(self, limit_to_model_ctx = False) -> str:
"""Get the text content of the current page."""
page_text = self.browser.get_text()
if limit_to_model_ctx:
#page_text = self.memory.compress_text_to_max_ctx(page_text)
page_text = self.memory.trim_text_to_max_ctx(page_text)
return page_text
def conclude_prompt(self, user_query: str) -> str:
annotated_notes = [f"{i+1}: {note.lower()}" for i, note in enumerate(self.notes)]
search_note = '\n'.join(annotated_notes) search_note = '\n'.join(annotated_notes)
print("AI research notes:\n", search_note) pretty_print(f"AI notes:\n{search_note}", color="success")
return f""" return f"""
Following a human request: Following a human request:
{user_query} {user_query}
A web AI made the following finding across different pages: A web browsing AI made the following finding across different pages:
{search_note} {search_note}
Summarize the finding, and provide a conclusion that answer the request. Expand on the finding or step that lead to success, and provide a conclusion that answer the request. Include link when possible.
Do not give advices or try to answer the human. Just structure the AI finding in a structured and clear way.
You should answer in the same language as the user.
""" """
def search_prompt(self, user_prompt): def search_prompt(self, user_prompt: str) -> str:
return f""" return f"""
Current date: {self.date} Current date: {self.date}
Make a efficient search engine query to help users with their request: Make a efficient search engine query to help users with their request:
{user_prompt} {user_prompt}
Example: Example:
User: "search: hey jarvis i want you to login to my twitter and say hello everyone " User: "go to twitter, login with username toto and password pass79 to my twitter and say hello everyone "
You: Twitter You: search: Twitter login page.
User: "I need info on the best laptops for AI this year." User: "I need info on the best laptops for AI this year."
You: "search: best laptops 2025 to run Machine Learning model, reviews" You: "search: best laptops 2025 to run Machine Learning model, reviews"
@@ -177,47 +283,147 @@ class BrowserAgent(Agent):
You: "search: Recent space missions news, {self.date}" You: "search: Recent space missions news, {self.date}"
Do not explain, do not write anything beside the search query. Do not explain, do not write anything beside the search query.
Except if query does not make any sense for a web search then explain why and say {Action.REQUEST_EXIT.value}
Do not try to answer query. you can only formulate search term or exit.
""" """
def process(self, user_prompt, speech_module) -> str: def handle_update_prompt(self, user_prompt: str, page_text: str, fill_success: bool) -> str:
prompt = f"""
You are a web browser.
You just filled a form on the page.
Now you should see the result of the form submission on the page:
Page text:
{page_text}
The user asked: {user_prompt}
Does the page answer the users query now? Are you still on a login page or did you get redirected?
If it does, take notes of the useful information, write down result and say {Action.FORM_FILLED.value}.
if it doesnt, say: Error: Attempt to fill form didn't work {Action.GO_BACK.value}.
If you were previously on a login form, no need to take notes.
"""
if not fill_success:
prompt += f"""
According to browser feedback, the form was not filled correctly. Is that so? you might consider other strategies.
"""
return prompt
def show_search_results(self, search_result: List[str]):
pretty_print("\nSearch results:", color="output")
for res in search_result:
pretty_print(f"Title: {res['title']} - ", color="info", no_newline=True)
pretty_print(f"Link: {res['link']}", color="status")
def stuck_prompt(self, user_prompt: str, unvisited: List[str]) -> str:
"""
Prompt for when the agent repeat itself, can happen when fail to extract a link.
"""
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
prompt += f"""
You previously said:
{self.last_answer}
You must consider other options. Choose other link.
"""
return prompt
async def process(self, user_prompt: str, speech_module: type) -> Tuple[str, str]:
"""
Process the user prompt to conduct an autonomous web search.
Start with a google search with searxng using web_search tool.
Then enter a navigation logic to find the answer or conduct required actions.
Args:
user_prompt: The user's input query
speech_module: Optional speech output module
Returns:
tuple containing the final answer and reasoning
"""
complete = False complete = False
animate_thinking(f"Thinking...", color="status") animate_thinking(f"Thinking...", color="status")
self.memory.push('user', self.search_prompt(user_prompt)) mem_begin_idx = self.memory.push('user', self.search_prompt(user_prompt))
ai_prompt, _ = self.llm_request() ai_prompt, reasoning = await self.llm_request()
if Action.REQUEST_EXIT.value in ai_prompt:
pretty_print(f"Web agent requested exit.\n{reasoning}\n\n{ai_prompt}", color="failure")
return ai_prompt, ""
animate_thinking(f"Searching...", color="status") animate_thinking(f"Searching...", color="status")
self.status_message = "Searching..."
search_result_raw = self.tools["web_search"].execute([ai_prompt], False) search_result_raw = self.tools["web_search"].execute([ai_prompt], False)
search_result = self.jsonify_search_results(search_result_raw)[:7] # until futher improvement search_result = self.jsonify_search_results(search_result_raw)[:16]
self.show_search_results(search_result)
prompt = self.make_newsearch_prompt(user_prompt, search_result) prompt = self.make_newsearch_prompt(user_prompt, search_result)
unvisited = [None] unvisited = [None]
while not complete: while not complete and len(unvisited) > 0 and not self.stop:
answer, reasoning = self.llm_decide(prompt) self.memory.clear()
self.save_notes(answer)
if "REQUEST_EXIT" in answer:
complete = True
break
links = self.extract_links(answer)
if len(unvisited) == 0:
break
if len(links) == 0 or "GO_BACK" in answer:
unvisited = self.select_unvisited(search_result) unvisited = self.select_unvisited(search_result)
prompt = self.make_newsearch_prompt(user_prompt, unvisited) answer, reasoning = await self.llm_decide(prompt, show_reasoning = False)
pretty_print(f"Going back to results. Still {len(unvisited)}", color="warning") if self.stop:
links = [] pretty_print(f"Requested stop.", color="failure")
break
if self.last_answer == answer:
prompt = self.stuck_prompt(user_prompt, unvisited)
continue continue
animate_thinking(f"Navigating to {links[0]}", color="status") self.last_answer = answer
speech_module.speak(f"Navigating to {links[0]}") pretty_print(''*32, color="status")
self.browser.go_to(links[0])
self.search_history.append(links[0]) extracted_form = self.extract_form(answer)
page_text = self.browser.get_text() if len(extracted_form) > 0:
self.status_message = "Filling web form..."
pretty_print(f"Filling inputs form...", color="status")
fill_success = self.browser.fill_form(extracted_form)
page_text = self.get_page_text(limit_to_model_ctx=True)
answer = self.handle_update_prompt(user_prompt, page_text, fill_success)
answer, reasoning = await self.llm_decide(prompt)
if Action.FORM_FILLED.value in answer:
pretty_print(f"Filled form. Handling page update.", color="status")
page_text = self.get_page_text(limit_to_model_ctx=True)
self.navigable_links = self.browser.get_navigable() self.navigable_links = self.browser.get_navigable()
prompt = self.make_navigation_prompt(user_prompt, page_text) prompt = self.make_navigation_prompt(user_prompt, page_text)
continue
self.browser.close() links = self.parse_answer(answer)
link = self.select_link(links)
if link == self.current_page:
pretty_print(f"Already visited {link}. Search callback.", color="status")
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
self.search_history.append(link)
continue
if Action.REQUEST_EXIT.value in answer:
self.status_message = "Exiting web browser..."
pretty_print(f"Agent requested exit.", color="status")
complete = True
break
if (link == None and len(extracted_form) < 3) or Action.GO_BACK.value in answer or link in self.search_history:
pretty_print(f"Going back to results. Still {len(unvisited)}", color="status")
self.status_message = "Going back to search results..."
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
self.search_history.append(link)
self.current_page = link
continue
animate_thinking(f"Navigating to {link}", color="status")
if speech_module: speech_module.speak(f"Navigating to {link}")
nav_ok = self.browser.go_to(link)
self.search_history.append(link)
if not nav_ok:
pretty_print(f"Failed to navigate to {link}.", color="failure")
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
continue
self.current_page = link
page_text = self.get_page_text(limit_to_model_ctx=True)
self.navigable_links = self.browser.get_navigable()
prompt = self.make_navigation_prompt(user_prompt, page_text)
self.status_message = "Navigating..."
self.browser.screenshot()
pretty_print("Exited navigation, starting to summarize finding...", color="status")
prompt = self.conclude_prompt(user_prompt) prompt = self.conclude_prompt(user_prompt)
self.memory.push('user', prompt) mem_last_idx = self.memory.push('user', prompt)
answer, reasoning = self.llm_request() self.status_message = "Summarizing findings..."
answer, reasoning = await self.llm_request()
pretty_print(answer, color="output") pretty_print(answer, color="output")
self.status_message = "Ready"
self.last_answer = answer
return answer, reasoning return answer, reasoning
if __name__ == "__main__": if __name__ == "__main__":
+15 -27
View File
@@ -1,3 +1,4 @@
import asyncio
from sources.utility import pretty_print, animate_thinking from sources.utility import pretty_print, animate_thinking
from sources.agents.agent import Agent from sources.agents.agent import Agent
@@ -5,43 +6,30 @@ from sources.tools.searxSearch import searxSearch
from sources.tools.flightSearch import FlightSearch from sources.tools.flightSearch import FlightSearch
from sources.tools.fileFinder import FileFinder from sources.tools.fileFinder import FileFinder
from sources.tools.BashInterpreter import BashInterpreter from sources.tools.BashInterpreter import BashInterpreter
from sources.memory import Memory
class CasualAgent(Agent): class CasualAgent(Agent):
def __init__(self, model, name, prompt_path, provider): def __init__(self, name, prompt_path, provider, verbose=False):
""" """
The casual agent is a special for casual talk to the user without specific tasks. The casual agent is a special for casual talk to the user without specific tasks.
""" """
super().__init__(model, name, prompt_path, provider) super().__init__(name, prompt_path, provider, verbose, None)
self.tools = { self.tools = {
"web_search": searxSearch(), } # No tools for the casual agent
"flight_search": FlightSearch(), self.role = "talk"
"file_finder": FileFinder(), self.type = "casual_agent"
"bash": BashInterpreter() self.memory = Memory(self.load_prompt(prompt_path),
} recover_last_session=False, # session recovery in handled by the interaction class
self.role = "Chat and Conversation" memory_compression=False,
model_provider=provider.get_model_name())
def process(self, prompt, speech_module) -> str: async def process(self, prompt, speech_module) -> str:
complete = False
self.memory.push('user', prompt) self.memory.push('user', prompt)
self.wait_message(speech_module)
while not complete:
animate_thinking("Thinking...", color="status") animate_thinking("Thinking...", color="status")
answer, reasoning = self.llm_request() answer, reasoning = await self.llm_request()
exec_success, _ = self.execute_modules(answer)
answer = self.remove_blocks(answer)
self.last_answer = answer self.last_answer = answer
complete = True self.status_message = "Ready"
for tool in self.tools.values():
if tool.found_executable_blocks():
complete = False # AI read results and continue the conversation
return answer, reasoning return answer, reasoning
if __name__ == "__main__": if __name__ == "__main__":
from llm_provider import Provider pass
#local_provider = Provider("ollama", "deepseek-r1:14b", None)
server_provider = Provider("server", "deepseek-r1:14b", "192.168.1.100:5000")
agent = CasualAgent("deepseek-r1:14b", "jarvis", "prompts/casual_agent.txt", server_provider)
ans = agent.process("Hello, how are you?")
print(ans)
+55 -19
View File
@@ -1,3 +1,5 @@
import platform, os
import asyncio
from sources.utility import pretty_print, animate_thinking from sources.utility import pretty_print, animate_thinking
from sources.agents.agent import Agent, executorResult from sources.agents.agent import Agent, executorResult
@@ -5,50 +7,84 @@ from sources.tools.C_Interpreter import CInterpreter
from sources.tools.GoInterpreter import GoInterpreter from sources.tools.GoInterpreter import GoInterpreter
from sources.tools.PyInterpreter import PyInterpreter from sources.tools.PyInterpreter import PyInterpreter
from sources.tools.BashInterpreter import BashInterpreter from sources.tools.BashInterpreter import BashInterpreter
from sources.tools.JavaInterpreter import JavaInterpreter
from sources.tools.fileFinder import FileFinder from sources.tools.fileFinder import FileFinder
from sources.logger import Logger
from sources.memory import Memory
class CoderAgent(Agent): class CoderAgent(Agent):
""" """
The code agent is an agent that can write and execute code. The code agent is an agent that can write and execute code.
""" """
def __init__(self, model, name, prompt_path, provider): def __init__(self, name, prompt_path, provider, verbose=False):
super().__init__(model, name, prompt_path, provider) super().__init__(name, prompt_path, provider, verbose, None)
self.tools = { self.tools = {
"bash": BashInterpreter(), "bash": BashInterpreter(),
"python": PyInterpreter(), "python": PyInterpreter(),
"c": CInterpreter(), "c": CInterpreter(),
"go": GoInterpreter(), "go": GoInterpreter(),
"java": JavaInterpreter(),
"file_finder": FileFinder() "file_finder": FileFinder()
} }
self.role = "Code Assistance" self.work_dir = self.tools["file_finder"].get_work_dir()
self.role = "code"
self.type = "code_agent"
self.logger = Logger("code_agent.log")
self.memory = Memory(self.load_prompt(prompt_path),
recover_last_session=False, # session recovery in handled by the interaction class
memory_compression=False,
model_provider=provider.get_model_name())
def process(self, prompt, speech_module) -> str: def add_sys_info_prompt(self, prompt):
"""Add system information to the prompt."""
info = f"System Info:\n" \
f"OS: {platform.system()} {platform.release()}\n" \
f"Python Version: {platform.python_version()}\n" \
f"\nYou must save file at root directory: {self.work_dir}"
return f"{prompt}\n\n{info}"
async def process(self, prompt, speech_module) -> str:
answer = "" answer = ""
attempt = 0 attempt = 0
max_attempts = 3 max_attempts = 5
prompt = self.add_sys_info_prompt(prompt)
self.memory.push('user', prompt) self.memory.push('user', prompt)
clarify_trigger = "REQUEST_CLARIFICATION"
while attempt < max_attempts: while attempt < max_attempts and not self.stop:
print("Stopped?", self.stop)
animate_thinking("Thinking...", color="status") animate_thinking("Thinking...", color="status")
self.wait_message(speech_module) await self.wait_message(speech_module)
answer, reasoning = self.llm_request() answer, reasoning = await self.llm_request()
animate_thinking("Executing code...", color="status") self.last_reasoning = reasoning
exec_success, _ = self.execute_modules(answer) if clarify_trigger in answer:
answer = self.remove_blocks(answer)
self.last_answer = answer self.last_answer = answer
if exec_success: await asyncio.sleep(0)
return answer, reasoning
if not "```" in answer:
self.last_answer = answer
await asyncio.sleep(0)
break break
self.show_answer() self.show_answer()
animate_thinking("Executing code...", color="status")
self.status_message = "Executing code..."
self.logger.info(f"Attempt {attempt + 1}:\n{answer}")
exec_success, feedback = self.execute_modules(answer)
self.logger.info(f"Execution result: {exec_success}")
answer = self.remove_blocks(answer)
self.last_answer = answer
await asyncio.sleep(0)
if exec_success and self.get_last_tool_type() != "bash":
break
pretty_print(f"Execution failure:\n{feedback}", color="failure")
pretty_print("Correcting code...", color="status")
self.status_message = "Correcting code..."
attempt += 1 attempt += 1
self.status_message = "Ready"
if attempt == max_attempts: if attempt == max_attempts:
return "I'm sorry, I couldn't find a solution to your problem. How would you like me to proceed ?", reasoning return "I'm sorry, I couldn't find a solution to your problem. How would you like me to proceed ?", reasoning
self.last_answer = answer
return answer, reasoning return answer, reasoning
if __name__ == "__main__": if __name__ == "__main__":
from llm_provider import Provider pass
#local_provider = Provider("ollama", "deepseek-r1:14b", None)
server_provider = Provider("server", "deepseek-r1:14b", "192.168.1.100:5000")
agent = CoderAgent("deepseek-r1:14b", "jarvis", "prompts/coder_agent.txt", server_provider)
ans = agent.process("What is the output of 5+5 in python ?")
print(ans)

Some files were not shown because too many files have changed in this diff Show More