V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
songray
V2EX  ›  程序员

分享最近解决的小众需求:如何在浏览器里检测代码文本是什么语言

  •  1
     
  •   songray ·
    Ray-D-Song · 10 小时 21 分钟前 · 3143 次点击

    仓库: https://github.com/ray-d-song/guesslang-js
    效果展示: https://ray-d-song.github.io/guesslang-js/

    最近我正在完成一个叫 EchoRSS 的阅读器项目,有一个我非常想要的功能,就是拦截订阅中的外链跳转(阅读全文、引用啥的),直接在当前页内显示。

    有一个问题是返回的 HTML 代码块失去了语言标注(或者原先在 pre 和 code 标签上就没有标注语言),这样没法用 shiki 或者 prism.js 之类的工具进行代码高亮。

    我找到了三个检测代码语言的方案:

    1. linguist

    这是一个部署在服务器上的 Ruby 项目,Github 用它来检测仓库的语言构成,如果你需要极高的准确度且可以在服务端运算的话,这是最优解。

    2. hljs

    highlight.js 是一个非常知名的网页代码高亮库,也是唯一一个提供自动代码检测的高亮库。
    原理很简单,就是枚举语言的关键词,用这些关键词去一个个匹配文本,最后看哪个的匹配度最高。

    hljs 有四个问题。

    • 对代码长度的要求很高,大多数语言至少要 300 个字符才能达到比较合格的准确度。
    • 检测语言的部分并不是单独的模块,而是跟 parser 、render 紧紧的耦合在一起,代码写的也非常命令式,很难提取有用的部分
    • 如果不提取检测模块,直接用 hljs 高亮,会丢失代码原有的一些格式(换行和缩进)
    • 需要进行大量的正则匹配,性能较差,又因为原因 2 ,没法放到 web worker 中运行。

    3. guesslang

    guesslang 是一个基于 tensorflow.js 的机器学习项目。
    Microsoft 在 2021 年用 tensorflow.js 将这个项目移植到 node.js 上,为 vscode 增加了自动语言检测的功能。

    一个越南小哥hieplpvip三年前又将这个项目移植到了浏览器上,不过也有三个问题:

    • 漏内存,疯狂漏内存...
    • 只支持 umd 格式,不支持 esm ,不支持 bundle
    • 同样又因为原因 2 ,不支持 web worker

    而且这位小哥已经不再维护这个项目,3 月份有个支持 esm 的 feat request 一直没有回复。

    所以我提取了 hljs 中的检测模块,又 fork guesslang-js 修复了上面那些问题,对比了一下两种方案,最终 guesslang 胜出,产物就是这个: https://github.com/ray-d-song/guesslang-js

    貌似叨太多了,也许未来会有人需要这个,所以 po 一下。

    如果有人了解 tensorflow.js 的话,希望可以推荐一些学习材料,我想进一步改为 web gpu 计算来提升效率。

    42 条回复    2024-11-22 17:52:46 +08:00
    musi
        1
    musi  
       10 小时 20 分钟前
    直接拿一个小语言模型判断就好了,感觉 1b 的就够了
    songray
        2
    songray  
    OP
       10 小时 18 分钟前
    @musi 不行,一是很难跑在浏览器里(大多数语言模型都是 pytorch 而不是 tf ),还有就是 1b 的模型不可能支持结构化输出,返回内容不稳定
    musi
        3
    musi  
       10 小时 17 分钟前
    @songray #2 第一点你去找支持跑在浏览器里的小模型,现在已经有了。
    第二点你并不需要结构化输出,你只需要提取关键字就行了
    songray
        4
    songray  
    OP
       10 小时 14 分钟前 via iPhone
    @musi 我只能说这是我花时间摸索出来的结论,真的可行的话你可以贴个 showcase 链接给我…
    xxx 可行这种话没啥意义。
    musi
        5
    musi  
       10 小时 10 分钟前
    @songray #4 看的出来你是真不想花时间搜索
    直接 google "run LLM in browser"直接就出来了 https://github.com/mlc-ai/web-llm
    你是真想别人把饭喂你嘴里才吃
    ukhack
        6
    ukhack  
       10 小时 6 分钟前
    前端取一段丢给后端,后端接个免费的大模型就行了,比如说智谱 flash 。
    打完收工
    songray
        7
    songray  
    OP
       10 小时 4 分钟前
    @musi 这就是我说的你压根没有花时间摸索就得出结论。
    我就算用 0.5b 的模型也要下几百兆到浏览器里... 然后每次再推理十几秒,这有啥用?
    musi
        8
    musi  
       10 小时 1 分钟前
    @songray #7 那你应该用下载模型耗时太长反驳我,而不是“很难跑在浏览器里”,你不说清楚我怎么知道你对时间敏不敏感,万一你对对一次的下载时间不敏感后面加上缓存了呢?
    感觉你沟通能力也不行
    songray
        9
    songray  
    OP
       10 小时 0 分钟前
    @musi 你但凡我 po 的内容呢?
    songray
        10
    songray  
    OP
       9 小时 59 分钟前   ❤️ 8
    这交流环境也太恶劣了...
    musi
        11
    musi  
       9 小时 58 分钟前
    @songray 你 po 的内容有说明你的产品运行在什么样的网络环境和设备环境吗?只能知道是跑在 web 浏览器上的,web-llm 是不能跑在浏览器上吗?
    musi
        12
    musi  
       9 小时 57 分钟前
    笑死,自己没说清楚别人给你找了解决方案还说交流环境恶劣。。。
    vvhy
        13
    vvhy  
       9 小时 56 分钟前
    可以拿 polyglot 测试一下,哈哈
    songray
        14
    songray  
    OP
       9 小时 55 分钟前 via iPhone
    @ukhack 确实可以,实际上我也试了 cloudflare ai ,就是大模型返回实在是太慢了…
    songray
        15
    songray  
    OP
       9 小时 54 分钟前
    @vvhy 没搜到,可以贴个链接给我吗。
    我真的很需要高性能方案 = =
    LinYa
        16
    LinYa  
       9 小时 52 分钟前
    我觉得这个挺好的,有时候把网页扒下来转换成 md ,会丢失对代码块语言的标记,导致我得手动添加。
    vvhy
        17
    vvhy  
       9 小时 51 分钟前
    @songray 不是方案,是可以解释为多种语言的代码 https://en.wikipedia.org/wiki/Polyglot_(computing)
    skallz
        18
    skallz  
       9 小时 30 分钟前
    @songray 大部分模型是可以转化到 onnx ,onnx 在浏览器运行也有成熟的 wasm 方案,好处是各环境能保持一致,比 tf 好处理,不过 onnx 的 wasm 版本目前社区只支持 cpu
    june4
        19
    june4  
       9 小时 15 分钟前
    感觉代码高亮这功能不是那么有必要上这么重量级的东西在浏览器里,本地应用的话还行。

    如果是我,我可能会搞个粗糙的高亮方案,集合 top 10 种语言的大部分重要关键字,和字符串/数字/注释格式,这几样东西才是最需要高亮的东西,搞个通用又朴素的高亮应付所有代码。毕竟高亮文本只是个辅助视觉提示,不需要那么精确和花骚。这套轻量方案几 K 代码就搞定了,而上模型又慢又要 M 级内存打底。
    dhb233
        20
    dhb233  
       9 小时 1 分钟前
    说的是编程语言吧,感觉随便写写就能区分主流的语言,哪用大模型
    zhmouV2
        21
    zhmouV2  
       8 小时 55 分钟前   ❤️ 6
    拿 llm 当解决手段疑似有点幽默了,属实是大炮打蚊子,感觉是不是对 1b 参数量模型有啥误解? stable diffusion v1.5 的参数量差不多也就这个数。如果这也算解决方案,我找 1000 个印度外包去人工识别好不好。。。

    正经方法不外乎提取关键字做匹配或者依赖一个小的文本分类模型做检测,或者二者结合。就跟二维码定位差不多,要么依赖 cv 传统算法提取线段/点/矩形,要么搞个小的 mobilenet 去做 detection 。
    ResidualSoils
        22
    ResidualSoils  
       8 小时 49 分钟前
    我觉得楼主的分享很不错
    songray
        23
    songray  
    OP
       8 小时 48 分钟前
    @zhmouV2 是的,我觉得现在很多人形成路径依赖了... 一言不合大模型。
    大多数任务依赖传统 cv 就可以了,大模型的速度和大小在很多场景下都是不可接受的。
    songray
        24
    songray  
    OP
       8 小时 45 分钟前
    @june4 guesslang 打包出来是 1000k ,zip 之后 200k ,还算可以接受的大小
    june4
        25
    june4  
       8 小时 32 分钟前
    @songray 确实 200K 的话也不算太过份,你做的是 rss reader 吧,很可能整个 reader 的前端代码 zip 后也没有 200K ,这个小功能就超过整个 app 了。
    yggd
        26
    yggd  
       8 小时 26 分钟前   ❤️ 1
    magika 怎么样,模型大小也是 1M 左右,主要就是检测文件类型的
    songray
        27
    songray  
    OP
       8 小时 21 分钟前
    @yggd 好东西,我试一下!
    kebyn
        28
    kebyn  
       7 小时 42 分钟前   ❤️ 2
    可以看一下 vscode 的解决方案的
    @vscode/vscode-languagedetection
    hafuhafu
        29
    hafuhafu  
       7 小时 39 分钟前
    长见识了,原来 VSC 的自动语言模式是用机器学习实现的,怪不得偶尔结果是错的
    Alliot
        30
    Alliot  
       7 小时 34 分钟前
    百度有语言检测 API 参考 openai-translator
    weiwenhao
        31
    weiwenhao  
       4 小时 29 分钟前
    @yggd 收藏了,看起来很高级
    Ocean810975
        32
    Ocean810975  
       3 小时 28 分钟前
    好文,mark 了,要是用大模型的人少说两句就更好了……
    zoharSoul
        33
    zoharSoul  
       2 小时 54 分钟前
    用大模型也太幽默了
    liuzhaowei55
        34
    liuzhaowei55  
       2 小时 43 分钟前 via Android
    不错,最近关注 Monaco editor ,也很需要语言自动判断
    NoOneNoBody
        35
    NoOneNoBody  
       2 小时 38 分钟前
    @songray #10
    @musi #11
    两位正经讨论技术,跑偏了,跑偏了,没必要变为讨论立场和态度,回到可行性上面吧
    ooTwToo
        36
    ooTwToo  
       2 小时 25 分钟前
    magika
    lllllliu
        37
    lllllliu  
       2 小时 20 分钟前   ❤️ 1
    (随便说的)本质上是一个分类问题,用传统机器学习也是可以做的应该~ 各个语言的特征应该是都比较明显的,最好理解的算法应该是决策树了~
    zhangkui
        38
    zhangkui  
       2 小时 11 分钟前
    @songray #10 有用配上我的浏览器插件直接起飞。。。牛逼 op
    Plumbiu
        39
    Plumbiu  
       1 小时 38 分钟前
    代码高亮的成本太高了,就算有一些小模型,shiki 或者 prism.js 的体积都已经很大了,建议不搞
    Plumbiu
        40
    Plumbiu  
       1 小时 37 分钟前
    @Plumbiu 或者转移到服务端,可以减少一下客户端体积
    mahaoqu
        41
    mahaoqu  
       1 小时 22 分钟前
    Java 字符串里写 SQL 的能匹配上两种语言,还是只有其中一种?
    mightybruce
        42
    mightybruce  
       1 小时 13 分钟前
    觉得用大模型来检测,似乎是一种费力不讨好的方案。
    毕竟一个语言要高亮的话也就那么一些关键字和语法,你做好匹配不就行了。

    我用的很多专业的代码编辑器也就是这么做的而已。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2948 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 11:05 · PVG 19:05 · LAX 03:05 · JFK 06:05
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.