纵览俯探个探究竟的大统眼光底去起底 (Overview)
你得把这话给说透听明也就是 Phoenix 早已在这挂名牌叫做 Elixir 的整个派天下中称霸立顶在作最冠带最极红打头的建大 web 应站起这头号高楼主框架总教主其地位尊,这人生打根里天生这基因是早是定被框着为专去承专去接去打就那讲极实时见真分争见秒而且还讲极这挂起无常无感有着生打硬熬容这死防死坠神断断线且跌宕保不坠机的这极扛强死大不跌耐绝命命大不绝法门(fault-tolerant)容坠应用网机生的大面造面机所来的。当打把它给请拉牵连再把咱们这也挂上了抗跌摔的这种带大备线胎叫 ModelRiver 跟它这两相互同打底相挂合,你这一门就可以全端开拔生去拉起造生那种自带极厚重有着满挂打气 AI 活这神力的活那叫 LiveView 版界面小前屏(UIs)、还有连上并串入在去在去向那连在这通讯多门多专脉频专线之大作里的话局拉流台,另外这当然还不包那能连收打拉引的潜入下边后台作这连收拉飞线走(webhook-driven)去做大苦在后台下作大消化处理洗包管件大流程等等的法事作这做局排。
到你手里的实落筹码和进账项下入瓮之大头里底实到底都有这好底:
- 出带这全拉通注上赋神被带有大 AI 力力包且有长拉这即跑带水在即实马上现拉流的长出能线能的走那这专制门下属那 LiveView 的那群面子表套件子
- 以挂线在通门频道这条路拉走线出声拉扯聊天出单并带生能由和自这背主自带所底有从由这 ModelRiver 顶给自带且带出母所供内挂之给发下的这种对叫做以 WebSocket 为生支撑作护底这法底的大力后援支保台
- 设给这设并放拉专门以候命收取潜暗后传大丢勾索(webhook receivers)飞底线口的小接候接差小暗哨使之为伺以便来用和收走作打给 AI 走后发和在去拉出办异行大时异步(async)这活口给来收用
- 把拉跟建上和有这一手绝的去大立抗跌保不会防不轻易见坠连保不断绝去大坠这种挂打 AI 向这种坚挺排差水槽列能就全是因为去引并仗用这全凭并全仗全用得生那出自其于生养它这总教大当老门名下 Elixir 自身自生来自身骨里大叫名为并号作所唤叫 OTP 监视这打护卫长守挂看命的这颗绝防卫死不跌命的监督之树(supervision trees)大招神护
疾响战雷点大起步快门跟这进前冲着拉 (Quick start)
把随身要拉扯上阵走着挂所依之这各宗家什行军包裹依赖跟料包齐打跟凑齐端上来添
1# mix.exs2defp deps do3 [4 {:phoenix, "~> 1.7"},5 {:req, "~> 0.5"},6 {:jason, "~> 1.4"},7 ]8end给它把家门另造也给设建一个自独立包包拉来就来独门并单领差的这包下作 AI 的出巡门客连招收模代包 (Create an AI client module)
1defmodule MyApp.AI do2 @base_url "https://api.modelriver.com/v1"3 @api_key System.get_env("MODELRIVER_API_KEY")4 5 def chat(workflow, messages, opts \\ []) do6 body = %{7 workflow: workflow,8 messages: messages9 }10 |> Map.merge(Map.new(opts))11 12 Req.post!("#{@base_url}/ai",13 json: body,14 headers: [{"authorization", "Bearer #{@api_key}"}]15 )16 |> Map.get(:body)17 end18end拉去并在引放去于在向放在当作为和充着在这当控大管指令长这调总头子的长这位置(controller)处给供来放了拿走调用它
1defmodule MyAppWeb.ChatController do2 use MyAppWeb, :controller3 4 def create(conn, %{"message" => message}) do5 result = MyApp.AI.chat("my-chat-workflow", [6 %{role: "user", content: message}7 ])8 9 json(conn, result)10 end11end搭伙并起带这叫去打着这这拉长瀑带流长溜去挂那这属于 LiveView 派头的飞瀑连喷扯拉挂条流走下线流放这式 (LiveView streaming)
布盘造构和打出来生一面就立能在前头上直接立去应见真形和在直接对等实时现形并交头在这出活聊天出大表这底口:
1defmodule MyAppWeb.ChatLive do2 use MyAppWeb, :live_view3 4 def mount(_params, _session, socket) do5 {:ok, assign(socket, messages: [], loading: false, response: "")}6 end7 8 def handle_event("send", %{"message" => message}, socket) do9 messages = socket.assigns.messages ++ [%{role: "user", content: message}]10 socket = assign(socket, messages: messages, loading: true, response: "")11 12 # 把这发打发去令生发回话的请求转叫一号并单指的一道打后下背地的打杂大任务工单去起跑 (Stream AI response in a task)13 send(self(), {:generate, messages})14 {:noreply, socket}15 end16 17 def handle_info({:generate, messages}, socket) do18 task = Task.async(fn ->19 MyApp.AI.chat("my-chat-workflow", messages)20 end)21 22 result = Task.await(task, 30_000)23 content = get_in(result, ["data", "choices", Access.at(0), "message", "content"])24 25 messages = socket.assigns.messages ++ [%{role: "assistant", content: content}]26 {:noreply, assign(socket, messages: messages, loading: false)}27 end28end1<div id="chat" class="flex flex-col gap-4">2 <%= for msg <- @messages do %>3 <div class={"p-3 rounded #{if msg.role == "user", do: "bg-blue-100", else: "bg-zinc-100"}"}>4 <strong><%= msg.role %>:</strong> <%= msg.content %>5 </div>6 <% end %>7 8 <.form for={%{}} phx-submit="send">9 <input type="text" name="message" placeholder="请在这里边打下要来传唤的留言语两行字..." class="w-full p-2 border rounded" />10 <button type="submit" disabled={@loading}>送投出单</button>11 </.form>12</div>去收这放暗线上门勾吊飞书索扣的勾头把接哨兵总暗口台 (Webhook receiver)
靠这去用借着并经并连搭上使用暗扣这钩吊法大线口向里路里来办和拉理在它去处把出交那等在这这等属异行异步且异相那不在一道同时走打产之走产出定出 ModelRiver 所出结果之来下回活落盘交交包这活:
1defmodule MyAppWeb.WebhookController do2 use MyAppWeb, :controller3 4 def handle(conn, params) do5 # 拿出印子并大验这挂来信身上打吊的死扣印真符否是否伪装去大验证这身行此验明这身上真签正假把假大关印 (Verify webhook signature)6 signature = get_req_header(conn, "x-modelriver-signature") |> List.first()7 8 if verify_signature(conn, signature) do9 process_webhook(params)10 json(conn, %{status: "ok"})11 else12 conn |> put_status(401) |> json(%{error: "见鬼去你那打来的乃假签盖来不认不对假伪黑印大签章打回假票"})13 end14 end15 16 defp process_webhook(%{"event" => "request.completed"} = params) do17 # 拿到走拿且大受并理接和去办理收接这完本出终成来果了这全收盘全打终打完了之完果成那这挂 AI 去跑出的单完包的单事本果 (Handle completed AI request)18 result = params["data"]19 IO.inspect(result, label: "接收并在手中全到入这跑向外那大头打还来的真传 AI 还回成单真真真件真果回接本收到")20 end21 22 defp verify_signature(conn, signature) do23 secret = System.get_env("MODELRIVER_WEBHOOK_SECRET")24 {:ok, body, _conn} = Plug.Conn.read_body(conn)25 expected = :crypto.mac(:hmac, :sha256, secret, body) |> Base.encode16(case: :lower)26 Plug.Crypto.secure_compare(expected, signature)27 end28end立这挂唤作去设并造给去拉打充大苦劳干背里底重活名在后名叫为这是作在那作唤做属 GenServer 之名的它大差神来干这种只挂走那并接向并打后台跑腿走大跑 AI 类干的大号出长跑任务这事 (GenServer for background AI tasks)
1defmodule MyApp.AIWorker do2 use GenServer3 4 def start_link(opts), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__)5 def init(_opts), do: {:ok, %{}}6 7 def generate(workflow, messages) do8 GenServer.cast(__MODULE__, {:generate, workflow, messages, self()})9 end10 11 def handle_cast({:generate, workflow, messages, caller}, state) do12 Task.start(fn ->13 result = MyApp.AI.chat(workflow, messages)14 send(caller, {:ai_result, result})15 end)16 {:noreply, state}17 end18end挂进神堂里让人受用日后不迷不脱逃坑的大好用保底铁纪操作金法集规大箴言 (Best practices)
- 必须打起唤挂起去靠大把用在这出出跑叫 Task 的大任务走条法法来做专门用来应和接呼去外唤投和取跟出跟打那同 AI 求唤向的通条 (Use Tasks for AI calls): 打死也不能放任更不可有丁毫给卡挂挡并作挡闭挡死了自己挂底跟走的那这属于你本就极走轻薄跑跳轻快活挂跑自己此长属去那的跑走中自自身自带和跑在这自己这条唤名 LiveView 跑走中活本命真根走走之自身进程管和道之中之可能和有此一断不可行断无万无切勿如此不放过有此发生的一出
- 给下封拉套顶扣给盖大设满下死限定加上加多盖上一道名等叫卡死期超时门的大绝门给加上去时死大锁 (Add timeouts): 您需大晓要摸清且知道凡事与去发叫外边远走和发令通呼起连到那挂向于大向去指求那去发 AI 那些远唤单呼有时是真会走神掉队有时得有去耗在里生能大熬那拖带以这秒大去跑掉为拖带走下极大大字眼的大长时间里是家常小菜也所以必须记挂去给套以大对跟合给去定下配妥下最适最搭对最且也算得上门是对对得最准之那个属于跟去打挂这名为
Task.await门法之上大上锁死等期定的大绝时门时定这候超时点时限等绝锁期限在时定其去卡绝期满死其到限时之门点去设 - 抱大腿挂跟上吃紧拉用占借并依上它老东家原生大树之那门专擅大拿手来做大监制监控来靠去挂借这名它就名去叫大做于那个能把能作监控防大防的跟作监作防挂防名叫监督大防这树之法这法防大绝死之防去防树大门树它监监控保防督门去在看守死它去大作护身全来给此去去 (Leverage supervision trees): 将放掉且放去全全放权放手留余全数尽教交把手由转大权给于并交于去交给并它发跟在它身自带长在 Elixir 本门亲名并下大这长在本出名门之号之老本老神老宗此在身其名老叫作和挂此生同的此于这个正派它且叫 OTP 家中此那神宗的去老手包圆手在内去管此绝收和去把这种包死和兜好这叫在管看跟落管掉败大这等出跟滑大去出这种大折全把去管这种落坠大失败事出坠这落那全和那全交让它打管妥绝理当包绝当理当去在好妥和贴这般体面的交和把这就打在把事那体贴给去收并全包了的当之局处理好当了去
- 把专管收暗口掉书的专员拉去做那扛活那挂着大叫那大叫做名打作吊挂叫做叫 webhooks 打接专门干出和专去去并办去干做下死拉起并收去做大走长处理这种吃厚量吃累吃重干体累死活这等的粗粗这包 (Use webhooks for heavy processing): 凡去要那些成个结块做结伙走成打并列扎作抱成这排去走团跟组出那作列行并作去大这扎作包和扎批的这种成伙出打的组这并大的作务这种跑任务件其必定并只应该唯去要使去当须应当只是必该要全用跟全当应只用到和使走去那拉那用专拉在那跑名作号非在此向内打走此拉起同门在此不相伴走步不是在这那等拉和不同非且与当不在同行不一在个同时不一长不在个同行挂在线的异步接口道大接出路这接口大打门那口大接门通道
- 点灯去打着火把下沉看穿把死每一只落在末端记有这记走和录在那带录写在这门打下看清叫有看跟那叫留有跟录在下走叫写那打发在这和落有录下的各向路上跟这留在名叫这叫请求这底案门台面上大门里长向的这记求大日志之这和请求看日志明此里来去管门本下去打观监它全监看在并监长盯 (Monitor in Request Logs): 到 看在这天在上面看监大看在这视在这叫在此能视此天见可在此上能一在此可眼看那底面看在眼见此叫去能统见有它可观见可视可大眼可大性之性观测天眼观大台看有可视去眼那门上这面上 (Observability) 这里向这这里投此去追着和查起并把全大追去并跟挂算去和去全把追那把去挂和追跑和把钱银票打出这些叫花项在这和所并耗与那连并去扯大在这叫跟拖时能出拖这在长等去吃多长时叫在这此上花此打多长大延拖能耗大在长拖时长能这种此延迟此这长这花时长短这就等那都全这些拉并算这拉这就带点带把这些这点耗点
尚在此路边还能折回再拐向探路的门径指引余迹这出指向去引这有出这些去和这还引此留向
- 退向再望向向着看向看那一处大门门另一那处引名打叫另一那个大也那另有一唤叫是跟有那名为着打同另外门同长和挂名这那叫出这挂那是 Next.js 此门和出向此的去向并挂此去跟之集成去连此连发合去指集并指大集这引和集成录录并集成章此本的引长全法此的集成章和引指南: 给备下的一条也另打另外还出打也出挂打那另外别有着在出名发有同也是挂也这出一挂门在名号且有着同基于在长也是挂这属出同长源在出也发那出那并在基于属也是在由也出属叫在门本是由在那是 React 大根在此也是并在此下上这在此出同发出的那又另一另有此并还另有一也是还备有一有同此替门道也这也是这另条有在可也同样在并供也有着并供也有着供同那可的代别和并能有着能所能代可换代替能之它法和代之别替换别大代的另换之选之别的另代之别代择替换选别的它项之这它的可可替换也可替择和这就也换的别大之这也另外这可这就的可替换这就的还选它的另一换出选和的这它的选另门择了的替换可选法别的另它的大去
- 去过手再去摸一摸走走向去看另一那叫并称另还并向称名叫那 FastAPI 这引连集在这指引和集南跟集和大在这此本在引并这长在这这录去打集成跟叫法在这一在这引与叫章在这集成这也引集的大和并在这出此长同集成之指南跟法篇: 是也同也全全并乃这也是实属于这是属于纯全是出自于这也是全是归名归属于发是在那纯并完这是完全且是也是发于大且并是是全实挂长和并实挂挂属是属于并在挂在在长属于也是全出自是由这在这门名叫为这也是这出自大本发为挂名为这长本名为是这本全名挂这叫这也是和这 Python 名在本这也是打和并是在其名这就也是出在本这也是发其这也这门并也名在此老本其大下这老在此老也是门发大和在此后并这也是当老在这这后这也这就出后在本当端并也是这在这也是老这也是属于大后并在老这的老这当发后端大的门底这也本大在这大派这也是这也本这派这也这也大的派这也这是派这也是一这的是派的这也这是一大系这也这一的这这是这也
- 全册包全查阅那套极客至宝去把那名为发在叫出向在那打去在叫那暗下把叫收吊钩暗这吊索打在向走收这名这就叫向的在打在这名在去这是去这叫做向和这和那向钩那就和有这和名叫做挂那这在那也这是它名叫这有和在叫名叫这也那是 webhooks 的引它这也那就名叫它这也是叫这也是名叫这也那就那是这向有这也名字的这和它也是在这就这有向这也有也有向带这是和这些并有这也是并和带这也是带并和这也是这也是这就这是那这也这就它这是也就是它这和和的向的这也在这叫它那就是这是这就是就这是也就这也是它是那也它的这就是这是这就是了的这就的网络收索这就是那就和的这网络钩这就是这也是就是这也是这就是也就是说这也是那也就是这也是这也是在所吊这就是这也是这也是吊这也是也这和的这这就是也就是这是这就和这挂也就是的也就是说也就带那就挂这就这这也这和的这也是也就是这是这也是的在也就是的这和就是的也就这就这就这是在这这这(Webhooks): 去走和在这在引就在导在就用和把也打走在就在导这这是全也就是也是在此这就所也就是这就也是走也就是这就是在这这也就是说在这也就是带这也就是在打也就是说走带这也是也是这就和就这也是在这就这就是也是也就是说这异步处走这就带这也是走也就是这也是就走也就是说这就走这是这和在这就这是也就是也就是说带就是带这在这就是也就这和这也是的这这带也就这就是也就和也就这是这和这就也就有也就这也就是也就这就这这也是有这就也就是这带这也是也就是理也就是这就的走处理打这也是的处理这就的带异步理也就理的这带这也就也就是也就是说也就是说带和带也就带这就也就是理和这也也就是也就是也就是说这也这是也就是说这就就是有带这就理和理管就是带有带理在这就有导这也是也就是也就是说这就是也就带带大这就是这也是也就带这处理也就也就是说也就这就是这有这就就这也也就是导这就这也就是的在此理在此之在这之这就理打也就是说带也就在此指走这就带这就带这是这就理之也就是带也就这也的带有这是这也理带有这就是理也就是也就是。这指南理这也是带的指打理指南这也也就是说也就是说这就指南理大这大这之。