大模型时代,还需要跨端framework吗?

avatar
作者
猴君
阅读量:3

跨端

在我近十年的大前端从业经验中,有一半是在和flutter/rn打交道。虽然,flutter和rn官方和社区已经在非常努力的优化、填坑了,但是这两者的坑还是远远高于原生开发。
但是,在锁表的大周期下,华为带着鸿蒙来了,给水深火热的客户端开发带来了新的降温神器:乍一看,鸿蒙是带来了更多的开发需求。但时间拉长,在成本的驱使下,大量中小厂的客户端要不然更快的被完整放弃,要不然科技以套壳为本,客户端最终会落到更加边缘的窘境。当然,跨端很可能会是救客户端于水火的最后稻草,或者跨端真的还需要吗?

为什么要跨端

跨端能带来什么?无非是几个优点:开发效率、多端一致性和动态化(部分多端才有),当然对于大厂来说,跨端还能带来前所未有的可控性,毕竟整个framework层都是打到app里的,可以自主修改的,统一的代码。
前两者都是由单点开发,多点运行带来的。动态化和可控性则是不同framework各有千秋,即便没有跨端,也有很多办法达成(只不过,因为跨端有前两个好处,各家做动态化的时候通常会魔改rn)。
跨端的问题是什么?不同方案问题不尽一致,但是跑不出性能、与原生交互能力、系统特性追随速度等核心痛点。
在没有大模型之前,跨端的评价大概率是正向的,毕竟又贵又慢的客户端是生产成本上极为显眼的组成项。

怎么跨端

跨端无非是几个层面的adapter:

  • 语言:首先是开发时统一到一个中间语言上,无非是kotlin、js、dart还是别的。运行时的分野比较大,传统的走集成一个vm(或者调用系统的),KMM则是直接在编译时编译成对应平台原生代码。对于KMM来说,需要用Expectations与Actualizations来抹平语言层面的差异。这是一个专家枚举差异的过程。
  • 框架:通常也是有一个中间层定义,module、channel、jsbridge、expectations都是一样的逻辑。对原生依赖越小,这部分的风险和成本都越小,但是都少不了。这也是一个专家枚举差异的过程。
  • UI:无非是自己画和用系统画,自己画集成困难一致性好,用系统一致性差集成好,但都有明显短板。性能上的劣势也多由此带来。这里不太是枚举差异,而是重新定义dsl。

新办法

从上面的分析来说,跨端永远是用用户体验换开发效率的一个妥协选择。随着设备性能提升和框架能力增强(不过最近感觉每一个跨端框架都在雕花而不是想办法解决最要紧的问题),用户体验的损失会越来越小。但是,用户体验永远是有损失的。那么,有什么别的办法吗?统一架构+大模型翻译可能是一个方向。(我曾经有一段时间对llvm翻译多端跃跃欲试,最终因为ast实在太复杂放弃了)
首先,要统一多端的架构,不论是基础的in-house能力还是上层的业务设计逻辑都需要思路一致。
基础能力需要保证层级、可见性、接口风格和参数尽可能一致。此时,大模型翻译需要的特殊上下文是最少的,prompt也不需要特殊说明什么,让模型自己去做语义翻译就行了。可以认为用不同语言构建一个相同的基础能力语义化DSL。
业务设计就更重要一些,毕竟底层方法调用只是简单的fix build,而业务是真的要让翻译完的逻辑完全一致的。之前写过的一个文章里也主要是絮絮叨叨的说这个问题。
架构搞完之后,有一个重要的SOP:翻译后的代码,仅允许修改以保证运行,不能人工迭代。因为,要保证迭代时一直能做到生成+fix build,一旦放开人工修改的口子,后续的分叉会来的非常快,迅速打破模型上下文的限制,让翻译极为困难。

一次尝试

之所以敢说这个新办法,是因为我真的尝试了一次。
功能相对简单:网页内容的分享,从flutter迁回原生实现。有7种分享入口,4个jsbridge。但涉及到了UI、逻辑和框架差异,能很好的验证我的想法。

UI

翻译水平并不好,原因有几个:

  • UI比较简单,懒得优化prompt,优化prompt的时间足够我自己fix了
  • 老代码业务和UI耦合非常严重,模型很容易lost
  • 没充值ChatGPT,只是嫖了公司的openai api,缺乏ChatGPT产品化的各种优化
    按之前的经验,好好调一下prompt,用figmaToCode生成的无业务逻辑的纯UI代码,翻译可以做到基本可用。组件和不知道的方法,通过prompt能自动加上fixme,方便快速修复。不过ChatGPT写snapkit edge加不全的毛病还是一如既往。

逻辑

逻辑部分可以分为几个部分:核心业务逻辑、数据层逻辑、对外交互。

核心业务逻辑

使用原教旨(但手写)的状态机来表达。先写的kotlin,用enum表达状态,每个状态有moveIn和moveOut两个可以复写的方法。核心业务逻辑由state流转表达。
这部分翻译起来非常快,正确率也很好。但swift的enum并不支持复写方法,生成后的代码有大量的switch-case,只能手动将结构改成enum->concrete operator的映射关系。这种简单跨模式的翻译是需要给出few shot example的。

数据层逻辑

这里的数据层其实很简单,主要是解析jsbridge的数据和网络请求,并没有什么了不得的数据层逻辑。
这部分需要稍微在prompt里面说明一下具体的库。因为安卓有livedata、retrofit、rxjava、gson,swift则选择了alamofire、rxswift、rxalamofire、swiftjson,告诉模型用什么库能极大的降低修改成本。

对外交互

一个是分享接口绑定,另一个是事件绑定。
分享接口由于是现成接口,并没有用到翻译,一行代码自己写的。
事件绑定也是需要说明使用rxgesture,不得不吐槽一下iOS倒霉的事件绑定方式。这里的翻译都漏掉了filter掉首个事件,需要特殊prompt。

结论

最大的问题还是出现在UI上,而UI的复原是对平台知识要求最高的部分。还是期待有人用langchain的figma document做一个完备的方案(为啥这个api在docs上找不到了)。
另一个问题是swift/oc这种奇异且不稳定的语法,带来了很多fix build的工作,而且xcode实在难用。如果用idea全家桶再买上copilot,体验能提升一个量级。
还有一个小点是rx的线程模型和livedata不一样,需要加到prompt里面。

这个方案还是需要双端都略懂的开发结对工作。整体双端知识的要求很低,有个半年工作经验就差不多了。开发效率和一致性介于需要native module的rn和纯flutter之间,用户体验是可达到的最高。人员吃紧的团队内是值得推广的。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!