Fq)B*h(5+Ho0Q!Yy*Mh)et%QLedjH;z
zFM5M#QjI?=;er>k*+6ggYerpFAcCGUn1;wQYfLsFNmT=_)IInO+T4Ib`zNOF>Nz`_
zD*3nit#7n%j@UmIAyZ!ymG{n^5wP#UsezFblpry5oSvg{c9?Pjz`v1WQ0Bd!Dy=!H
zvJhfs>5PqyiN3Vv-wzB=N#CAKi(Dr?&Gldj(a5pFB+#0qDr*E%L2qiTTE}NGC68(V=QcK~nID;`Rg+M2-2l8twSJ1byYNg{jUN^`-KxlfxP3hGw`8K`jQAV}P
zO;+TsU;P7|`H?D}GWKhXNEX6JENZRqr`MNqK=HqJmx6e}fJ`W_Q-Z2G8rWMO!t+`*
zLU_OqBQ@-IY?)%iuD|D?{Ym|e?Y;VW-)f4N4RPH%jmF|=6-hB4pGX}(2;gaF<97*M(BXnQ%KVhmri
zqvS+E*(5J<+k|rl=ckr!)7iAfF<(rjh|AB>;2#h7?9Yji+A3+=vO<#trw&Z=2s{%Q@UMWh_qSacE&=c
z7uzd?d)4T#y0@z`WI3|5IuoJlD{$mcTlnSN5yK`memwA;OZa}4&}tK-R_%lj(+-gmj64z4NwWgt9^V83JG)~nu^;{bC;4a
z+|MRLdN*;9Q808;Zs+h4R9}qCq6;ygQ2)dg{N_eR6dfnQxP$Oe(l{1Iw=
z5z)DG=Y~n3i#T3NkcW7#=5?RroJh>nM-!PXw#lzwD>skbuq5lga(w{QO=>^x#2Ak#
zgsjoV6YgQtn&vT_cJ~2s0eYAI6FDMXBZYsEGHY9jWmQcvThAB=Vg;Sk<+k1J0!5r;
z_*;xy@XP&R641s;$k8GWr)f0q$u$ab%>l-MbM+gbckumCSuj8VQr9;I%V%Qg*o*l0
z_xEikqk4<;5T6}I$Wg5()jPX2=wRiwvrca|zNYLYU)}!tF*WB)&jT8kz|RGWj!=eX
z98v~GYG8u$ZY`If=WXh!GK~Py+q~cqwP$&{`%{3}9ZqoNr+rY1d6v;la0`AKDJhp8
z{mm#pH)b2WuHXt0l0mYvM}Q1A4sk+UGHm5D6fWWd5dYU@Ox{qn+ih0Dd(WvgZfHH5
zZ?aaL5Zg!wK!r`1JG(4Cx?fhHF#@&U3?G7y0>MNEt$1l+*C5m)pf3rdg_iCZ&ASUf
zetdvB1;2X_PtMgpUMTwPTPTcX_E-nQU0Tqor4wP!E%g@-@xPy`tU8V-=2Alf*G&N?
z)BS$Xgr8_-LLj|kQR8v{
zSxsgl6XH{rM$t0p
z@O=K_I0p9l%lrhe5YU0Kyk?Je#3brS>z_e!m6&rWOXId5_*WDT`d05ljbZ-=0X>8T
zxk}P-Q$RXvg)2ia*~fXQ0I@vD2$i&QGkzRF_1%DT5LO8uNn`H@t!lOL-6{O=Yg>|c
z1-`oiy1Q{l#ErCyKv)Xh>hG&8E*_xGH&un3e+@9A0R5x?|fK%=0sAsBmpc@
z(Aqd=3rt{x+od&qYA(
z8`TD9k5&2+84k*Asq+4E9%=Eji^>RjQ|jIII{G%*5zq)DT|vr#RsE3##Y?*iGStQt
zEs=3H&HN4%6Dv~4C9zN1Mim$4)&;}|dMKdQQ^6=FVHWIFsk!pL#0xWhBn)|BEBmA$
zoR({zJbN}sE1VK3;$jKk!xTFVBb%^KE&RHlO1Dbh7ofP@R#y+s1{%nU6FSCry+?Tn
zE}`3%P$$MC`QxJV({s+LiCry_~;X)tO;bwuUQ
zu6Ym-XiX$Wfqp34b*k7txvlvJV_6ol6|Q8g1io%`kQ~|}$$6;hb6`!FQG2&wVczVTmLw3Ql$trk2Ga7MiZSDKM1Gb?ZBq`DrBGcFB
zuDT{hq_VJsI|<)t9bYuG!PBBseMfSrBrz;l*Wh~+f86&W`J$|311|s;kOqKFxFVN@
z;ldF@g+j1(&w-LYv-$->%NLYu+4H+P;me|ANyQOi)f!)^A9Mz8_w{~MK7TKi&HjqY
zQ`gRd>+({@s_>Ade-8EVH(GW2)UswjInafZHaKaQinuT~`%8oH6jCorMShyiqeE|J
z>GScDM(9vvtJn2C(20F7vd2$0MpF3a#5F@kD?CrP?)iH&Qwh`Rj
zpKhkZwR+fJV&TkbSVJ6Eg(QISlk7R+ERTTrdcHJj`YyY6KQ&$qzU-z-<3+^)$cN~#
z9+P26QFR~rwDvhsb4S(A&&0yoa@=Srn;JYI9BO2EBau~<0@e>TyTMJUoLIPi)p%{=
z*}Du{lu-u{~e>u^#bS!JE>0JsD)$0|FaYU;**?EJ-Z#*!HNc}}Q6DTG+
zYF8YrPl7rdpE
zPurs^d27bUd5CVudhV`?ma?2``a|rpv}`Zvvoi*n3O0B4*Q2t&IiEBCBbE@JZqP+K
z`d0RerjW9vBOB1gq?-t-1c2C`bXa;ByX}|W|Jb=5CfS=l9E6yve=a*bK7u)KBJx@V
zFgIKUgNKDplKDC1S@(~2oXYzCfDRNoSb!Vk@&h)kJ}RZzt|=XxlsFEtLLJCxSzxgz
ztvW`T=)q+Anvg0rhKHS3ue&ikT=*>y-0^ylgubgWuDa4Fr_%N_uWa&w8lpghXmG#I
z!f4+?%yoba_PzdObP?vtO@!@=bi=$KtPb3vVHwxbyiwkUX(
z&o8+@ChyY-;h8|XN#Wz`}nh_hiQbadAc9qrpbuCb$Bmmt~kt5@AeD+xj6qhrgkopL;
zl!!26bFr#Y=jgbyOg+jwWynGe9L+1>Zwm)+?g)aj3@HD%cG;r07bx^+Usqw*8ACm5
zm|qN0W(~4?p$m&SE@BGMoG9G0L!xZCegK?6A?d<6eS%BsvEseCjY4WE>4R2
zj>=-2bvv&d*%Ty#&tE=Qoo$Fr4AJF=DeOZ)Pk|*|R=>vAB1eFL=$^6e$vUf*$;
zFEGy$$xqQ7=lp(>rVjfwkN)spYh`QR@}rFGXFa`g*?$DDUsB9ucmvKA^bYt8%fFij;aa!``TK+;;Uk+vs3P^
ztoP%4DdWSvK_upUA|D^#7Kr$S|MnsoTJ648ukC;C_qoBN?Hh&)0`ye5wTkhGZgBah
zjmUrfQ+4&Y;gwAjQvLo>TI#g|Q}Pfy
z^UGF3ES6i3a$cFXEZ1+c{wI1KmOzBQTz3vU_$8=e#LW1Kv|sBeSGUS85gr{$1|7_`
zEFGV+xRQp*twJr_(Y~RQO;-=E;g)EZHN9R;mz#j^G`^jwLnj<6
zbKF=sdp*a6JNJp!@*GY3v6>P>%uE8qm3uCDfJglUR@F{?;93SRC^^nY7s7s&Z{b>qC}IT_A2m&z^MxxEH(@#VVEa&di(lr
ze0KxR&|KjD{rjAs@*aH6{pR_dS0v(Ao|F_5EZ`}0)G!g|PxBtR!t~U+EPHhoy(k`6!guG1+G;MmwZ#5{9x(aFVGDOmy(aq%R=72i?mPRCLHrI&NhDFxu
zb0ULO;D*cz9ih%Rds1_6W#dB_@!I9}UZ2V}QhTMrM_bDMEQQ1`&(x&bgn#6A=Gx=v
z<=L3(CIgx}@o5__0I5!T?<)bKp1U@BUmIlFuRNl@grQ7vrAMMryDrrID4;&zQE;Iv
znQWPAo^I~)tfzOLju1NKxQ%Tm(Y}Fj2K7PjxkO8`2B*aP7`vHfEF;R?fW|j7y;BdG
zsn%#IiX7HZ37tNSg-ff4MWth^I=BEa0HzVEvEf`>U5$5;KNN+CpE)Tb)mPR1j3<)o
zHD%|cxc(4li(QRnysK|kntKMNcaXzuq5b4+>!;7l4r}_k#M~u{X2RER-$Zs|+MxM3
zgBBoVllyPFU!dmff>Afd;cwTk&niA>LTEZk9`gCNU!>Pt8KoTmNd190tOIB7vs{FcB$3`4h`>WVe-r}j)$&-UEM
z0W~ewVAee|=|8Tv*qLW|63pxxWtEX}wMD((p;vxyn9MnS{)5$uDKm1xsG{NBT~A~4
zdU27Cs=Ov&Hmw}H^BKVP-A?X$X5Lj_Dk^o35@uEV&(4@7MP&29bvbjhB}`fS2yFm>^2+Qt6rlL+^hiHNLNvm#GRO3Mg`dMTGFXYJwbNHM
zJXq7a*}r3uvdC+`CY+NQd;0;WAv>Rkey>e@VZ86h!SIqhum8VoQ_<&$lCiI)`&(6H
z4A2NC{6tO01To(eHRMuZd;Qrg;XuJ}CAHQI_w(8?b(<$2;oG<6!j}9{)JE0d?%aMK
z&O6fOBigKL(r8UKE?SM!))wFU)X^b^?G**UvW9rn&EslGYp6bVe$?AvZ(x>7KB05v(^_y1tJlQD~7U(+ow|SDHX|mFxUvxVT-85s+rm)29at>
zWxap)F`_1|@~8B-4TciasCg(xbBv&9C@PZdS7}iz?>qGh`7|ki8E`U2Z9Y)qV?D00
z_Jz$=O!@8az%#}T>USR9E+ct%ylF78qq(v{p^QIR&)1kQIU<;Q9wdWU(%=OpW@i$c
zOo2JX|Jm}y8Ovlur9OR0zg2P#)Iz5WHzBw+R|E<;V#CZScM{;C_XgD<1upmyOv3a<
zJrSE3qP)f)u(+Kb3%9gXcvt=Ce${C`5?{i_qP1t7cn+t01`h3yrAx<7y|vbvIvFsS
z7Sy%fK(X;lmaIHHe{%f-{ifdM&dNZ*^cH-m%k5-pmATEO{1mjW|H2KF#tHm00DVs0-wkv|LRv>)vx&%SHi5o5uX;~{Ufh>TCo
z{Bcc#V)8N_EPL_aPlWsu^55;UBvcvJX3U?u7fz#@5cW!6&ZMSLHlW+B!0b|QbDB$F
z4uN+6`w+)OL~L2bry|v+vy|np#bzE1p0ZbeR-nn~DXgcfW*oj$qJ6d~-;J~5k0y_6
zdsFv(U+Vecdkd;1S@<(~b<*3u7EL-ki|4L{0UCg^Nnxk(z4~^sJ
zB+bbUJ_RaXj64ng;9Te6WJb02cQyi~?Oo`c+U`9Vjm_x|
z8519q)7;o!ua^*~DgC_cvgXM|+S8s#}y+~GPh5^auvH6Pki@Lw=uC8T!?^dNo
zw_Wfv4m6tLY|I^wd^Izxe(vy?8x-UGp0qYfi~lbQU61z>;rtc(4ilqD&XG7FUQ7
zej7!8G5+{BF-+BzqIrux2k#cPXq)yiAVE6nB{Dx>Y&87M1WobQ
zvhe-~%R3-hzIW(OsePOK!_w%`;7^PgN{bCRu+etcIR8k38wm_5Q=D#BPN;fy@lg41
zrzutQtw4luRK})y3%R4`D;Z0DvIiUPV%uqG(|~5P1dnd5?aLBkx)oa=G<&BhV?RB4
zt;2v?~bzPt>#PU8`-n||=Ugq-J;a)FV6W&7&YxoOY#g8;f)2)b;zLOit
zLMUXu4Fbp{xQ^&zDDXapPI7E*cRQ-&&!+D6bOrpGz_kYjrzWST_@O*~0U2sz}Mvw#H#b`*&XSzcpjuT<2U`T1UfRJpWJtm5Qd<<@_>)mXg}z
z_>`yW@jJ?od2MX@@k%f{p3jBcr!HE8$vJREZZ8>
zD_}io!r}@bO>Lp8cJG^-6Eayg?z6`-
z?{ZK!^TYLaPdyIr1f|T}Lba%i&dKxheJ}D4>edl)$BuP_#TQ!ES1QikAX}hlPTrew
z5KgJhk|X~)5sUf41TpVoYPwSME!g4o(AwJC;TQZwFZkPNwI}ks6_X%QBxQcpQKe-I
z>bXu(N&l1q+`c&O!n8J^Q2=-R>R{JjkY2S9+^aA*&RR?U#UPBIU2Sz0q-dTb~!hIbybz4!$RAk}kCoI>d@3U=JTSFtCbhgsG?>t?U>1Nmw^jWsX?&+jg
z_zTwKpRe}_bFxmRtm#cNV#3T|~O217TLAd!T)Y^e`CPt%LE)}h-ndSF1;;5U}sp<^JC!rh4o0sJ|;@iw)LsxbCw
z;^^pT$&Vc#is;@7wgNXMPnuHILc$PYq^Jwd*;)NVOF{X5X3)J;v#l{>o|V4p?$n^kpZOHlai4#Z5KQ}y0kTgzxJ~HF=_g9FA=@Bu#nv$8ER;=
zYMXR1nE&fjX_<4I@t_|-wRZ~KPUS?V%v-@MWV-Bj);j&%&&-xL8qccMQU&g`T2
z`BByP1ch!uZHh1qX}ox>KIbF)?Gd$;)X}_~=0bT1sH)_@^24SneW~0FOcj^i87k~@
zs1JV8FF>9(=q@_2`_zMVc~15Wticz;nhF~VSxSmR&NLOEKr%8_pvfaR69bCbM)ePU
zWQ^t}M!+w%a87&*#!Q%nqzE`9xl)H@ppza+km$ZQg@>Ju^s&s+{d
zclEh^{YGt`hh`Y}AjZIH)dXFkH@UF`u@~cd(z!YjH&6PWp_b
zy$i9Gf7Y+6MJKw5-*@MVV#L0>hr~Q$6tskJDMKmYCvYj$Fe+@)|KPXkDBcww|K;op
zR*Ui(aK#nNG_C3qyj!)@hIOJoHm#>@&Uj+uJz*}t!K-M=+tF6-xSHA3i=2>u$o>;E
z=f{e(?3Iz}o7c>q83p3%MS*J|&~GEq2+_Y2WtLT&DsBjcu!trV)QI4Ysjx+qwFpto41`dE@!)qod+sbh!i%wV~oonbDo+
zcaQG(cCiX%QiEE`tjN^9Ti@=`L?NM9a$m4|fD)o*`Y=bv#P5w_i*ZvRXw#MHa(o8!Isiw<>
zGWM1d?TW~tkxfRFq!cr5rIW3~Bx%Ow$doh`ns>d=TI+eA^*rD2H?r-#Mfu#a#o5-QHTVX1y6vWy
zk|Da35xoAW=lP2O7FFV8Un8QD{dzNWs;m#wqhd0A7z((ifScv@JWqG!$ih=eQ3
zR$3Sk*{HadA0i45c^`gM!m^kf$5ZrLr;P~1)ERXLv&9Z{uCG)c&=K@!wT;#Ri^7x`
z5!Z-_#~u>V2ZsSg;tkb013D*zhd#EKH%zz^jdFQFJ5JVf89j@tzO#wHJ$kWq1@=@f
z_B7pQ(k>9~u3EwGW8wGg)VE<9>IQ?r)oeo9_AAXvb-9
zw)kgb^{tf1puEPjAzAMmDT77L#_?ribB-o=Mf5n?*{AJ40%sZ_HE{Xv?B%%xp(Z0C
zKZmsTQ}>&ue#woQiC;dLDi*0>4E#6Yq$(ShG-CDnEAhI$!w>fg@#e-9RDs>;74?v}
z*=OKujyWk@XKH@fvYy;S?NW7!CfU#LN{5HTB&-wm&jowPsj12Ic-*f}UbTP|_-lJD
zK5QnSRV$ZfOy5>@q(L$Sg>f0ckNTrCV_pb66>72jmS9*oS~zKjv1$5_vj-r%+A<^1
zR8DQsb#J}uu?fH3nCLk?F5Yu)2^N}WMyuAu)pbYLR@3#4wh08geCQgp-ek(^1#Tk)
zVH=Yg9=fibN!D%7PPyizC(~|%d{2Hj{~j|~1It0`M<7f=3!=GR)Z7|Hgw&xGCBu7E
zWcFa)S(?|$bvYqSQeJT8kb9KVE@%8@*zpGySoyenHVc8_czfNk?vqn^CXyki!g`CJXlS&SaMIcaF`
zbzkR2?quDQX=?`@BOwQubwr+3cU@O9+8k+h@-I
zB@Qa_N+^_L2FJAz@39#_4C$CAQeq}Wx3p!Gc@))JcGG(<;Pd-H1mT-%%`W6OOOky2
zLO1Fg3H^rG^jkHNdOnoQk-F2`rTGO%uuGR0AmB0_{*c#l+;-RGscYZ%G|Zu{yTGF{
zKouZslXcw25*Liw~jpd(MCo+rVe=1K1(BVF=AXzU=FU#C93K`=3=PSk~
zCs7p$wPv)0aB$)+G;`_oHNTi(tV3v+b{=OFw&2nyd2bKS>dY$7@plLH0$BQ`TOhl3p0hSh{`xFCNq{H4H
z>n?mZ0^%#@x{Z|6eltP$T{~bR4*aYVGi@PFdi-G9q#af@&q>>;+gUVF7cLq
z?&)^ad(jVlJc(ir<)02X0e_Mgr|le>u5a(yh*UuGAKoz(Ego3YX{@~Cn-me?g7)ai
zO4V^^4Oc}#l;Bwmg%G@DZ-32;?mH8oJE^KcK1I{I`(>n6Cx2qBE5#EdpWA+|x1Rj|
zLwpuQ%UlQ5_~xO{Aq@~Jxup#@hDVVmOfl6;W=QY|ikKySGPG==YItI)qW#h}br4tb
z@gQF9`{)j
zxtqUoQ6I#+S5v8#ist2xoE*;MBTiQa0bQr^7N?N8=cf@KwYRq~B~)dTvGkmpSB?fk
zFIy|;pL#@6jH{&*Xj29n!L;=R7AKW?icteG{+q;w3I3tCO*;|q0Fa>;D06#-GVMm_
zl5`LwY=xTN#?vVa68tBEgf*L$_Y`ZP6?qUx86o+5*Ua0lc~pp=($8-tQf|3oE0b
zwHk=6Zz5(qIpbux)Q6$YPT`K#I%Hxa6x$=
zLm5=h-?)cI!EWTa)2e5%#>gZ_0zFXzb5o#Z4tXK(>nUHY6m45Z0&bKzCeT&=Y+xT_
zG4nIiKT~Jp?imV-%gV?Cv-ARv`emKu$3-T`0!r4D7(sSKL-n9oRAv6#E%cB^AC=$%
zPT7AfTQQ#PdB>nCQGMa?zWzSGQ)?aQR8`iPkFzQgGnh@9f0j^6)=25oE0mAKI$#ZB
zqP&@ukxtH0x3NxHk)Cs~fwb5~0U($zHv`Q#pG(UQvRLwF#R~|jCrBZWy?gm5il-~P
zAJ7Afd~2&Zi~ghhy9#L`s@kNK?|+#Hm76Bbf-LYq;;erw_Vcv@(N9yycXo7{B%@2%
r&;&RzsoLb_q#Y*L!{lc8zjg}K1k77SE+1`_VtURSHaQfoXT<*-4th1#
literal 0
HcmV?d00001
diff --git a/requirements.txt b/requirements.txt
index cdda0d1..1471909 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,5 +2,4 @@ browser-use
langchain-google-genai
pyperclip
gradio
-langchain-ollama
-
+langchain-ollama
\ No newline at end of file
diff --git a/webui.py b/webui.py
index eef1e3c..a1e81b4 100644
--- a/webui.py
+++ b/webui.py
@@ -4,62 +4,56 @@
# @Email : wenshaoguo1026@gmail.com
# @Project : browser-use-webui
# @FileName: webui.py
-import pdb
from dotenv import load_dotenv
load_dotenv()
import argparse
-
-import asyncio
+import os
import gradio as gr
-import asyncio
-import os
-from pprint import pprint
-from typing import List, Dict, Any
-
-from playwright.async_api import async_playwright
+from browser_use.agent.service import Agent
from browser_use.browser.browser import Browser, BrowserConfig
from browser_use.browser.context import (
- BrowserContext,
BrowserContextConfig,
BrowserContextWindowSize,
)
-from browser_use.agent.service import Agent
+from playwright.async_api import async_playwright
-from src.browser.custom_browser import CustomBrowser, BrowserConfig
-from src.browser.custom_context import BrowserContext, BrowserContextConfig
-from src.controller.custom_controller import CustomController
from src.agent.custom_agent import CustomAgent
from src.agent.custom_prompts import CustomSystemPrompt
-
+from src.browser.custom_browser import BrowserConfig, CustomBrowser
+from src.browser.custom_context import BrowserContextConfig
+from src.controller.custom_controller import CustomController
from src.utils import utils
+
async def run_browser_agent(
- agent_type,
- llm_provider,
- llm_model_name,
- llm_temperature,
- llm_base_url,
- llm_api_key,
- use_own_browser,
- headless,
- disable_security,
- window_w,
- window_h,
- save_recording_path,
- task,
- add_infos,
- max_steps,
- use_vision
+ agent_type,
+ llm_provider,
+ llm_model_name,
+ llm_temperature,
+ llm_base_url,
+ llm_api_key,
+ use_own_browser,
+ headless,
+ disable_security,
+ window_w,
+ window_h,
+ save_recording_path,
+ task,
+ add_infos,
+ max_steps,
+ use_vision,
):
# Ensure the recording directory exists
os.makedirs(save_recording_path, exist_ok=True)
# Get the list of existing videos before the agent runs
- existing_videos = set(glob.glob(os.path.join(save_recording_path, '*.[mM][pP]4')) +
- glob.glob(os.path.join(save_recording_path, '*.[wW][eE][bB][mM]')))
+ existing_videos = set(
+ glob.glob(os.path.join(save_recording_path, "*.[mM][pP]4"))
+ + glob.glob(os.path.join(save_recording_path, "*.[wW][eE][bB][mM]"))
+ )
# Run the agent
llm = utils.get_llm_model(
@@ -67,7 +61,7 @@ async def run_browser_agent(
model_name=llm_model_name,
temperature=llm_temperature,
base_url=llm_base_url,
- api_key=llm_api_key
+ api_key=llm_api_key,
)
if agent_type == "org":
final_result, errors, model_actions, model_thoughts = await run_org_agent(
@@ -79,7 +73,7 @@ async def run_browser_agent(
save_recording_path=save_recording_path,
task=task,
max_steps=max_steps,
- use_vision=use_vision
+ use_vision=use_vision,
)
elif agent_type == "custom":
final_result, errors, model_actions, model_thoughts = await run_custom_agent(
@@ -93,14 +87,16 @@ async def run_browser_agent(
task=task,
add_infos=add_infos,
max_steps=max_steps,
- use_vision=use_vision
+ use_vision=use_vision,
)
else:
raise ValueError(f"Invalid agent type: {agent_type}")
# Get the list of videos after the agent runs
- new_videos = set(glob.glob(os.path.join(save_recording_path, '*.[mM][pP]4')) +
- glob.glob(os.path.join(save_recording_path, '*.[wW][eE][bB][mM]')))
+ new_videos = set(
+ glob.glob(os.path.join(save_recording_path, "*.[mM][pP]4"))
+ + glob.glob(os.path.join(save_recording_path, "*.[wW][eE][bB][mM]"))
+ )
# Find the newly created video
latest_video = None
@@ -109,31 +105,34 @@ async def run_browser_agent(
return final_result, errors, model_actions, model_thoughts, latest_video
+
async def run_org_agent(
- llm,
- headless,
- disable_security,
- window_w,
- window_h,
- save_recording_path,
- task,
- max_steps,
- use_vision
+ llm,
+ headless,
+ disable_security,
+ window_w,
+ window_h,
+ save_recording_path,
+ task,
+ max_steps,
+ use_vision,
):
browser = Browser(
config=BrowserConfig(
headless=headless,
disable_security=disable_security,
- extra_chromium_args=[f'--window-size={window_w},{window_h}'],
+ extra_chromium_args=[f"--window-size={window_w},{window_h}"],
)
)
async with await browser.new_context(
- config=BrowserContextConfig(
- trace_path='./tmp/traces',
- save_recording_path=save_recording_path if save_recording_path else None,
- no_viewport=False,
- browser_window_size=BrowserContextWindowSize(width=window_w, height=window_h),
- )
+ config=BrowserContextConfig(
+ trace_path="./tmp/traces",
+ save_recording_path=save_recording_path if save_recording_path else None,
+ no_viewport=False,
+ browser_window_size=BrowserContextWindowSize(
+ width=window_w, height=window_h
+ ),
+ )
) as browser_context:
agent = Agent(
task=task,
@@ -150,18 +149,19 @@ async def run_org_agent(
await browser.close()
return final_result, errors, model_actions, model_thoughts
+
async def run_custom_agent(
- llm,
- use_own_browser,
- headless,
- disable_security,
- window_w,
- window_h,
- save_recording_path,
- task,
- add_infos,
- max_steps,
- use_vision
+ llm,
+ use_own_browser,
+ headless,
+ disable_security,
+ window_w,
+ window_h,
+ save_recording_path,
+ task,
+ add_infos,
+ max_steps,
+ use_vision,
):
controller = CustomController()
playwright = None
@@ -177,14 +177,14 @@ async def run_custom_agent(
no_viewport=False,
headless=headless, # 保持浏览器窗口可见
user_agent=(
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 '
- '(KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
+ "(KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36"
),
java_script_enabled=True,
bypass_csp=disable_security,
ignore_https_errors=disable_security,
record_video_dir=save_recording_path if save_recording_path else None,
- record_video_size={'width': window_w, 'height': window_h}
+ record_video_size={"width": window_w, "height": window_h},
)
else:
browser_context_ = None
@@ -193,17 +193,21 @@ async def run_custom_agent(
config=BrowserConfig(
headless=headless,
disable_security=disable_security,
- extra_chromium_args=[f'--window-size={window_w},{window_h}'],
+ extra_chromium_args=[f"--window-size={window_w},{window_h}"],
)
)
async with await browser.new_context(
- config=BrowserContextConfig(
- trace_path='./tmp/result_processing',
- save_recording_path=save_recording_path if save_recording_path else None,
- no_viewport=False,
- browser_window_size=BrowserContextWindowSize(width=window_w, height=window_h),
+ config=BrowserContextConfig(
+ trace_path="./tmp/result_processing",
+ save_recording_path=save_recording_path
+ if save_recording_path
+ else None,
+ no_viewport=False,
+ browser_window_size=BrowserContextWindowSize(
+ width=window_w, height=window_h
),
- context=browser_context_
+ ),
+ context=browser_context_,
) as browser_context:
agent = CustomAgent(
task=task,
@@ -212,7 +216,7 @@ async def run_custom_agent(
llm=llm,
browser_context=browser_context,
controller=controller,
- system_prompt_class=CustomSystemPrompt
+ system_prompt_class=CustomSystemPrompt,
)
history = await agent.run(max_steps=max_steps)
@@ -223,6 +227,7 @@ async def run_custom_agent(
except Exception as e:
import traceback
+
traceback.print_exc()
final_result = ""
errors = str(e) + "\n" + traceback.format_exc()
@@ -240,10 +245,9 @@ async def run_custom_agent(
return final_result, errors, model_actions, model_thoughts
-import argparse
-import gradio as gr
-from gradio.themes import Base, Default, Soft, Monochrome, Glass, Origin, Citrus, Ocean
-import os, glob
+import glob
+
+from gradio.themes import Citrus, Default, Glass, Monochrome, Ocean, Origin, Soft
# Define the theme map globally
theme_map = {
@@ -253,9 +257,10 @@ theme_map = {
"Glass": Glass(),
"Origin": Origin(),
"Citrus": Citrus(),
- "Ocean": Ocean()
+ "Ocean": Ocean(),
}
+
def create_ui(theme_name="Ocean"):
css = """
.gradio-container {
@@ -283,25 +288,27 @@ def create_ui(theme_name="Ocean"):
}
}
"""
-
- with gr.Blocks(title="Browser Use WebUI", theme=theme_map[theme_name], css=css, js=js) as demo:
+
+ with gr.Blocks(
+ title="Browser Use WebUI", theme=theme_map[theme_name], css=css, js=js
+ ) as demo:
with gr.Row():
gr.Markdown(
"""
# 🌐 Browser Use WebUI
### Control your browser with AI assistance
""",
- elem_classes=["header-text"]
+ elem_classes=["header-text"],
)
-
+
with gr.Tabs() as tabs:
- with gr.TabItem("🤖 Agent Settings", id=1):
+ with gr.TabItem("⚙️ Agent Settings", id=1):
with gr.Group():
agent_type = gr.Radio(
["org", "custom"],
label="Agent Type",
value="custom",
- info="Select the type of agent to use"
+ info="Select the type of agent to use",
)
max_steps = gr.Slider(
minimum=1,
@@ -309,26 +316,33 @@ def create_ui(theme_name="Ocean"):
value=100,
step=1,
label="Max Run Steps",
- info="Maximum number of steps the agent will take"
+ info="Maximum number of steps the agent will take",
)
use_vision = gr.Checkbox(
label="Use Vision",
value=True,
- info="Enable visual processing capabilities"
+ info="Enable visual processing capabilities",
)
with gr.TabItem("🔧 LLM Configuration", id=2):
with gr.Group():
llm_provider = gr.Dropdown(
- ["anthropic", "openai", "gemini", "azure_openai", "deepseek", "ollama"],
+ [
+ "anthropic",
+ "openai",
+ "gemini",
+ "azure_openai",
+ "deepseek",
+ "ollama",
+ ],
label="LLM Provider",
- value="gemini",
- info="Select your preferred language model provider"
+ value="openai",
+ info="Select your preferred language model provider",
)
llm_model_name = gr.Textbox(
label="Model Name",
- value="gemini-2.0-flash-exp",
- info="Specify the model to use"
+ value="gpt-4o",
+ info="Specify the model to use",
)
llm_temperature = gr.Slider(
minimum=0.0,
@@ -336,17 +350,14 @@ def create_ui(theme_name="Ocean"):
value=1.0,
step=0.1,
label="Temperature",
- info="Controls randomness in model outputs"
+ info="Controls randomness in model outputs",
)
with gr.Row():
llm_base_url = gr.Textbox(
- label="Base URL",
- info="API endpoint URL (if required)"
+ label="Base URL", info="API endpoint URL (if required)"
)
llm_api_key = gr.Textbox(
- label="API Key",
- type="password",
- info="Your API key"
+ label="API Key", type="password", info="Your API key"
)
with gr.TabItem("🌐 Browser Settings", id=3):
@@ -355,51 +366,51 @@ def create_ui(theme_name="Ocean"):
use_own_browser = gr.Checkbox(
label="Use Own Browser",
value=False,
- info="Use your existing browser instance"
+ info="Use your existing browser instance",
)
headless = gr.Checkbox(
label="Headless Mode",
value=False,
- info="Run browser without GUI"
+ info="Run browser without GUI",
)
disable_security = gr.Checkbox(
label="Disable Security",
value=True,
- info="Disable browser security features"
+ info="Disable browser security features",
)
-
+
with gr.Row():
window_w = gr.Number(
label="Window Width",
- value=1920,
- info="Browser window width"
+ value=1280,
+ info="Browser window width",
)
window_h = gr.Number(
label="Window Height",
- value=1080,
- info="Browser window height"
+ value=1100,
+ info="Browser window height",
)
-
+
save_recording_path = gr.Textbox(
label="Recording Path",
placeholder="e.g. ./tmp/record_videos",
value="./tmp/record_videos",
- info="Path to save browser recordings"
+ info="Path to save browser recordings",
)
- with gr.TabItem("📝 Task Settings", id=4):
+ with gr.TabItem("🤖 Run Agent", id=4):
task = gr.Textbox(
label="Task Description",
lines=4,
placeholder="Enter your task here...",
value="go to google.com and type 'OpenAI' click search and give me the first url",
- info="Describe what you want the agent to do"
+ info="Describe what you want the agent to do",
)
add_infos = gr.Textbox(
label="Additional Information",
lines=3,
placeholder="Add any helpful context or instructions...",
- info="Optional hints to help the LLM complete the task"
+ info="Optional hints to help the LLM complete the task",
)
with gr.Row():
@@ -414,54 +425,74 @@ def create_ui(theme_name="Ocean"):
with gr.Row():
with gr.Column():
final_result_output = gr.Textbox(
- label="Final Result",
- lines=3,
- show_label=True
+ label="Final Result", lines=3, show_label=True
)
with gr.Column():
errors_output = gr.Textbox(
- label="Errors",
- lines=3,
- show_label=True
+ label="Errors", lines=3, show_label=True
)
with gr.Row():
with gr.Column():
model_actions_output = gr.Textbox(
- label="Model Actions",
- lines=3,
- show_label=True
+ label="Model Actions", lines=3, show_label=True
)
with gr.Column():
model_thoughts_output = gr.Textbox(
- label="Model Thoughts",
- lines=3,
- show_label=True
+ label="Model Thoughts", lines=3, show_label=True
)
# Run button click handler
run_button.click(
fn=run_browser_agent,
inputs=[
- agent_type, llm_provider, llm_model_name, llm_temperature,
- llm_base_url, llm_api_key, use_own_browser, headless,
- disable_security, window_w, window_h, save_recording_path,
- task, add_infos, max_steps, use_vision
+ agent_type,
+ llm_provider,
+ llm_model_name,
+ llm_temperature,
+ llm_base_url,
+ llm_api_key,
+ use_own_browser,
+ headless,
+ disable_security,
+ window_w,
+ window_h,
+ save_recording_path,
+ task,
+ add_infos,
+ max_steps,
+ use_vision,
+ ],
+ outputs=[
+ final_result_output,
+ errors_output,
+ model_actions_output,
+ model_thoughts_output,
+ recording_display,
],
- outputs=[final_result_output, errors_output, model_actions_output, model_thoughts_output, recording_display]
)
return demo
+
def main():
parser = argparse.ArgumentParser(description="Gradio UI for Browser Agent")
- parser.add_argument("--ip", type=str, default="127.0.0.1", help="IP address to bind to")
+ parser.add_argument(
+ "--ip", type=str, default="127.0.0.1", help="IP address to bind to"
+ )
parser.add_argument("--port", type=int, default=7788, help="Port to listen on")
- parser.add_argument("--theme", type=str, default="Ocean", choices=theme_map.keys(), help="Theme to use for the UI")
+ parser.add_argument(
+ "--theme",
+ type=str,
+ default="Ocean",
+ choices=theme_map.keys(),
+ help="Theme to use for the UI",
+ )
parser.add_argument("--dark-mode", action="store_true", help="Enable dark mode")
args = parser.parse_args()
demo = create_ui(theme_name=args.theme)
demo.launch(server_name=args.ip, server_port=args.port)
-if __name__ == '__main__':
+
+if __name__ == "__main__":
main()