403 Commits
Author SHA1 Message Date
martin legrand 89f5736f6b feat : self run script 2025-05-05 15:55:35 +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
136 changed files with 37216 additions and 1642 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
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'
+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]
+26 -1
View File
@@ -1,11 +1,36 @@
*.wav
config.ini
*.DS_Store
*.log
*.tmp
*.safetensors
*.egg-info
cookies.json
test_agent.py
config.ini
.voices/
experimental/
.logs/
.screenshots/*.png
.screenshots/*.jpg
conversations/
agentic_env/*
agentic_seek_env/*
.env
*/.env
dsk/
### react ###
.DS_*
*.log
logs
**/*.backup.*
**/*.back.*
node_modules
bower_components
*.sublime*
psd
thumb
sketch
# 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"]
+345 -182
View File
@@ -1,55 +1,40 @@
# 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)
### Why AgenticSeek ?
* 🔒 Fully Local & Private - Everything runs on your machine — no cloud, no data sharing. Your files, conversations, and searches stay private.
* 🌐 Smart Web Browsing - AgenticSeek can browse the internet by itself — search, read, extract info, fill web form — all hands-free.
* 💻 Autonomous Coding Assistant - Need code? It can write, debug, and run programs in Python, C, Go, Java, and more — all without supervision.
* 🧠 Smart Agent Selection - You ask, it figures out the best agent for the job automatically. Like having a team of experts ready to help.
* 📋 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.
* 🎙️ 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
### **Demo**
> *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*
https://github.com/user-attachments/assets/b8ca60e9-7b3b-4533-840e-08f9ac426316
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.
> 🛠️ **Work in Progress** Looking for contributors!
![alt text](./media/whale_readme.jpg)
> *Do a web search to find tech startup in Japan working on cutting edge AI research*
> *Make a snake game in Python*
> *Scan my network with nmap, find out who is connected?*
> *Hey can you find where is contract.pdf*?
## Features:
- **100% Local**: No cloud, runs on your hardware. Your data stays yours.
- **Voice interaction**: Voice-enabled natural interaction.
- **Filesystem interaction**: Use bash to navigate and manipulate your files effortlessly.
- **Code what you ask**: Can write, debug, and run code in Python, C, Golang and more languages on the way.
- **Autonomous**: If a command flops or code breaks, it retries and fixes it by itself.
- **Agent routing**: Automatically picks the right agent for the job.
- **Divide and Conquer**: For big tasks, spins up multiple agents to plan and execute.
- **Tool-Equipped**: From basic search to flight APIs and file exploration, every agent has it's own tools.
- **Memory**: Remembers whats useful, your preferences and past sessions conversation.
- **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**
## Installation
Make sure you have chrome driver, docker and python3.10 (or newer) installed.
@@ -73,126 +58,231 @@ source agentic_seek_env/bin/activate
### 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
./install.sh
```
For windows:
```sh
./install.bat
```
**Manually:**
```sh
pip3 install -r requirements.txt
# or
python3 setup.py install
```
**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**
- *Linux*:
Update Package List: `sudo apt update`
Install Dependencies: `sudo apt install -y alsa-utils portaudio19-dev python3-pyaudio libgtk-3-dev libnotify-dev libgconf-2-4 libnss3 libxss1`
Install ChromeDriver matching your Chrome browser version:
`sudo apt install -y chromium-chromedriver`
Install requirements: `pip3 install -r requirements.txt`
- *Macos*:
Update brew : `brew update`
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
**We recommend using at the very least Deepseek 14B, smaller models will struggle with tasks especially for web browsing.**
## Run locally on your machine
**Setup your local provider**
**We recommend using at least Deepseek 14B, smaller models struggle with tool use and forget quickly the context.**
Start your local provider, for example with ollama:
### 1️⃣ **Download Models**
Make sure you have [Ollama](https://ollama.com/) installed.
Download the `deepseek-r1:14b` model from [DeepSeek](https://deepseek.com/models)
```sh
ollama pull deepseek-r1:14b
```
### 2 **Run the Assistant (Ollama)**
Start the ollama server
```sh
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
[MAIN]
is_local = True
provider_name = ollama
provider_model = deepseek-r1:14b
is_local = True # Whenever you are running locally or with remote provider.
provider_name = ollama # or lm-studio, openai, etc..
provider_model = deepseek-r1:14b # choose a model that fit your hardware
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 :
Note: Some provider (eg: lm-studio) require you to have `http://` in front of the IP. For example `http://127.0.0.1:1234`
```sh
sudo ./start_services.sh
```
**List of local providers**
Run the assistant:
| Provider | Local? | Description |
|-----------|--------|-----------------------------------------------------------|
| 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) |
```sh
python3 main.py
```
*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 **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-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) |
*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
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`
```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.
To exit, simply say/type `goodbye`.
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*
### 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 ?*
*Note that form filling capabilities are still experimental and might fail.*
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.
@@ -206,77 +296,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.
### 1️⃣ **Set up and start the server scripts**
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.
On your "server" that will run the AI model, get the ip address
```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.
Clone the repository and then, run the script `stream_llm.py` in `server/`
Clone the repository and enter the `server/`folder.
```sh
python3 server_ollama.py
git clone --depth 1 https://github.com/Fosowl/agenticSeek.git
cd agenticSeek/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:
Clone the repository.
Change the `config.ini` file to set the `provider_name` to `server` and `provider_model` to `deepseek-r1:14b`.
Change the `config.ini` file to set the `provider_name` to `server` and `provider_model` to `deepseek-r1:xxb`.
Set the `provider_server_address` to the ip address of the machine that will run the model.
```sh
[MAIN]
is_local = False
provider_name = server
provider_model = deepseek-r1:14b
provider_server_address = x.x.x.x:5000
provider_model = deepseek-r1:70b
provider_server_address = x.x.x.x:3333
```
Run the assistant:
```sh
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
```
Next step: [Start services and run AgenticSeek](#Start-services-and-Run)
---
## 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:
```
@@ -300,25 +377,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?"
```
## 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
The table below show the available providers:
| Provider | Local? | Description |
|-----------|--------|-----------------------------------------------------------|
| 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 |
| OpenAI | No | Use ChatGPT API (non-private) |
| Deepseek | No | Deepseek API (non-private) |
| HuggingFace| No | Hugging-Face API (non-private) |
| 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 |
| lm-studio | Yes | Run LLM locally with LM studio (`lm-studio`) |
| openai | Depends | Use ChatGPT API (non-private) or openai compatible API |
| 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:
```
is_local = False
provider_name = openai
provider_model = gpt-4o
is_local = True
provider_name = ollama
provider_model = deepseek-r1:32b
provider_server_address = 127.0.0.1:5000
```
`is_local`: should be True for any locally running LLM, otherwise False.
@@ -352,40 +485,70 @@ And download the chromedriver version matching your OS.
![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
**Q: What hardware do I need?**
7B Model: GPU with 8GB VRAM.
14B Model: 12GB GPU (e.g., RTX 3060).
32B Model: 24GB+ VRAM.
| Model Size | GPU | Comment |
|-----------|--------|-----------------------------------------------------------|
| 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?**
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?**
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.
**Q: How is it better than manus ?**
It's not but we prioritizes local execution and privacy over cloud based approach. Its a fun, accessible 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.
Unlike Manus, AgenticSeek prioritizes independence from external systems, giving you more control, privacy and avoid api cost.
## Contribute
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)
## Authors:
> [Fosowl](https://github.com/Fosowl)
> [steveh8758](https://github.com/steveh8758)
## Maintainers:
> [Fosowl](https://github.com/Fosowl) | Paris Time | (Sometime busy)
> [https://github.com/antoineVIVIES](antoineVIVIES) | Taipei Time | (Often busy)
> [steveh8758](https://github.com/steveh8758) | Taipei Time | (Always busy)
+567
View File
@@ -0,0 +1,567 @@
# 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(或更新)。
有关于 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)需要在 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) | 巴黎时间 | (有时很忙)
> [https://github.com/antoineVIVIES](https://github.com/antoineVIVIES) | 台北时间 | (经常很忙)
> [steveh8758](https://github.com/steveh8758) | 台北时间 | (总是很忙)
+550
View File
@@ -0,0 +1,550 @@
# 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(或更新)。
有關於 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` 设置为 `deepseek-r1:14b`
注意:`deepseek-r1:14b` 只是一个示例,如果你的硬件允许,可以使用更大的模型。
```sh
[MAIN]
is_local = True
provider_name = ollama # 或 lm-studio, openai 等
provider_model = deepseek-r1:14b
provider_server_address = 127.0.0.1:11434
```
**本地提供者列表**
| 提供者 | 本地? | 描述 |
|-------------|--------|-------------------------------------------------------|
| 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) | 台北时间 | (总是很忙)
+497
View File
@@ -0,0 +1,497 @@
<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 (ou une version plus récente).
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)
> [https://github.com/antoineVIVIES](https://github.com/antoineVIVIES)
+488
View File
@@ -0,0 +1,488 @@
<p align="center">
<img align="center" src="./media/whale_readme.jpg">
<p>
--------------------------------------------------------------------------------
[English](./README.md) | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Français](./README_FR.md) | 日本語
# AgenticSeek: Deepseek R1エージェントによって動作するManusのようなAI。
**Manus AIの完全なローカル代替品**、音声対応のAIアシスタントで、コードを書き、ファイルシステムを探索し、ウェブを閲覧し、ミスを修正し、データをクラウドに送信することなくすべてを行います。DeepSeek R1のような推論モデルを使用して構築されており、この自律エージェントは完全にハードウェア上で動作し、データのプライバシーを保護します。
[![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)
> 🛠️ **進行中の作業** – 貢献者を探しています!
https://github.com/user-attachments/assets/fe9e8006-0462-4793-8b31-25bd42c6d1eb
*そしてもっと多くのことができます!*
> *大阪と東京のAIスタートアップを深く調査し、少なくとも5つ見つけて、research_japan.txtファイルに保存してください*
> *C言語でテトリスゲームを作れますか?*
> *新しいプロジェクトファイルインデックスをmark2として設定したいです。*
## 特徴:
- **100%ローカル**: クラウドなし、ハードウェア上で動作。データはあなたのものです。
- **ファイルシステムの操作**: bashを使用してファイルを簡単にナビゲートおよび操作します。
- **自律的なコーディング**: Python、C、Golangなどのコードを書き、デバッグし、実行できます。
- **エージェントルーティング**: タスクに最適なエージェントを自動的に選択します。
- **計画**: 複雑なタスクの場合、複数のエージェントを起動して計画および実行します。
- **自律的なウェブブラウジング**: 自律的なウェブナビゲーション。
- **メモリ**: 効率的なメモリとセッション管理。
---
## **インストール**
chrome driver、docker、およびpython3.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
# Windowsの場合: agentic_seek_env\Scripts\activate
```
### 3️⃣ **パッケージをインストール**
**自動インストール:**
```sh
./install.sh
```
** テキスト読み上げ(TTS)機能で日本語をサポートするには、fugashi(日本語分かち書きライブラリ)をインストールする必要があります:**
```
pip3 install --upgrade pyopenjtalk jaconv mojimoji unidic fugashi
pip install unidic-lite
python -m unidic download
```
**手動で:**
```sh
pip3 install -r requirements.txt
# または
python3 setup.py install
```
---
## ローカルマシンでLLMを実行するためのセットアップ
**少なくともDeepseek 14Bを使用することをお勧めします。小さいモデルでは、特にウェブブラウジングのタスクで苦労する可能性があります。**
**ローカルプロバイダーをセットアップする**
たとえば、ollamaを使用してローカルプロバイダーを開始します:
```sh
ollama serve
```
以下に、サポートされているローカルプロバイダーのリストを示します。
**config.iniを更新する**
config.iniファイルを変更して、`provider_name`をサポートされているプロバイダーに設定し、`provider_model``deepseek-r1:14b`に設定します。
注意: `deepseek-r1:14b`は例です。ハードウェアが許可する場合は、より大きなモデルを使用してください。
```sh
[MAIN]
is_local = True
provider_name = ollama # または lm-studio、openai など
provider_model = deepseek-r1:14b
provider_server_address = 127.0.0.1:11434
```
**ローカルプロバイダーのリスト**
| プロバイダー | ローカル? | 説明 |
|-----------|--------|-----------------------------------------------------------|
| ollama | はい | ollamaをLLMプロバイダーとして使用して、ローカルでLLMを簡単に実行 |
| lm-studio | はい | LM studioを使用してローカルでLLMを実行(`provider_name``lm-studio`に設定)|
| openai | はい | OpenAI互換APIを使用 |
次のステップ: [サービスを開始してAgenticSeekを実行する](#Start-services-and-Run)
*問題が発生している場合は、**既知の問題**セクションを参照してください。*
*ハードウェアがDeepseekをローカルで実行できない場合は、**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ベースのAPIを使用する場合は、`is_local`をTrueに設定してください。
OpenAIベースのAPIが独自のサーバーで実行されている場合は、IPアドレスを変更してください。
次のステップ: [サービスを開始してAgenticSeekを実行する](#Start-services-and-Run)
*問題が発生している場合は、**既知の問題**セクションを参照してください。*
*詳細な設定ファイルの説明については、**設定**セクションを参照してください。*
---
## サービスの開始と実行
必要に応じてPython環境をアクティブにしてください。
```sh
source agentic_seek_env/bin/activate
```
必要なサービスを開始します。これにより、docker-compose.ymlから以下のサービスがすべて開始されます:
- searxng
- redis (searxngに必要)
- フロントエンド
```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インターフェースではメッセージのストリーミングがサポートされていないことに注意してください。
---
## 使い方
警告: 現在、サポートされている言語は英語、中国語、フランス語のみです。他の言語でのプロンプトは機能しますが、適切なエージェントにルーティングされない場合があります。
サービスが`./start_services.sh`で起動していることを確認し、`python3 cli.py`でagenticSeekを実行します。
```sh
sudo ./start_services.sh
python3 cli.py
```
`>>> `と表示されます
これは、agenticSeekが指示を待っていることを示します。
configで`listen = True`を設定することで、音声認識を使用することもできます。
終了するには、単に`goodbye`と言います。
以下は使用例です:
### コーディング/バッシュ
> *Pythonでスネークゲームを作成*
> *C言語で行列の掛け算を教えて*
> *Golangでブラックジャックを作成*
### ウェブ検索
> *日本の最先端のAI研究を行っているクールなテックスタートアップを見つけるためにウェブ検索を行う*
> *agenticSeekを作成したのは誰かをインターネットで見つけることができますか?*
> *オンラインの燃料計算機を使用して、ニースからミラノまでの旅行の費用を見積もることができますか?*
### ファイルシステム
> *契約書.pdfがどこにあるか見つけてくれませんか?*
> *ディスクにどれだけの空き容量があるか教えて*
> *READMEを読んでプロジェクトを/home/path/projectにインストールしてください*
### カジュアル
> *フランスのレンヌについて教えて*
> *博士号を追求すべきですか?*
> *最高のワークアウトルーチンは何ですか?*
クエリを入力すると、agenticSeekはタスクに最適なエージェントを割り当てます。
これは初期のプロトタイプであるため、エージェントルーティングシステムはクエリに基づいて常に適切なエージェントを割り当てるとは限りません。
したがって、何を望んでいるか、AIがどのように進行するかについて非常に明確にする必要があります。たとえば、ウェブ検索を行いたい場合は、次のように言わないでください:
`一人旅に良い国を知っていますか?`
代わりに、次のように尋ねてください:
`ウェブ検索を行い、一人旅に最適な国を見つけてください`
---
## **ボーナス: 自分のサーバーで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の場合、IPアドレスを見つけるには、それぞれ`ipconfig`または`ifconfig`を使用してください。
リポジトリをクローンし、`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サービスとして選択できます。
次に、個人用コンピュータで以下を行います:
`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を実行する](#Start-services-and-Run)
---
## 音声認識
現在、音声認識は英語でのみ動作することに注意してください。
音声認識機能はデフォルトで無効になっています。有効にするには、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: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 ja
[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。
- 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)。これは単にプロンプトファイルを変更するだけです。
- headless_browser -> ウィンドウを表示せずにブラウザを実行する(True)か、しない(False)。
- stealth_mode -> ボット検出を難しくします。唯一の欠点は、anticaptcha拡張機能を手動でインストールする必要があることです。
- languages -> List of supported languages. Required for agent routing system. The longer the languages list the more model will be downloaded.
## プロバイダー
以下の表は利用可能なプロバイダーを示しています:
| プロバイダー | ローカル? | 説明 |
|-----------|--------|-----------------------------------------------------------|
| ollama | はい | ollamaをLLMプロバイダーとして使用して、ローカルでLLMを簡単に実行 |
| server | はい | モデルを別のマシンでホストし、ローカルマシンで実行 |
| lm-studio | はい | LM studio`lm-studio`)を使用してローカルでLLMを実行 |
| openai | 場合による | ChatGPT API(非プライベート)またはopenai互換APIを使用 |
| deepseek-api | いいえ | Deepseek API(非プライベート) |
| huggingface| いいえ | Hugging-Face API(非プライベート) |
| togetherAI | いいえ | together AI 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`: エージェントが使用するモデルを設定します。
`provider_server_address`: サーバープロバイダーを使用しない場合は何でも設定できます。
# 既知の問題
## 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バージョンをダウンロードします。
![alt text](./media/chromedriver_readme.png)
このセクションが不完全な場合は、問題を報告してください。
## 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が実行中であることを確認してください(`ollama serve`)、`config.ini`がプロバイダーに一致していること、および依存関係がインストールされていることを確認してください。それでも解決しない場合は、問題を報告してください。
**Q: 本当に100%ローカルで実行できますか?**
はい、OllamaまたはServerプロバイダーを使用すると、すべての音声認識、LLM、および音声合成モデルがローカルで実行されます。非ローカルオプション(OpenAIまたは他のAPI)はオプションです。
**Q: Manusを持っているのに、なぜAgenticSeekを使用する必要があるのですか?**
これは、AIエージェントに関する興味から始まったサイドプロジェクトです。特別な点は、ローカルモデルを使用し、APIを避けることです。
私たちは、JarvisやFriday(アイアンマン映画)からインスピレーションを得て、「クール」にしようとしましたが、機能性に関してはManusから多くのインスピレーションを得ています。なぜなら、人々が最初に求めているのはローカルのManusの代替品だからです。
Manusとは異なり、AgenticSeekは外部システムからの独立性を優先し、より多くの制御、プライバシーを提供し、APIのコストを回避します。
## 貢献
AgenticSeekを改善するための開発者を探しています!オープンな問題やディスカッションを確認してください。
[![Star History Chart](https://api.star-history.com/svg?repos=Fosowl/agenticSeek&type=Date)](https://www.star-history.com/#Fosowl/agenticSeek&Date)
## 著者:
> [Fosowl](https://github.com/Fosowl)
> [steveh8758](https://github.com/steveh8758)
Executable
+238
View File
@@ -0,0 +1,238 @@
#!/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=["*"],
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),
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("/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,
"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 = ""
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_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"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="",
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
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.agent_name = interaction.current_agent.agent_name
query_resp.success = str(interaction.last_success)
query_resp.blocks = blocks_json
# Store the raw dictionary representation
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),
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),
]
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_model = deepseek-r1:14b
provider_server_address = 127.0.0.1:11434
agent_name = Friday
recover_last_session = True
agent_name = Name_of_your_AI
recover_last_session = False
save_session = False
speak = True
speak = 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
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
@@ -22,17 +22,17 @@ community include:
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
@@ -52,15 +52,15 @@ decisions when appropriate.
This Code of Conduct applies within all community spaces, and also applies when
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
representative at an online or offline event.
## Enforcement
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 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
**Community Impact**: A violation through a single incident or series
of actions.
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
like social media. Violating these terms may lead to a temporary or permanent
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
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
version 2.1, available at
[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
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
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/translations.
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[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
+40
View File
@@ -0,0 +1,40 @@
{
"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-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:
+479
View File
@@ -0,0 +1,479 @@
* {
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;
}
.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 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;
}
}
+277
View File
@@ -0,0 +1,277 @@
import React, { useState, useEffect, useRef } from 'react';
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 messagesEndRef = useRef(null);
useEffect(() => {
const intervalId = setInterval(() => {
checkHealth();
fetchLatestAnswer();
fetchScreenshot();
}, 3000);
return () => clearInterval(intervalId);
}, [messages]);
const checkHealth = async () => {
try {
await axios.get('http://0.0.0.0: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://0.0.0.0: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 fetchLatestAnswer = async () => {
try {
const res = await axios.get('http://0.0.0.0: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,
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 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://0.0.0.0: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'
}`}
>
{msg.type === 'agent' && (
<span className="agent-name">{msg.agentName}</span>
)}
<p>{msg.content}</p>
</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>
</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>
<p className="block-success">
Success: {block.success ? 'Yes' : 'No'}
</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
SCRIPTS_DIR="scripts"
LLM_ROUTER_DIR="llm_router"
echo "Detecting operating system..."
OS_TYPE=$(uname -s)
case "$OS_TYPE" in
"Linux"*)
echo "Detected Linux OS"
if [ -f "$SCRIPTS_DIR/linux_install.sh" ]; then
echo "Running Linux installation script..."
bash "$SCRIPTS_DIR/linux_install.sh"
bash -c "cd $LLM_ROUTER_DIR && ./dl_safetensors.sh"
else
echo "Error: $SCRIPTS_DIR/linux_install.sh not found!"
exit 1
@@ -22,24 +25,15 @@ case "$OS_TYPE" in
if [ -f "$SCRIPTS_DIR/macos_install.sh" ]; then
echo "Running macOS installation script..."
bash "$SCRIPTS_DIR/macos_install.sh"
bash -c "cd $LLM_ROUTER_DIR && ./dl_safetensors.sh"
else
echo "Error: $SCRIPTS_DIR/macos_install.sh not found!"
exit 1
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 "This script supports Linux, macOS, and Windows (via Bash-compatible environments)."
echo "This script supports only Linux and macOS."
exit 1
;;
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:
- 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 do not ever ever need to use bash to execute code. All code is executed automatically.
- As a coding agent, you will get message from the system not just the user.
- Do not ever tell user how to run it. user know it already.
- 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 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
sacremoses>=0.0.53
requests>=2.31.0
numpy>=1.24.4
colorama>=0.4.6
@@ -10,28 +20,29 @@ torch>=2.4.1
python-dotenv>=1.0.0
ollama>=0.4.7
scipy>=1.9.3
kokoro>=0.7.12
soundfile>=0.13.1
protobuf>=3.20.3
termcolor>=2.4.0
pypdf>=5.4.0
ipython>=8.13.0
pyaudio>=0.2.14
librosa>=0.10.2.post1
selenium>=4.27.1
markdownify>=1.1.0
text2emotion>=0.0.5
adaptive-classifier>=0.0.10
langid>=1.1.6
chromedriver-autoinstaller>=0.6.4
httpx>=0.27,<0.29
anyio>=3.5.0,<5
distro>=1.7.0,<2
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
# for api provider
openai
# if use chinese
sniffio
ordered_set
pypinyin
cn2an
jieba
Regular → Executable
+22 -17
View File
@@ -2,29 +2,34 @@
echo "Starting installation for Linux..."
set -e
# Update package list
sudo apt-get update
pip install --upgrade pip
# install pyaudio
pip install pyaudio
sudo apt-get update || { echo "Failed to update package list"; exit 1; }
# make sure essential tool are installed
sudo apt install python3-dev python3-pip python3-wheel build-essential
# install port audio
sudo apt-get install portaudio19-dev python-pyaudio python3-pyaudio
# Install essential tools
sudo apt-get install -y \
python3-dev \
python3-pip \
python3-wheel \
build-essential \
alsa-utils \
portaudio19-dev \
python3-pyaudio \
libgtk-3-dev \
libnotify-dev \
libgconf-2-4 \
libnss3 \
libxss1 || { echo "Failed to install packages"; exit 1; }
# upgrade pip
pip install --upgrade pip
# install wheel
pip install --upgrade pip setuptools wheel
# install docker compose
sudo apt install docker-compose
# Install Python dependencies from requirements.txt
pip3 install -r requirements.txt
sudo apt install -y docker-compose
# Install Selenium for chromedriver
pip3 install selenium
# Install portaudio for pyAudio
sudo apt-get install -y portaudio19-dev python3-dev alsa-utils
# Install Python dependencies from requirements.txt
pip3 install -r requirements.txt --no-cache-dir
echo "Installation complete for Linux!"
Regular → Executable
+17 -4
View File
@@ -2,16 +2,29 @@
echo "Starting installation for macOS..."
# Install Python dependencies from requirements.txt
pip3 install -r requirements.txt
set -e
# 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
brew install --cask chromedriver
# Install portaudio for pyAudio using Homebrew
brew install portaudio
# update pip
python3 -m pip install --upgrade pip
# upgrade setuptools and wheel
pip3 install --upgrade setuptools wheel
# Install Selenium
pip3 install selenium
# Install Python dependencies from requirements.txt
pip3 install -r requirements.txt --no-cache-dir
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
environment:
- SEARXNG_BASE_URL=http://localhost:8080/
- UWSGI_WORKERS=4
- UWSGI_THREADS=4
- UWSGI_WORKERS=1
- UWSGI_THREADS=1
cap_add:
- CHOWN
- SETGID
+1 -1
View File
@@ -95,7 +95,7 @@ server:
# If your instance owns a /etc/searxng/settings.yml file, then set the following
# 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}
image_proxy: false
# 1.0 and 1.1 are supported
File diff suppressed because it is too large Load Diff
+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
+108
View File
@@ -0,0 +1,108 @@
#!/usr/bin python3
"""
self_run.py is a script for automatically creating prompts, and saving history as training data.
"""
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
import warnings
warnings.filterwarnings("ignore")
config = configparser.ConfigParser()
config.read('config.ini')
def copy_conversations_folder():
source_path = "conversations/"
destination_path = "training_data/"
if not os.path.exists(destination_path):
os.makedirs(destination_path)
for filename in os.listdir(source_path):
source_file = os.path.join(source_path, filename)
destination_file = os.path.join(destination_path, filename)
shutil.copy2(source_file, destination_file)
print(f"Copied {source_file} to {destination_file}")
def get_random_query(provider):
prompt = """
You are an expert in crafting queries for AgenticSeek, a AI assistant that autonomously browses the web, writes code, plans tasks, and manages files. It supports tasks like web searches, coding in Python/C/Go/Java, file operations, task planning.
Queries must be explicit, specifying actions like "search the web," "write code," or "save to a file," as AgenticSeek's agent routing may not infer vague intents.
Generate a single realistic user query for AgenticSeek. The query should:
Be concise and explicit about the desired action (e.g., web search, coding, file management).
Align with AgenticSeeks capabilities (web browsing, coding, task planning, file operations).
Include a specific output where relevant (e.g., save to a file with a clear name and path).
Reflect a practical use case (e.g., research, programming, personal tasks).
Be formatted as a single sentence.
Example Query:
Search the web for the best hiking trails in Colorado and save a list of three trails with their locations in hiking_trails.txt in /home/project
"""
history = [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": prompt}]
thought = provider.respond(history)
return thought
async def self_runner():
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=True, stealth_mode=False),
anticaptcha_manual_install=False
)
agents = [
CasualAgent(name=config["MAIN"]["agent_name"],
prompt_path=f"prompts/base/casual_agent.txt",
provider=provider, verbose=False),
CoderAgent(name="coder",
prompt_path=f"prompts/base/coder_agent.txt",
provider=provider, verbose=False),
FileAgent(name="File Agent",
prompt_path=f"prompts/base/file_agent.txt",
provider=provider, verbose=False),
BrowserAgent(name="Browser",
prompt_path=f"prompts/base/browser_agent.txt",
provider=provider, verbose=False, browser=browser),
PlannerAgent(name="Planner",
prompt_path=f"prompts/base/planner_agent.txt",
provider=provider, verbose=False, browser=browser)
]
interaction = Interaction(agents,
tts_enabled=False,
stt_enabled=False,
recover_last_session=False,
langs=['en']
)
print("Start self-running for training data generation...")
try:
while interaction.is_active:
query = get_random_query(provider)
print(f"Generated query: {query}")
interaction.set_query(query)
if await interaction.think():
interaction.show_answer()
except Exception as e:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
copy_conversations_folder()
raise e
finally:
if config.getboolean('MAIN', 'save_session'):
interaction.save_session()
copy_conversations_folder()
if __name__ == "__main__":
asyncio.run(self_runner())
-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(),
include_package_data=True,
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",
"openai",
"sacremoses>=0.0.53",
"numpy>=1.24.4",
"colorama>=0.4.6",
"python-dotenv>=1.0.0",
"playsound>=1.3.0",
@@ -26,7 +34,6 @@ setup(
"ollama>=0.4.7",
"scipy>=1.9.3",
"kokoro>=0.7.12",
"flask>=3.1.0",
"protobuf>=3.20.3",
"termcolor>=2.5.0",
"ipython>=8.34.0",
@@ -35,11 +42,18 @@ setup(
"markdownify>=1.1.0",
"text2emotion>=0.0.5",
"python-dotenv>=1.0.0",
"adaptive-classifier>=0.0.10",
"langid>=1.1.6",
"chromedriver-autoinstaller>=0.6.4",
"httpx>=0.27,<0.29",
"anyio>=3.5.0,<5",
"distro>=1.7.0,<2",
"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",
"tqdm>4"
],
+2 -1
View File
@@ -5,5 +5,6 @@ from .casual_agent import CasualAgent
from .file_agent import FileAgent
from .planner_agent import PlannerAgent
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"]
+127 -37
View File
@@ -5,57 +5,104 @@ import os
import random
import time
import asyncio
from concurrent.futures import ThreadPoolExecutor
from sources.memory import Memory
from sources.utility import pretty_print
from sources.schemas import executorResult
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():
"""
An abstract class for all agents.
"""
def __init__(self, model: str,
name: str,
def __init__(self, name: str,
prompt_path:str,
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.browser = browser
self.role = None
self.type = None
self.current_directory = os.getcwd()
self.model = model
self.llm = provider
self.memory = Memory(self.load_prompt(prompt_path),
recover_last_session=recover_last_session,
memory_compression=False)
self.memory = None
self.tools = {}
self.blocks_result = []
self.success = True
self.last_answer = ""
self.status_message = "Haven't started yet"
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_blocks(self) -> list:
return self.blocks_result
@property
def get_status_message(self) -> str:
return self.status_message
@property
def get_tools(self) -> dict:
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:
if tool is not Callable:
raise TypeError("Tool must be a callable object (a method)")
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:
try:
with open(file_path, 'r', encoding="utf-8") as f:
@@ -85,43 +132,73 @@ class Agent():
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>"
end_tag = "</think>"
if text is None:
return None
start_idx = text.find(start_tag)
end_idx = text.rfind(end_tag)+8
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.
"""
memory = self.memory.get()
thought = self.llm.respond(memory, verbose)
thought = self.llm.respond(memory, self.verbose)
reasoning = self.extract_reasoning_text(thought)
answer = self.remove_reasoning_text(thought)
self.memory.push('assistant', answer)
return answer, reasoning
def wait_message(self, speech_module):
async def wait_message(self, speech_module):
if speech_module is None:
return
messages = ["Please be patient, I am working on it.",
"Computing... I recommand you have a coffee while I work.",
"Hold on, Im crunching numbers.",
"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:
return self.blocks_result
def get_last_tool_type(self) -> str:
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):
"""
Show the answer in a pretty way.
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")
for line in lines:
if "block:" in line:
@@ -130,7 +207,6 @@ class Agent():
self.blocks_result[block_idx].show()
else:
pretty_print(line, color="output")
self.blocks_result = []
def remove_blocks(self, text: str) -> str:
"""
@@ -153,28 +229,42 @@ class Agent():
block_idx += 1
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]:
"""
Execute all the tools the agent has and return the result.
"""
feedback = ""
success = False
success = True
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():
feedback = ""
blocks, save_path = tool.load_exec_block(answer)
if blocks != None:
pretty_print(f"Executing tool: {name}", color="status")
output = tool.execute(blocks)
pretty_print(f"Executing {len(blocks)} {name} blocks...", color="status")
for block in blocks:
self.show_block(block)
output = tool.execute([block])
feedback = tool.interpreter_feedback(output) # tool interpreter feedback
success = not tool.execution_failure_check(output)
pretty_print(feedback, color="success" if success else "failure")
self.memory.push('user', feedback)
self.blocks_result.append(executorResult(blocks, feedback, success))
self.blocks_result.append(executorResult(block, feedback, success, name))
if not success:
self.success = False
self.memory.push('user', feedback)
return False, feedback
self.memory.push('user', feedback)
if save_path != None:
tool.save_block(blocks, save_path)
return True, feedback
+290 -87
View File
@@ -1,126 +1,200 @@
import re
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.agents.agent import Agent
from sources.tools.searxSearch import searxSearch
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):
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
"""
super().__init__(model, name, prompt_path, provider)
super().__init__(name, prompt_path, provider, verbose, browser)
self.tools = {
"web_search": searxSearch(),
}
self.role = "Web Research"
self.browser = Browser()
self.role = "web"
self.type = "browser_agent"
self.browser = browser
self.current_page = ""
self.search_history = []
self.navigable_links = []
self.last_action = Action.NAVIGATE.value
self.notes = []
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:
"""Get the date"""
date_time = date.today()
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+)'
matches = re.findall(pattern, search_result)
trailing_punct = ".,!?;:"
trailing_punct = ".,!?;:)"
cleaned_links = [link.rstrip(trailing_punct) for link in matches]
self.logger.info(f"Extracted 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 = []
for link in links:
link = link.strip()
if link[-1] == '.':
if not (link[-1].isalpha() or link[-1].isdigit()):
links_clean.append(link[:-1])
else:
links_clean.append(link)
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])
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)
self.logger.info(f"Search results: {search_choice}")
return f"""
Based on the search result:
{search_choice}
Your goal is to find accurate and complete information to satisfy the users request.
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.
"""
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_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"""
You are a web browser.
You are currently on this webpage:
You are navigating the web.
**Current Context**
Webpage ({self.current_page}) content:
{page_text}
You can navigate to these navigation links:
{remaining_links}
Allowed Navigation Links:
{remaining_links_text}
Your task:
1. Decide if the current page answers the users query: {user_prompt}
- 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.
Inputs forms:
{inputs_form_text}
Recap of note taking:
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.]
End of webpage ({self.current_page}.
Example 1 (useful page, no need of going futher):
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
# Instruction
Example 2 (not useful, but related link):
Error: This forum reddit.com/welcome does not discuss anything related to the users query.
There is a link that could lead to the information, I want to navigate to http://reddit.com/r/locallama
1. **Evaluate if the page is relevant for users query and document finding:**
- If the page is relevant, extract and summarize key information in concise notes (Note: <your note>)
- 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):
Error: x.com does not discuss anything related to the users query and no navigation link are usefull
GO_BACK
Error: x.com does not discuss anything related to the users query and no navigation link are usefull.
Action: {Action.GO_BACK.value}
Example 3 (query answer found):
Note: I found on github.com that agenticSeek is Fosowl.
Given this information, given this I should exit the web browser. REQUEST_EXIT
Example 3 (clear definitive query answer found or enought notes taken):
I took 10 notes so far with enought finding to answer user question.
Therefore I should exit the web browser.
Action: {Action.REQUEST_EXIT.value}
Current date: {self.date}
Remember, the user asked: {user_prompt}
Do not explain your choice.
Example 4 (loging form visible):
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")
self.memory.push('user', prompt)
answer, reasoning = self.llm_request()
pretty_print("-"*100)
answer, reasoning = await self.llm_request()
if show_reasoning:
pretty_print(reasoning, color="failure")
pretty_print(answer, color="output")
pretty_print("-"*100)
return answer, reasoning
def select_unvisited(self, search_result):
def select_unvisited(self, search_result: List[str]) -> List[str]:
results_unvisited = []
for res in search_result:
if res["link"] not in self.search_history:
results_unvisited.append(res)
self.logger.info(f"Unvisited links: {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")
parsed_results = []
for block in result_blocks:
@@ -139,36 +213,67 @@ class BrowserAgent(Agent):
parsed_results.append(result_dict)
return parsed_results
def stringify_search_results(self, results_arr):
return '\n\n'.join([f"Link: {res['link']}" for res in results_arr])
def stringify_search_results(self, results_arr: List[str]) -> str:
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')
saving = False
buffer = []
links = []
for line in lines:
if line == '' or 'action:' in line.lower():
saving = False
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):
annotated_notes = [f"{i+1}: {note.lower().replace('note:', '')}" for i, note in enumerate(self.notes)]
def select_link(self, links: List[str]) -> str | None:
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, compression = False) -> str:
"""Get the text content of the current page."""
page_text = self.browser.get_text()
if compression:
#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)
print("AI research notes:\n", search_note)
pretty_print(f"AI notes:\n{search_note}", color="success")
return f"""
Following a human request:
{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}
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"""
Current date: {self.date}
Make a efficient search engine query to help users with their request:
{user_prompt}
Example:
User: "search: hey jarvis i want you to login to my twitter and say hello everyone "
You: Twitter
User: "go to twitter, login with username toto and password pass79 to my twitter and say hello everyone "
You: search: Twitter login page.
User: "I need info on the best laptops for AI this year."
You: "search: best laptops 2025 to run Machine Learning model, reviews"
@@ -177,47 +282,145 @@ class BrowserAgent(Agent):
You: "search: Recent space missions news, {self.date}"
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
animate_thinking(f"Thinking...", color="status")
self.memory.push('user', self.search_prompt(user_prompt))
ai_prompt, _ = self.llm_request()
mem_begin_idx = self.memory.push('user', self.search_prompt(user_prompt))
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")
self.status_message = "Searching..."
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)
unvisited = [None]
while not complete:
answer, reasoning = self.llm_decide(prompt)
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:
while not complete and len(unvisited) > 0:
self.memory.clear()
unvisited = self.select_unvisited(search_result)
prompt = self.make_newsearch_prompt(user_prompt, unvisited)
pretty_print(f"Going back to results. Still {len(unvisited)}", color="warning")
links = []
answer, reasoning = await self.llm_decide(prompt, show_reasoning = False)
if self.last_answer == answer:
prompt = self.stuck_prompt(user_prompt, unvisited)
continue
animate_thinking(f"Navigating to {links[0]}", color="status")
speech_module.speak(f"Navigating to {links[0]}")
self.browser.go_to(links[0])
self.search_history.append(links[0])
page_text = self.browser.get_text()
self.last_answer = answer
pretty_print(''*32, color="status")
extracted_form = self.extract_form(answer)
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()
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()
self.navigable_links = self.browser.get_navigable()
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()
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)
self.memory.push('user', prompt)
answer, reasoning = self.llm_request()
mem_last_idx = self.memory.push('user', prompt)
self.status_message = "Summarizing findings..."
answer, reasoning = await self.llm_request()
pretty_print(answer, color="output")
self.status_message = "Ready"
self.last_answer = answer
return answer, reasoning
if __name__ == "__main__":
+15 -27
View File
@@ -1,3 +1,4 @@
import asyncio
from sources.utility import pretty_print, animate_thinking
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.fileFinder import FileFinder
from sources.tools.BashInterpreter import BashInterpreter
from sources.memory import Memory
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.
"""
super().__init__(model, name, prompt_path, provider)
super().__init__(name, prompt_path, provider, verbose, None)
self.tools = {
"web_search": searxSearch(),
"flight_search": FlightSearch(),
"file_finder": FileFinder(),
"bash": BashInterpreter()
}
self.role = "Chat and Conversation"
} # No tools for the casual agent
self.role = "talk"
self.type = "casual_agent"
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:
complete = False
async def process(self, prompt, speech_module) -> str:
self.memory.push('user', prompt)
self.wait_message(speech_module)
while not complete:
animate_thinking("Thinking...", color="status")
answer, reasoning = self.llm_request()
exec_success, _ = self.execute_modules(answer)
answer = self.remove_blocks(answer)
answer, reasoning = await self.llm_request()
self.last_answer = answer
complete = True
for tool in self.tools.values():
if tool.found_executable_blocks():
complete = False # AI read results and continue the conversation
self.status_message = "Ready"
return answer, reasoning
if __name__ == "__main__":
from llm_provider import Provider
#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)
pass

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