From 7916a4019f7d7f367368d5b4e8c151512b9dad6e Mon Sep 17 00:00:00 2001 From: Kevin Sylvestre Date: Mon, 17 Jun 2024 14:43:56 -0700 Subject: [PATCH] Support for client.transcribe --- Gemfile.lock | 2 +- README.md | 8 + lib/omniai/chat.rb | 4 + lib/omniai/client.rb | 14 ++ lib/omniai/transcribe.rb | 152 +++++++++++++++++++ lib/omniai/transcribe/transcription.rb | 26 ++++ lib/omniai/version.rb | 2 +- spec/fixtures/file.ogg | Bin 0 -> 65743 bytes spec/omniai/transcribe/transcription_spec.rb | 17 +++ spec/omniai/transcribe_spec.rb | 57 +++++++ 10 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 lib/omniai/transcribe.rb create mode 100644 lib/omniai/transcribe/transcription.rb create mode 100644 spec/fixtures/file.ogg create mode 100644 spec/omniai/transcribe/transcription_spec.rb create mode 100644 spec/omniai/transcribe_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index 1b373d4..02f8127 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - omniai (1.0.9) + omniai (1.1.0) event_stream_parser http zeitwerk diff --git a/README.md b/README.md index 160a532..570a05e 100644 --- a/README.md +++ b/README.md @@ -111,3 +111,11 @@ stream = proc do |chunk| end client.chat('Tell me a joke.', stream:) ``` + +### Transcribe + +Clients that support chat (e.g. OpenAI w/ "Whisper", etc) convert recordings to text via the following calls: + +```ruby +client.transcribe(file.path) +``` diff --git a/lib/omniai/chat.rb b/lib/omniai/chat.rb index 12a33e4..1656564 100644 --- a/lib/omniai/chat.rb +++ b/lib/omniai/chat.rb @@ -33,6 +33,10 @@ module Role SYSTEM = 'system' end + module Format + JSON = :json + end + def self.process!(...) new(...).process! end diff --git a/lib/omniai/client.rb b/lib/omniai/client.rb index 588695f..fec7ed5 100644 --- a/lib/omniai/client.rb +++ b/lib/omniai/client.rb @@ -45,5 +45,19 @@ def connection def chat(messages, model:, temperature: nil, format: nil, stream: nil) raise NotImplementedError, "#{self.class.name}#chat undefined" end + + # @raise [OmniAI::Error] + # + # @param file [IO] + # @param model [String] + # @param language [String, nil] optional + # @param prompt [String, nil] optional + # @param temperature [Float, nil] optional + # @param format [Symbol] :text, :srt, :vtt, or :json (default) + # + # @return text [OmniAI::Transcribe::Transcription] + def transcribe(file, model:, language: nil, prompt: nil, temperature: nil, format: Transcription::Format::JSON) + raise NotImplementedError, "#{self.class.name}#speak undefined" + end end end diff --git a/lib/omniai/transcribe.rb b/lib/omniai/transcribe.rb new file mode 100644 index 0000000..899875c --- /dev/null +++ b/lib/omniai/transcribe.rb @@ -0,0 +1,152 @@ +# frozen_string_literal: true + +module OmniAI + # An abstract class that provides a consistent interface for processing transcribe requests. + # + # Usage: + # + # class OmniAI::OpenAI::Transcribe < OmniAI::Transcribe + # module Model + # WHISPER_1 = "whisper-1" + # end + # + # protected + # + # # @return [Hash] + # def payload + # raise NotImplementedError, "#{self.class.name}#payload undefined" + # end + # + # # @return [String] + # def path + # raise NotImplementedError, "#{self.class.name}#path undefined" + # end + # end + # + # client.transcribe(File.open("..."), model: "...", format: :json) + class Transcribe + module Language + AFRIKAANS = 'af' + ARABIC = 'ar' + ARMENIAN = 'hy' + AZERBAIJANI = 'az' + BELARUSIAN = 'be' + BOSNIAN = 'bs' + BULGARIAN = 'bg' + CATALAN = 'ca' + CHINESE = 'zh' + CROATIAN = 'hr' + CZECH = 'cs' + DANISH = 'da' + DUTCH = 'nl' + ENGLISH = 'en' + ESTONIAN = 'et' + FINNISH = 'fi' + FRENCH = 'fr' + GALICIAN = 'gl' + GERMAN = 'de' + GREEK = 'el' + HEBREW = 'he' + HINDI = 'hi' + HUNGARIAN = 'hu' + ICELANDIC = 'is' + INDONESIAN = 'id' + ITALIAN = 'it' + JAPANESE = 'ja' + KANNADA = 'kn' + KAZAKH = 'kk' + KOREAN = 'ko' + LATVIAN = 'lv' + LITHUANIAN = 'lt' + MACEDONIAN = 'mk' + MALAY = 'ms' + MARATHI = 'mr' + MAORI = 'mi' + NEPALI = 'ne' + NORWEGIAN = 'no' + PERSIAN = 'fa' + POLISH = 'pl' + PORTUGUESE = 'pt' + ROMANIAN = 'ro' + RUSSIAN = 'ru' + SERBIAN = 'sr' + SLOVAK = 'sk' + SLOVENIAN = 'sl' + SPANISH = 'es' + SWAHILI = 'sw' + SWEDISH = 'sv' + TAGALOG = 'tl' + TAMIL = 'ta' + THAI = 'th' + TURKISH = 'tr' + UKRAINIAN = 'uk' + URDU = 'ur' + VIETNAMESE = 'vi' + WELSH = 'cy' + end + + module Format + JSON = 'json' + TEXT = 'text' + VTT = 'vtt' + SRT = 'srt' + end + + def self.process!(...) + new(...).process! + end + + # @param path [String] required + # @param client [OmniAI::Client] the client + # @param model [String] required + # @param language [String, nil] optional + # @param prompt [String, nil] optional + # @param temperature [Float, nil] optional + # @param format [String, nil] optional + def initialize(path, client:, model:, language: nil, prompt: nil, temperature: nil, format: Format::JSON) + @path = path + @model = model + @language = language + @prompt = prompt + @temperature = temperature + @format = format + @client = client + end + + # @return [OmniAI::Transcribe::Transcription] + # @raise [ExecutionError] + def process! + response = request! + raise HTTPError, response.flush unless response.status.ok? + + data = @format.eql?(Format::JSON) ? response.parse : { text: String(response.body) } + Transcription.new(format: @format, data:) + end + + protected + + # @return [Hash] + def payload + { + file: HTTP::FormData::File.new(@path), + model: @model, + language: @language, + prompt: @prompt, + temperature: @temperature, + }.compact + end + + # @return [String] + def path + raise NotImplementedError, "#{self.class.name}#path undefined" + end + + # @return [HTTP::Response] + def request! + @client + .connection + .accept(@format.eql?(Format::JSON) ? :json : :text) + .post(path, form: payload) + end + end +end diff --git a/lib/omniai/transcribe/transcription.rb b/lib/omniai/transcribe/transcription.rb new file mode 100644 index 0000000..83408a5 --- /dev/null +++ b/lib/omniai/transcribe/transcription.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module OmniAI + class Transcribe + # A transcription returned by the API. + class Transcription + attr_accessor :data, :format + + # @param data [Hash] + def initialize(data:, format:) + @data = data + @format = format + end + + # @return [String] + def text + @data['text'] + end + + # @return [String] + def inspect + "#<#{self.class} text=#{text.inspect} format=#{format.inspect}>" + end + end + end +end diff --git a/lib/omniai/version.rb b/lib/omniai/version.rb index 5d25942..0529669 100644 --- a/lib/omniai/version.rb +++ b/lib/omniai/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module OmniAI - VERSION = '1.0.9' + VERSION = '1.1.0' end diff --git a/spec/fixtures/file.ogg b/spec/fixtures/file.ogg new file mode 100644 index 0000000000000000000000000000000000000000..683ff131c50ddeb9360459616eb3492564d75ee5 GIT binary patch literal 65743 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

B4uhC-A^BXcXlp?S1`FO=L3 z-*_OnH0S2s#1~wsjLUL^9%|{6yQv_y5w{RsT1OlJQ7w6M~1sWor*P8y=)4A>uZyKe6D40rG{=Wf@Fj z-`-MxfV4jtgx9O4o;iM5F(Am1gQSmIV#U$Z;Kp2`nb`vxnz+4xo_NVw$zxmi**B$? z$ba~s>)6Q+dPK&2-JkJ#^bZlf9Ww+)zGcB31qZ!+T@*ZUdfN@c5q!FGx$U_=qcX<6 zj(Jz;M#w|OGm<8gl7(b1luP0VxF@lTkpFG46?8Ot5i^&Wd{M65mi=U&RN9ma4JS+G zYKZ^82P&pHqO^lEsQA^n$QtrsH>v^Hd*U^mwm0;7=sYelP#(ZYu>8|#iIUoAZ*;in zYmhG*$Pb(n16&e!b!oyUY>MUU#j%@u_y%OOnVUW$SJ1;1wwlm1KX$pTqts?jU>67O zJa{O0;~meu;L^SQkWbUYG+VsTMx@0R%}(FT%M`%!&L4|_dGeVYRD%v0Y90_PXzUu2 znVA$WfKlrR_^9`me&50g2$FvDE6(U8D0J{t^HE}Zi4hFCHM*aWV)&Ud&E&LCqcnV8 zzeI~+6{Ut_S;zV3F0Rcwg?8>k#libayZG%Gj3?Rp;e?^p!sGBBw*t(`mAbJsq3cS$ zy`uo>Ng=IkM%(4uvFAUF;EuI*&!|A=L8k@*cV;(;Qfh17ATdSLBR}_;ps%8wap57h zd3bj~c({M5$&;kgo%6HOqyJwW@m~!FYqlR53-VrF7Uoq@kQkPRzCz!P$~jzcm{w#- z^YrjY3N4T)>Z(5H_ayqul%_!L03pyQ&EMs6%s^91-Qm;y*F<+TLgcea;`#_TaG()> z%p%R^kctBf2f}#Bdc;`q;5@8&!sNBjO9u&nNCvj zY-AYIC&$)g1irZo>|M0i<9Al{gKZ0GhEOXbcxm_Vbl-iu&@h&b$`R^**v$0+gAA)c zE}JOrOz2y`yD{x7##O9aIPh!N8N<05m^suVTa453y`ZEKAEfBMXXr&$1?vqBS09L|Du{F&_FP^JsC&gl zI2LTz#55?i!nnS0$roq4wA~a5JhXySo368Y{+UVvbCj$RfD(7Qfm$+2itvqU?NQ_> zUr5gN-+%kFjc50(#_M?DouP5d-+8v#9~X!4F|#dRvnjK`tlr4zn{2+!RfZh6fA)Jv z&q6XU4kJvZ;ic}|(yNxYS0_#7Yfm&<@;?%)ZU>#w3`#N4v4UTv2@^i_NK(Cz5xr2C5G3bNkrrD<7 zm_2xK>?x_Jp3H9_HM|%U-&MILp(w1H(_FH*mCH~58aMc?(K4R+{0rU7-|J;vaaUJI zNE|7}EUZ7m$j8T(wG6%7M{aX?y;z)33aLxNz+1s26i1beSBOLF+9~;=Ndf^W-wUTy z3AMyzI5)9rdUjvWEz(n06r7+(J*Hh`zI-)w^REmdU(3P4FgBI)m);w{zkJamgBxfD z#jF)URShY?$e>V@C^BhZiofHR$qgTlygM`=0ka zC@sEpYvO)}qk7>~iBE(24q`6g`+0jnKNRrbDERC0kMoDRvtCP=BC_28VAayc3_F_P zQccOJMfcg-TV?WV#)5-o3u&SAfR)k8Yti>T|5e9yz_8lgm zWFIf2GsvBY0 zHnpk?Pen#Fl(V|`Z5>4P%QTSUp$$KMd!+;#|MMw73Eogh*?< zfr~psi<>G+_*XBnBW~4Q+NmsV^0HZ9xsSE1C3W;S0w@*=Q!W=4Y_nyqU-Crn7a2Hu z?G??v48YpbQce6{x6LTpc<5*;#v;!0sAu4oWebAP7XDPN;B->rlmh3*Z0+*KVs&HH zELILKWN{Q(Z|$6|w?-5L4H68{zrQtk)B72FQn;)vZ+|q2e>vC1MgCyulkTyPFxI#s3w!^e4X!0jLp%iJ%}A$ zA((sYvj_GbwVoQi)5R)6$^~6rDnY+84weG_@V=;$~n?s#U=>B#mvm;(_WN*SX zB?~y%N8INS0u3RO7uoi_LD2xYLL>jg#|@ChXkCeBMy{%3p-m#7#T)cKkcU5JR1kDK zYi8m9bRZi4w*!F!I}oY!-ZqjzdZh>0Zg8Rb`$mQbMsUDxgg2;b@Bv@927MDA7d3aX zjb4zBC1{zeJ*IfC%|gNrzj{8hOY)5Ti2z8UDQ}>O&HuWv^u{GYMcaMN_ZMKd6iF8f ziY$S;a$65TE8aMZeAua}ZL7}Do)NfV{3riHh)9%BdH4a+RWy2F9OZ4LmdlArg{+)j zsiP$Q@7%YHwg#! zBheM#TX!yLU2G{T8=_Os!-jL)T!;&awZ5*QBRau#!Popp!24~{-CBSw#b-R@XGmF7 ziM?`YJ7qLaBf;@T!8h++>2P-NA#0p$`zKW6GrZZ;#iVzf5qcygv5G92-pj`3$Uu3! z56Trhby!D3eTc64G38@N`M#$QM(pYiPL_^9hJStEw=W%!1@0c%!?sA!8GaA6FDHLW zI5w6S^{V$mT3EqF2p}qTskr{$ko41!?j!k!r6q$WR`*bNZ2 zaurwP)!0LWGF`${ct7@Xr+7-=NpDq?HDY+7SNGjIg`2p2on=&a{uvZ@H~A2gL;$QJ z#-!`&i{etQ5#lUFMsCxfrjU~GNw`Js3Y96ky&7~u>=FKx_y_1Z?br5FQ*i4WquK47M#9Wr51j>3rKx$%1O7DwCw)X^FbgHaSZoHT&W#k#>K$RDQN zC)E5-1;!XL#yuNcCpGw2V_}f(nwW8^bgk?F1ppzSlVn;_95lOI81jtI4JR3Rn5~a74{%v7a8Ea z8kBaDnIUf5kk%Ix$zZxtRU9C_Cc7r>ajEiduJpxPM0YsfPlwyaXV*hy_8dSznc8k{CTE z-lC?t2N$5r$vyi^Y{{SYj3W~gTggDutd)12K*F{#q`#Kp3-LT^E(T7L(EyROWFlQu z?-OnS<}+|%b$|ltT)M9Xf-vdpjj0tl$L(;nvI0!jDa_-|&h(yyW<9Ubm>s3{`L6NZ zRbqM++BxhCwgO)b)o$4YvGI)e5mEtwPz0iH1x;T1h|oUX0k~r(3NG+hH`6 z4a5)DAtzy;Q0Q)U@!$Pdhc%Y`?zW6G;h-2u%nKO*kQg&@vTEVWcX{r+IQ{_aGncer zav8#<_&D@I-9}`m0fjY5N^}Z>xU$h&vppG`8m~;8ke&~a$i;a|*ubXaOE;eniLgGg z@fD=P%xB)_H+1aeH33D=XW3E|!!w z@zr(46rtpJa#-xu4b!{+jR&g#{j9l>!Y`VF%rOP1T-3s#&x2>|3}e-!^&y*!qSIaP z`g&E6W&J}j!>%1Cd zcN z?y|z+VtZAJupCt+7Y=Zl91h1y7tVZZ&3}bv0d!^&0+K>+CB~+`{${sbR7mLCO)ia_jdhL&M)4LY>_47xCJha=)e=J^1;f%)i z+#m4+vIR!*i+6NDZS`BK*tbzqinJVn;j$<>OmPKAcZNi9^Z)oG-BV+zPVSs)0SdUJN97M0ogIbrBF zt@E-%6A5W|q>vnXe9S@q2Cfx}@@afqZ?)dWb~74!9|4WA?aN2&1@0 zu0l_W9tZ3%miE6-o3|SH<5Zv#Z-iRIa&}6TwC$L)Ix@WY`O%o{3|QdLT#Vh^)X(c* zPSCxd^Jc>KTGn3G?0lEK;_TMYVu(2n*x(2gH!xsQ+u!V2 zG0o}dSlzM#`2dK%8mPM2n|=6jOiS}8T}Q&f9^U11F$Oc1_$cJ(!#8h6UFlSWR;qGjnD;cS~h*vtAj& zplo4%@{fwAUy5`4aX?v3!R{m9PmCN3Aa^y(hc@h=w*+oREsuJ1cJb`#4%&WcMQ_zA z_=?$&G1FJgjAuXOZJq4hFCz-p9S5!^oeRmRoShxHasK3m=`g_U6?6zcDa?kge0kf~ zSUj^VcO)`6_x5$)C4c36|5H;q;sGA54{6QYqi9}J@h~8yXa+nrhY!OS^b3k0dU0%P zQrBs>a1eaOGjR648OQo>5~j(V=y~vJX5XywJzgRnD$y+IuY$ zp<_&uO$E4U7o%6r8bwecy9jh;4OKYGO2? zQwy9tT5;g^pbZgD6)8U@#i_Ru+t|kew!Zko-1+FABNqx^e)jg?bI$twlU9&{9P?*I zP}`mLKXX&8w{89T_|EBjhxD@rANG7bemM73_4TcPmR|20tvU1A*4Vpl>*|2J)wO2{C9;j= zC7N%K(^|8hh?zl03(l!u96ERj0ecoP$l;ML?02qy#liH%?duGiwZMaGDOjl#>sY;n#mVs>OZ9EfEDx=_LHIq%%~~lOc@9a7aiQn0|!9C8=mIw3`W4HZ>hK z6-EV`$WW+kT~&Nu6xnv*G0hoZGzP{RS(EF;cfxTm^JP2}$v_=02UQ-z$WbFzZVE@@ zToJwUc+cS9)&JD3Wnn`Jg^mnwXP(ka!Cj^?(mgl0+Kuk!5&SLyM%+JVA|rp6i;j&k zR_y*`Urcs!swI80_3QFxXp28u9aCInbFojz$<+92)-j*&rk(MRCbcjb@?*eZdT`sSt*`wObFmAl@0PkyXtU&*b7Zs z;GK&WHA<02hTX0%TC3)mM2I}5Ak#mDWf}tK_8DTUB1ns5@LSdbB+ugQs(0&Vkm(0* z5w>&W9FgU_L9Y#0dmdCL5(kJ&c6Etu+aBNDa@|uYRvzjRx|QxV0Ok%@UxWfajX{BF z`v~Tgh1*-(q8bY}0NBQ5yS@UQZX%IR)}QiUUSQsapj_7o`@HQ%QnXwi6|?vd zD(!6fmVd*+1eZ`_xL0xCmF*32WCuB+pTOyQs7W-TLZ>BM4o5G3bI6T9pqipcYY!-M z7N}nV2HxDeYa_E3t|Y69svMc&nBdEu33AZ@!?e|x=_xbgbgDS;`JfMOO*k9Bf=D%g3D#$mfko1{?)isdCw#J!|GNfRCFX3`hAw5;bYAW3SUQ zx2<6eejO>Q<@YGR{a4Uwek)h_hXn@)g#PyYZTH)U!S-jZqSHbnI4pX2BpBQg_?yY* zW@*;HBg|Jm7%5DzEkx}6|Biydqi_FlB>puAMAypU4+nk>#*3fdA3#Pdz_3dLp@4M! zT8Od{g+&6U02*Ctj`47?vmXFWb?Aoy<|~=7JVK(10fk1CmIpV!vxUnEhaSi<;uvS} zDkhPeW)z~eD8SYzVg}QPXe3e*(G3(L%h_8d0^A5X@-#&#^_pdJFqb1jz;r%By7M-F zt`A2Cfz?w;FX~pZ{{4PK4V`}E zem+o~cgwL#U*9M#4mV{?f4=iG@z}5KC2e-bh>i)&6D{3lzV{di6UUBPlV%O1^wv=# zy{F8ns@}{81c?I*{+5w<){I6PC$nB5bF3qBX30?Qr&FK)O3`ixe1J*ud{!89r;=5i zq&qc$C9nTMzHbQCTf`A;!abxg=dfj3;K1~cFSt(EN)f!_=fZ;Na~tmtxxE)um4ZN{ zLxYp_il6x`^k!Xf{EIsG%^cWv=L%tozMNq1uU8X_G-Q&h;zgb?h=t3*I10J7H#Y(z5gfj14{-=Q+CWFyfK) zh89{LaN^0T)?;NyNzY&xY=CQwBX(@XM#clyR~>4eYc((Y}3q?g!| z0+QvGIHVlI%MR{%7R=a;g(dFuJr&)6$vX;9S$gl3*RP@jP^~bwa;JXZQXJ%jFt#E| zzi+eZ@;+K^$B@Z=BOiMM5}4^e;_9J6NkVE*}W$~Tb>Ru(6ILCkYXkT9X0>s6$s(J3mfYZfK0brf(~ zwoyQ%r$J#R82Dv(VvWs-c?&6|1WWi=o}Jjlws*)9b;z9oDz1baN0;rIIFd?KqL=EjQ^8y?=Mx_nU}StqtG)ak58_7 z0OPu!1sd1QOVh-qqXOI<&W8D-MIM&RKve=s@A|OZ_@B_G<>UOHplkW(uTsNcL}7MYPn%L1qm%oW zw3~rI5^gfJ9m9!ab!sqU0?_u*^?GX?9LDPU_~mHgnjHK9@}6*hBf~lGsIuAOI9Jj% zbXeJKzW+4na)L%Db|G!A<2elq&zMVLggtLxU zHa~hy)A#-Ba)@yFV*yYFyj|$eyjqdLA*+9R0Z?GNVttnaKyv7#-Ox^_lrk3 z165HA65JBp#0d$ABzhsGH!Jcq#b#l@xAp+x^dT`8wk`%zBCV4*+cnD2N1MD=_Hz`3 zOeS+2H4pYpNOb~SvJTTh&6}p7lUxVYGP-r>O&53hpj0W>#N7MQK9A9!H_ooS z{PF)IHpJc^B!4lp{wRgMDx6;2P50ZgLRV$s1`*>KA)v(kaKZZdz~!XbTQ^%` zlDoVH1`#P8c~0K5TD&X|H=t?aCCdc8?VX)XN|a1BW-Tx-m*U|mg=Cp#wtgyL;Sjoc z^S1A;kChWr7cm&nEE<(ME1NTr2dnio$4;!LDc zB~lnwEUW&_4ZMDKcEOFSC6Q=BG0KE>+}k+`DcGGnRSZCd0reIQ*|^42ip zOZnOC(PdkT)(%I-Mpa%+t2jtmll5^otlZ~Vz_CVR)Oe_s;>+vN)kjZEeC^VI*q)OA zJ!bXF>riw4tw$+`?H^ukM*(<~Ig|)Z72y5cuNY;WEgHI#F|@9{d}=|&ncxKG%4X}W zoFM+zfCnoXQPEt*PM*S@#Z7K#9x5tk{1b`X>4Sneh&vmaumx^z9(0u3DS`o_2-l#R zCMIinMLIrrK!9^=i_%5u!Xr&|Tw~5lag3m=NqDuUiXy`l$?5GNkrxiQDx&MKUAG_3 zMwwgTfU6xP%e8qdty?#e1mvP6@!N3OloN}gWU(<|L(Rb<_~jhWK-;F1Isvu~hiyo5 z4Pr_{hKsGYdJY#Jx-e4EYX!8MpmN;Np^5#PXYFB_WGyZ<(Fv-?T|UQi7Hgln=cqV0s*6 z8Hwd|tKL@{&9Y9>``QgTTb!bC<1LVWPaAqydya^wR ztQ!==K70v_!FinS8Vtesnw0pn{_B#x-JIT^e&fsU{jd~#n(dY7MciDq+gJj|F#X3Q zhvO|JTHKjESJIdm6ke3gi7g_4G+^DpnIxJ^hBd8f+LU|yP<-kw=(&rhxrX9sMi|#h^8Hnmoa;imxXXe`;OQqZbUj;!EVqN0KzeC#R*XkJPGr=RLKaj%{K^n8X@569*f>=O zVBZU_fW%m4Hr^z9=n>}o388T(^dD)`!mfZ@1Sn+EQAK%-aU`5&5LI45fx$aiOmjv; znj>H}u+Z@6of^RNbLk_eNK3o9-31p#y)ekJjF&eiS?bXjOvJ2IlaUcTfbU7Q3w{aH zA*>?^A&p>^Wg8rSZt`qCyh+Z>=zAI7af{!`@@}(OU<~Bqm#h4?xjS6~H+h{i+3#<2 zU?&0KPFs1G(L{<&h6KMKe5HyL0B=(jsan*647q~P)w!vGIPP;q=H?~ zUAAyp`)9hT5KoG;8oTwqQTb5T#?9OWfj7#J7Byb`6D~=V`MFBUpw|M?h}@3+L<_Yj zhtMqI6<6eYCj}o>0@6qni@fc#Xv*!zhD( z|CPrtzX#F4m#a+VP?J0(pYknZPJ`nvKjowV1C1He`57V)yHE&0>z;kQG|YzWmI85$ zqdOO!HH+Ky*Rf&k@a_Gd{7!*62IYKc+aOvta+DhI^6_~>5?I)z_7Dpm zF^9UKTCT0h_x?=@{TBpPnI?QI7#b|#?&np%9lM!e?D6%W_V^}sc?oO8v2fNm(?bKd zv`jg04Tpx8SUC-BhC#z3XxFYS289SOj$Z#8vFz!#nV(PbYrnxs4Qo2 zHm6gGl|oj_`M;WiTI%R-c;mPiBqoDOJ&CjoraMBdLV9DD+h(pUSf3mo9E&sP5~#0d z>x$ZRP)8qxo&a>vAKC6r)d-h{I9qC?)&?)1Ks(D5#bq&5oup8nRuW#{3CN*)0Saqb zKRbfgF& z!YReD-VR67+a)1e)JgR7c>weJX@dudxBgNf#FnvVJBXurnI+h;r(^B zX6_Mlew;n?tkkJ0X8&bNbokRYx1nQ&I}gh&yB$w8gYxb^Z{G`!w`#&%Bbsyk6@1}9JJY(p@dZuV^yvg( zR(bYzQuX%6!TVj*%R#)mAy4=d{VraJlkt`jN$>4^jQG5M$SDgH4p-ZzhnoT3x zSkr-(S1s`O>o~BrTB%I&A?^03w2+2bsh|kj>CgI~;-h zZh1PrpghQD-k;qNkc>r|RI$v&K#1AeXPwuV;11&f`l`U1f>x8UVhNm4yi)HuVe%x7 zAh9n-<-X!Wikx65c0%LTy053Y_^arD zS`qpW|J#Z%0Z$idBg4-nJe(O8@_P-9L8H_BS!>pWhlJ8ru3)j*tTkca7>CRK9Z2Ja zh5e@gUiF({>un&!wHHlPA77c`+v$E^;NTVZ6JqYNrciGVTxUGlAwsU#Vjs}~WSdITs`Ai(eeXHgx=Th0eeW`s5*N%Ff=4~Xp|JD5`xSK)oFc6&K8pvBbb zw)<qGCgjp0bv)D}GhuHc zDl&>CLnMu8XQ>3XZBO}P6EGa{rPE#_u$$q4(q0KNntu7y!`E80BEh|9;wqf(`R0KfST zXOL6Lc)ZkYpun0W{s43O0}LERd+ly+0qH;A~UDwjxCLks%&xu+W8fI z9sEk@bSfvA2Zjc6SyP}=g^H({1Cp!s3xZ};Q_Z2Sjd4nTRHa+Gv`^omSTLt&nuVJH z?xeW0ZG@93z~D+*^@6%BMg~h_up^MyNQ2SQI!o3rOT&Qcj@5O34nWPYYa;=SkQGo} zB{&j*?rPtZlW9B=Ku?oaD8w9NfAJl!BEbSxQYS;x$*!z-p#hm2xGjtqJYg1wgw z5oP!L2yM5?C{7=ZmIg!auE%hx?P86~aD*>~z_5?OW46{_l0 zhaM&}&xxzNqOCs2E9)I^6FVjn+dRd?^`=bAMVa-q+b33gK;}M0h?d4{(T?^f=bLyW zxMzCH4d zVuTl_yZ@Vg5j{or(QWVXczK;1*yNFqX`faHdC#E6#pN~R4Y41d13eru1_6AOJ17mDxXT?x9k3_uRMP% zeQ}|A3%C)t_u#)P^|YCmC)La~k?x^iePsX)JN-XjOCi&`TDPAY4pKZ6(wKfLZy!~( z8J~7J?iy&nR+YW#FYayrdS-0g_KMl8 zThi6iIFCUjZ4UzTXmo^U7b#rMnmG{H2we9)^S6(geC6Sty6?vZZk-)n-1@^}iy2V# z=~A1j6MX`! z?`_*>(;{B4=YOluxE??^|M;5fQQ5oId~RlC?SuSDKL`4OyVYtY%!nQwV?q^cz1SKR zlK&q^S@Yui|9xDn&}jI4&GLXoTB&WK5jL=tFAOZPtOIl8$(E8zQz4Upwt2RN}_u?EZ^yqHC5emGRp6$N9TfJ(wlK zIqk>``7zHn-n9Zg-ub91Y1%=ku>dPsNsHR5#^Uxljg!C@)`$mXc5+>tB5Wb$%ybe} zKou$-(Pn)CUP&CzIzl*QBsG6F6Ann$Q$_Rz;<2R8pyyD(_kK)&oPkUA>ZAK5YTN99 zox7Y)=kn2r4h@g_y4}8#AmG8lWt8(sP$7w!Hb7>B$W|?JfF%5mV7}6jFWMaV8zAQW zb*#bH-1dp5^3KMr@PK3eHO;#3*UV7QC*BwagLo%{n?jRlw@ER!P0T^Ju?yAex)<~Y z3Y(kwGTe(IW+}&cKp}rjN;lrU?G)wv{AKADe*bvVJck3}uAVPGg49xm2zoR=6$?b# zUnVr1G7-CMEQryF5bSu{mdy&X5K<`chb%v;E&cT3LhB*3?~%ZQyB~?m5!Ec|?(GxF zuLu&bTMq$O-)MWA{ju(GETvBTYjR62G}>!bS;n`r$oJbWgxGFOfg$ZKo8ET-OrR?~ zJ>pg-Y(c?xCbq`Rb&!dR4x6vo&2!;9Ww3`;wVtI`O2<%*)duW}r0JiH;r-<&vqTgaUMc*x>zdn4r^pl>W7+tY*z>AUUT z$N;$e3A&;4WEX4iXCH2ikCP=ldOlEDh!6ruGd;lk20(6#bgEDJV1>9Tnyj9-oJ;75 zlHIMg4}cgH^7`v2)Q-Ro*VOe5thw+U+UT1DV=TJe zoyku=<-P%(^Y^Xks4tyCUb4{>6EHez`?5jluoo)(t_U;w>VjIK$Rq%x z;cAVMr=H-!n^$W^H#73IBmUI7CcblOLFFdSf>XYAcV``~$B2hX2;!u`ty%qg1CNs- zANu_TzqMa68$p86jyqN6XL7noiowp`?K7J;9i5hg5YKYyFJpcsu4!@JdBHM@vpZ_vQyx>3~P+qziMMHTbpu+z z;GIt|CqWv0oll!q4)ILA!_1QaLJ#ZKA+)4~}uhxk9 zpMHZwqew#;pt#$4YB3qeq9omE2ZOa}KfjF(=@9lXcLKSeCY%-|=?}U7`QpK_>GezWoK3AafWtO1WOksoMBZ(}NgQ<)6hB8dmGeTsp zAYudL+RC-|r4OP{Q{BJ5+8R%`yqI~FTz0RcTTMQ61pfpnnsTheFg+<0Atz8tkx)rO z9tXt#0wG62IL21}=zf)IOhxg9H@05hUlQ%XMVnrWI3HOZ-}Pp_j<~UMwszdSVb9t# zVy{ovtCLD^e!R%Cm?OyD_!v&1f`_5wUNSlC=&EWZXjPFSlwrx4XRr!*^t8yW%}L=i z{K;uLghTTKQW(lp9+a`yxU!g~^&_*E8=ohyrM}%Oz1ZlRDhiJPl1S>jzoo%}asapP zC0A>~V-|stCH(y&3AUP2bX^bhRySp{xsbWXZU?08g7Z`$8!#u{$qqYenTOqFdLih7 zk=0E77_Mq=*s1)CArt+OK*a5h(JId z5QS+U+^+2*1Pi^*iaiv(wrX?qR_OlO1|Uxu~fXNp2&tt*r2lVV2d-$LEB zV$=2_bp0!R7tq}1)+gmd1`x6J-$u@Y%M+m0HyrM)Rvd>@0Wv#-G6M@hlr!t&lsM~< zD)RAXmag{UlgEWKkITIH9Kc3^og!AM$RsK1)wQS&go5Vb_m|mlpv`)r zD}s6445#FQ`qw^Y2t-JKIwxqiyRa13uX^S=T`y=IBWtAK$HyC`2x6UuMc^m0$x8%m zx0{U3OArG@AXyJkz8J5i*T|mS*h{$5bqO|29(+_Dm3wUZ!{QLTK_Mc={#2)RE2Byg zd*8kzeR)XymJbgJ+i5El3}l2?j@?2V^b{c$H~kS;dUZonCUeTO?%OUbk_aC-R}WMd zG#g#uZ!QSF`Xzb2Zl>sGP|xa3=J$^6QHnjL+oGeLnr=7aFs>T52|K4wuwRA)F@E@S z3$S;5Q@B%J&1@JUaR27n;EJQ2wXUUR z_d35oywm9}P!14iLmqjcV{+jc0vxYUoQ$QFX-Eo58-~XzlDNdd&-;4LU)M#b|AUtZ3Q zHZQMNWfXj>4uHb#A#IxJifNWY^$ZP5iR1&u^FdFaB zRQmCk0l4LM4@KDdyGOZ_irkQ zNYoZDOQT)R7UhbujAuF{h9@j+M@L5*!LZ%{ zjW0=28l!!frZdxyc%?X(nv4(&mrU@0L;UPKvfN)+!385|@)e-;+ z-NkaHLT@=DoBioL%7(YKL6(`nKE##eMb^`*@-H=_ix}e~$XwX2PZ7(8k%ry|ct}3l z_+e*nHcf|w-b8Gv2W}oPq3w@2*cKsky4n$bjRJynj_uvM>L+#go?kz{y02PQ@$}d+ z;K=eGKGruh`8hhjf?f|jp4*-Q(FCRc) zm`BF!DE;i++)eg|SrT!ItLXxjR1Z)Ai4GI3hte9FHg5q$ zyw#CQP=H)jNnx1*<0yy(Ad#k*0F?-!`}ytw;t_{Zd~0m`a^?Q(Pa_}BSeKLwDqe*> z3iWKEgKSn95HLll9Hv9p>o&X(av`5& zb!TuTq`xB|IFsv&=$`PU6Lf_vQuw zPPuw=lfZ}*dp zBPMrEkw>^lhDhenWAY$*!AtU4g6u$eHe;%#&^`*1(@HD~`cm}nsoDNpOCPI0&V~3z zE!cE#XbwjUCnb{%XhyU~o8cI1{e`W~E44CuVUSluc3So`V-c-4$$qM>3A3H)583U# zWL@iW=Vgpm|DRBR@G~7LvyrtQ1reOR}S-AV>qY;%(k-V}9m34ITK;0~u zw${Z)ck2&IDF#va zTD}XPI|gBgPauMWBQcm#yNf~ePN?|wZzIhLolOqZ_xU7E|Nc066#A91qO~l{6h_@g zA=?!%nLPD>l`S**+aZho$v9_w)J(OEu6N3H8oU+)m6TpDX4tx8VRgGF#4?j)cFhtp z)zL9jfiXAtUZT3{PR{)sz32uyxe}kRjv+LA8BatQX!5gC>-f0BS+WMaV^8rh5ojdc z_%EX$o7}w3z(LpVJ*8V6%Im=WA>Bdt=F7LsJz+ZEX@V!a-^bN-Q7mw)9zwtAGqARq zfG*PD21GF3m`36vHn2JEIiR^Nv%CNE)%B`I$or#SVTkFB=&XY#Xbe@6)vf6{-Crw2X+^w9Jbu<|M5w) zmvc${$URi(@Z3FX-}thxL88O&SEXz^VU!uK#s&3xmoY`CO=s)$aS(?Vm{ETK$UMc{ zK)4}R6NA(3iiK5TFDFFonB36>uSp{0#8-+b;#4KSFlmaCq>)MBy-F(MXXhb@9utMQ zP-HVgOVJb5aUqlAXdZ4$4rHQNWBhJIcbG`wleC}b;^;)IMECWZz7SoyTF(aYHZQoJ$9-*^M1VlgV{ z-`(dnKT6T5LR3d%nj)U7>T>@+{ynkAgx>G3Kj$tB(;FhQxJ+EhfCpSLkgTPAlX zy2ZBtKV6*(RFdi2{~r(#6%7;!(Hg`hL`-n2v>H&rB{fJO#A*lCPy1Y3duUVGR7AT1gfCPY;ap?534Ho`* z8>LA_B}FR*g-={6^O4IXTt-J+eT_^;Q8rw^vxHrRzvh0%2MWyOBJ)Viv9^GK$6Mn> z+bLww@Nf{0%^9O;(^_Q@^!hE6z}-8>An?xuHD1KZvD^??$Rs_AtCd+w=zr}ygGoy$J$2+qC!4&8&V}-jbvOU|x5gGS_2Vu};40NS zddlb|vHNQ^)p6UZwDvo9@@+3Sd@Vm6mdsx}J@8u#C?;{Wg2czJ*b$!HNn=LQxF=Le zDZdX6j>6pJGLzE3YoOGxbPDEUCI(ROG!w7K$}kSxB_yk;y+VGsqzrFkXF@Nh_bUN+ zLT-gl$Pj^r>z;mAd3nS?lAbcHP;c%vy&R9a@g(9Vt=s}$1A9E=?>;KvtueHeLw6zo z0@H}dXzJc$oKkwp_}DHZ-8)OaB|+FRV@*(4y<*Dks{pB_eYfxSJf%)65%NwS*wGic zS+yp(Q+Sw-=z3zmLMfHpp5C|NheP>)ez_(J2v3|*0_gY4WZzpbx1;92AYP2ub~>or zbD*``a?x~|Fwm(0KGnE-Tp(H#6ZCEBLbqf-3vwO}3kS@e$ZnFEIVJGA#ssY*rO+Wsv=rrT33^$PlXu%7k&UHJ1;8Fi5@X9?+?0 z05i2Qr1>>U8RV5-gu-XSbxN|b>6WAYM0W5xpQAq{WHurtd~CPEt+h)~6+~#nc&juN zl^x%}Go;%X6ao6d^vVyB_MpT(moP5Dl^_uvfK;zBr1OIhzt>3EIFn?Oz@lQdxP0e! zC3_bfr4r{%D#bfkX;{yJJI>Y34PseZd0Fx&WMjeo4OVwVFcuCJhNUy*5MX5LG8A~1 zKGXZfqITD76tK?sYt}!H)Yecrq(pS$c+3gyg%rR!-y`?K?O*4{Ie+~d zoE6W%SD%V(Mm5;eherUqIjfE&tR5nknzST<4YsUh>2I%HUCnU!>;Dlm1PDABuirP{ z-ek(~_Nu7e_1C)fovjv!|JB8w8;+{4p}And@m*ePE71vdoHZtSq9ULlkjS2mZ*Csx zQK5iW-u)i=vA_YM`)pM8S#-tNKmL(}uc+G8iu{L`Vsb+<$|4|_S)AgN>`&|qLbJx? zO6e7ElK2dFygv1qwMrCqwKl*3@)%p<0k^JNjhkDboQbZe`JaU|68Iw@UkFo!2mjd) zH)iem)1UDjj@IOKtML+Q#rwMo!sTzvmblu5gq|mUcYu89)@0b@fV-cIUj?mSl>1B6 zlU#tlWQni@LV*y9Bdu&8qkPYq^#(hS+RCFbQ(^a*uC^0OV7PSWz$`3^2+68ok<6$4 zq0{6%X2*~76W+cq;e`xGKxE%3%n-Iu7j|s~amQr}?1i(#f9#9j^$2fbge??&*0$^*M_<~yyItg&+B3lnG#5CqO^3T zBhbL@PIoa+b6r&?3K17Su7dk>4d4ZGFkq*4x6f@C=6Uh>#5&vg@`iAL80Q~rm+sU` zocl~JNf~9$Ahd-+SHA<8&BSDCS0x91VMV0-(lF2_)w|ME>@Wg`r4EkD>|}0M6UgE6 z^FP#k-TZK!dwhEz4sttmkc9PJxg=`&5P1#F+t4YtpOQCog*t;KS7lN@{l#}hF#=%2 zOfrC{$J2(P*lFA@ZAhI;5nu)37!FR^;|1QDX=}pKBboN);_NU0DP#n81wHP(O(rq^KVE-x?TF;NKD#K&7} z%8g1p*gk$f0U2z&_()^GSK|=}KdyS9!)>wU*9i6D=7sONU;9+_AxmU7#fBP%*_XIbm2i9^kn&mQ+J0IuH4c(U!qFSH=YN3qxb zHrpjV8Tc#meH}hY(L0>$I9<&C(eDi^X5T=<@RE2iBZw za@PazPed%ES57E1eSO-MF8vINXJ(eMk{@^|3>FsQz^O>*pXJ@1mcbdr4YNMg%MU~D zU0nRC!=*@d?FRd_Av%m56tR6<_%qU}+FEg`ePT+A0UPG&W<`HBKbj;dn(Ur3&%`mZ zdNC7-sCdcYu5>ZqOS}x@L_@FfDh{yFX^E5j5=)etX%Q?_r$$O}g9r@W;ThUpjP8~! zBFhF(emiZ$XBcF8Du5ChN^y%Hw$J+Yj6o|d0!>h>jg8lz)L&|!q_jD|ktHyAnu0bCH5goC)29(v~d z>@^cGk`Ni)Dk?xioZXeOdgR(OB=C^? z1tYNH>dt~;KWeurJ=}Hev;&-)0B3DB9{0W?RXitQLPe{GXD(y z>J3`LHDqz)re{Alh5qp^sU`6GSQ^(qZnMv}i_s&$f9y~BVaYuWW9zR^H)|v;22@hk zsv)vjmTCp7M`WY*QYgnhx7i%a93XpQE5D@A*dKd-5(X3SJ3>v=G0%75P)IqTCIw%} zAxlcq+XBeuxo)n3O6J0x@@Eb18D_vaRZ~i@9zg5fquS-k=2X#UL@zTg6g3$fo}nX9x&Sf6Oy!Q0Q0|>;Bo{I=Nl!CoknTNB>h$>^cm{Lb|F#(Hz!pO> zW6at08~GdcTg3OFthH;`f@_y=jBj+XwXh-tY&Nh#O9ua2#3|y(fS|t610{ha25cKK zy6kWJtl!a(G&fUd9IeMA3bpmPmK9Kl-4O z#UOATDxZ>5D5*Fd7`By78Pc-AbO71rwzezpio#IGENe#}W`(#(DEfj@apo$#vGCd5 zujVJ;u4Z%g6uh~PPOx%w_}UwjEr?En*G#-$Bcn^;CBlJ!YrL&2aqKNm>b^UapPyKo z54ie&URLN|sX#J|e72YI00aQQFb!#}`s-kv-7!lSO-om#lF5@I=~Fx0t`0og_v7p9 zbuaUu?Zv;gUOl&AXkvBQy{EOK5$TcN|9|iP0ZI=#3~>D(;rpyhvEZfx;u5tQRa~{x;l~5F`X!MREmW>Z6)EO0KcT^tF3ar&U2gk-z)5@OwB;M$=Hn0ui_|TwEzpI_ea>GH(@0v7|BCwq z4-^mY9kC)a)F`>1Xr_@7;6P(97&DamZP5a`|G{BwPHUyIbOe&LZPVuz7?SQLA{ zsO!}9w5B5#hjGLNprC)$s(?&!o;oB#fgK}si9q`Poe#f`+FC?06;BIgC?)fRwAReEZ zH84n9eA?}BY&rpL;0jp52tmX)wld1LlmQ(IB6X`nQCw?Ajp4dIFzb^z!R_VAFTRbx zc~tDeb)B&ZZ6Dxjsd?K4!?{Ms&KBA-^vQ+0EYpuUuCXh1!MCT0WhA7Pc_?>3&Gp7` zy35(YkkUu-$A3e74;RO~p6n=nX-ZtZRBnH+XGD3)?pcs!r{8>vML5pw;R8zV0c)3_ zE7=b%RF}t)+-Ns)a@96}E&}(sI^Lf^=C-=rk-@cRRz9<|thNR<5K2R9{fctg-c>T^ zixn2r7V1&=A$1DCxEewI13A7tylJf9HK)H5Qv-q^5k=l_&>8Yq?9cFu(m2IoXz5>r zNYIcZaGEd15DHcPNn4_uDb~I)>@g(FHXY2Tq9!;LTEPSuzUTFu0j=xC?Ssw3UC%vV z^jC-9mwyuze)PQmk=g9>vB>pI-KE7H(8lk(&Zn-w>2HPCHxVBD^D`#jP+vvVH;Odt{V}UzB zpnFR~K$MdM%N5+t*(UB9J|qKW)=#du`&5@u=_@2Sa*zXHEt2*`gc1RdMm=nr0Lx!O7Fp z69gC>t(B?j>f~{yb;XWy8OP*i5VRYkdtPu)>}y-OD93e zhqYu7l+`=+GZ5@hVUbq+>*+>IX}7t7Dk(8%ckI5;-&f4x*tw2 z`zdon#?AculMixE6JWxkm@-k~ptv!%5vr9zj0a~Ab$;x;boBD*%`Xv@<|>ctUq(|p z#gab*zwJ$q3-JirpR&04YsBuIerMYVm*3w1hqip#xvPG4pXe8kmOxIoEdpjas()yi z53HXbI<&NDI&O#n*{rfvqfdjgr#{)BcwFH#=(=-X_p`UZiB4`m-vCvl>XqprEoBM8 zSXkMLUBcy{OT_+DBUxv&s-;K-hBsMV;dJh6&@##(!heYByu9s~%Jr>whmx7q%%pMfyR+v)NJV(+w%3dJaheSmt6F-9+UN zzLDsLB$`uqZx-D+ZF6^_goEMfr7)NIzqva|P1*U2nufRx0N9xiW1?Bi4BR~IYyMvQ zT*yP~lfOHY)(Pg_mo|HS9_>xcICyK19okd-(dEBC2)wvzuous= z@9OX--+7}qx||v4dr5AgPEw>+SMAf7O_U7L4byFFOQU8->j}UnH`&xV|8)>f~VtoIR6&O zGPDDm$DSU7ATuq)z3iYfl`F0DBck7RrvGv@;KD!E;ex7KnV7-RJvGxAY=;}fWj{)C z0D0H^OMH5%w`$Ie>?Qa1z^tvTtRSm@JY<1_IZxk9E?<@(EpYV zrE(gzDkXfuNdPUhuAYQJ3A@4(@>c~lQ&&F)s(Ub?m*?s34UNVT$1C|qq2c3n*rC7g z+pk`?Tx^cHXusB@?aXa&jBA17*<7>N%cP3e$2*kusEEkWr_-jA)2BX#H0`JxE;x#@ zDp~lJkRVl&K_eW%wIyVfiSxwhcpAR_O4`))RIMn~aJJ-#+pTU)4?(=}E`2bB9!1k> z+wdNNajFJc0#Wlq1myHu@ie{-bLS_Tgs#XABW19u3slt=Ue{ZZ>-^QdfW?EeO12Ay#X0%8ymb?UavR-X z`_9V{I@W~VK4rl z_kWL!?#n2tACBb5ve_66$3@V^ZMxs*a3p52tkYO9!m>Y8DXmXa)j>#Pjly7UrXXxo zJ$RujweX5?a1*viOe<{FILr%rv@xK(u173u6r0vX3uB|RuH_B3g-CS;Q@*{kOnVg< zWEdN87~9$KTU(zzsQWD?aYh915OCI&*FZ-?V78!=97ydZMO1=ihnhyTp=f$I^S^?I2tip7NW2gy?~ zd*y7nPq(x;`Po?CT;nphEsmY)HNfx37!d;Ggi3EeYKCwlln3 z8)3mU>ix28-`%6(;=3{=%`{KQyo_^L#qqU1|lMr(;NRs{M<WN?8x2 zCyrj(UwL{QO@%rp7vDU*{KHHA*@5eqLNvI$pI-lG8BZRoyyx+JI%MN@>{yQk1?eE> z5zp!Z4sOl!ML~QdRv+#Cc=~bAGOrve6kqV*ZZPoScfJ4Ydq11(Cx5;MS93?RPqp z>+d|-Ky6Fc?#myO>O3=>3)V<45e#ZfrYy;{;?A-|N`Z*ao}0_k$uIt=qKY+_Q4R+RTrdNX^NHD|{zk-(w(DR*Wj` zBYI;>a6*4Gn9G=s%hQE2z_@lG^Bb>l_H*q$_iYjOa>7;}#??DMUSiu4 zw>4v0@)~vbp`t9!Lgw01AYmA=JsO!1aBvt&wMuhFx>;Lwxl`H4w=k4&HheiiA0E9ZKx5dG9s|(O%>PV( zTB7R~dQD{}fYF|@?b<-3Mv@%%cuWuBA^R`cjw|$hu(NRL&|T_m_HHCc3YNd)e*t?Q zcYQz&L-oM0p&XWSc{P5RSng`!cIyn!xcLA1E0_oVx2v$=Kc|*wNmMFmoM3%h`7M|m z!WOTMWrZ?BzGre`*9usxf>*CvEfVo#V)$UEA?BOk!;1&3V*Q*CY+B?V)$-K*EVj1( z*T+xhD8D8}UX9L#W?nlT{QmHc+_GUoB`0QKNYF-RX&T-OQVXMZ^ny@0gQ15&K(t<2 zg?Dmt3chGvB>MO5A`dpmBc%*`E1G?5f3p320}V06D4yoEsA? z07of=m(PY6Bi{uBM#LytnF$~E@T2 z|0*%=L*Q^o^M~))Jsq}=3N)mPl5stJ|4~ocnZ^i2g-tDSR0e~^4Av$=0nE((qV#2* zvyu!xyXo(@LnIMnQlEZQ*fT(<3kJKdyxC`tCJQ(d+KQVTK@Gh%RXbI~N@) zMIoF4!J)_H(s85;q|r*Uhe^h&EKY{N=_a4;R zddQ?3y*tG9_;%4Ru;iL1&gow2Jvj)6M#pJ)k!a=6N_@%V2)}Q8$iUHyS9VM)3{dR? z0zfL}AZC*xrB71Q9$ka0i&g?|kHLJ*P1=>x2z7VIpOvxJUjCWEtas7UvtTuEidd@a<|0y*Jyfj%MNv*ht&SE(H#N|q64x}`}g;#sfB52E`eIxz_=cF ze4&uj*pr$)hg}pD<{D&>X;l)5*0vT&40g(rThXm;9NCnW(DJa@*E>Au{Ui~GH6PL~ zVwb=Hw3sWFxmQ(dCL1I$o6>CP2m|m`PQBoXT}S}nQd3>k6E;yMcOrFqBy`rIeOERVo_XiEn&-}!y_E%5uGkDt36 zV_hRTh4&T(UqWJH5NtXmY?f2MSrJMqSmXim17GSQm`9EYZtyRPvD=5dC&yQbZce@1 zzA7ho$E8#!Yqh>z{a`d|_N#*^hw zidjYJWz_-^Nz@&bJ;yUa0gf7b|DmOGq@>Ojz)o4o3G{$eTx8#i9!+bAXVdXRPT@>N zq%rhMhn)g~eXpdl8g25f(@Yt+`WGJ^yw;k)?$~qloxF9KSAPD9a=b;xWkSd2R$FTG zRsa33UFs<0f7@_4Ot+jA36tw^fbs`9fc@&$@%$gvx+Fy8 zafTxdsS$Og1uaD%Ec}@t$#t*%Ta#@qTSSEMaag~j&ws*#(eguavjwu_)D+U9D|OIZtu2J=HwtsAO5;)VClG(^ywR* z7t;L~dG4?C.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 literal 0 HcmV?d00001 diff --git a/spec/omniai/transcribe/transcription_spec.rb b/spec/omniai/transcribe/transcription_spec.rb new file mode 100644 index 0000000..0b65407 --- /dev/null +++ b/spec/omniai/transcribe/transcription_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +RSpec.describe OmniAI::Transcribe::Transcription do + subject(:transcription) { described_class.new(format: OmniAI::Transcribe::Format::JSON, data: { 'text' => 'Hi!' }) } + + describe '#format' do + it { expect(transcription.format).to eq('json') } + end + + describe '#text' do + it { expect(transcription.text).to eq('Hi!') } + end + + describe '#inspect' do + it { expect(transcription.inspect).to eq('#') } + end +end diff --git a/spec/omniai/transcribe_spec.rb b/spec/omniai/transcribe_spec.rb new file mode 100644 index 0000000..8aabd3f --- /dev/null +++ b/spec/omniai/transcribe_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +class FakeClient < OmniAI::Client + def connection + HTTP.persistent('http://localhost:8080') + end +end + +class FakeTranscribe < OmniAI::Transcribe + module Model + FAKE = 'fake' + end + + def path + '/transcribe' + end +end + +RSpec.describe OmniAI::Transcribe do + subject(:transcribe) { described_class.new(path, model:, client:) } + + let(:model) { '...' } + let(:client) { OmniAI::Client.new(api_key: '...') } + let(:path) { Pathname.new(File.dirname(__FILE__)).join('..', 'fixtures', 'file.ogg') } + + describe '#path' do + it { expect { transcribe.send(:path) }.to raise_error(NotImplementedError) } + end + + describe '.process!' do + subject(:process!) { FakeTranscribe.process!(path, client:, model:) } + + let(:client) { FakeClient.new(api_key: '...') } + let(:model) { FakeTranscribe::Model::FAKE } + + context 'when OK' do + before do + stub_request(:post, 'http://localhost:8080/transcribe') + .to_return_json(status: 200, body: { + text: 'Hi!', + }) + end + + it { expect(process!).to be_a(OmniAI::Transcribe::Transcription) } + it { expect(process!.text).to eq('Hi!') } + end + + context 'when UNPROCESSABLE' do + before do + stub_request(:post, 'http://localhost:8080/transcribe') + .to_return(status: 422, body: 'An unknown error occurred.') + end + + it { expect { process! }.to raise_error(OmniAI::HTTPError) } + end + end +end