DoKit:一机多控WebView无侵入注入JS|滴滴开源

将滴滴技术设为“星标⭐️”

第一时间收到文章更新

导读

自2018年正式对外开源以来,DoKit经历了五年的打磨,已经发展成一个相对完整的生态,支持六大平台(Android、iOS、Web、小程序、Flutter和PC),是滴滴开源委员会的精品孵化项目。在外部被众多头部企业广泛使用并获得了良好的口碑。

在滴滴内部,DoKit已经在所有业务线和App中落地使用,基本覆盖所有日常开发和测试场景,提升了研发和质量同学的日常工作效率。但是随着滴滴内部跨端研发方案的普及,在显著提升研发效率的同时,也给质量团队带来了较大压力。因此,DoKit作为跨端研发方案的孪生兄弟,在2023年将继续聚焦测试效率领域,如UI自动化测试、一机多控等技术。同时,我们也将一机多控研发过程中遇到的技术难点和解决方案分享给开发者们。

本篇文章分为:

1.一机多控遇到的两大问题

2.有哪些常规JS注入方式?

  • 使用loadUrl注入

  • 使用evaluateJavascript注入

  • 修改html插入<script>标签注入

3.为什么需要首行执行?

  • 失败的经历

  • 需要首行之行

  • html插入<script>标签注入

4.如何实现HTML插入<script>标签注入?

  • 为什么通过插入<script>标签能够实现首行执行?

  • 如何拦截HTML文件加载?

  • 如何在HTML文件中插入<script>标签?

5.如何实现代码无侵入?

  • 无侵入设置WebViewClientProxy

  • 插入代码的时机

  • 设置WebViewClientProxy

  • 兼容问题处理

6.总结

在移动端开发过程中,开发者经常会遇到三个问题:

1、开发过程中需要临时开发很多便于调试和测试的开发工具;

2、开发工具入口众多,经常找不到想要的功能在哪;

3、设计同学在UI验收时,需要繁琐操作步骤后才能看清UI是否符合设计稿要求……

为了解决日常困扰大家的这三个问题,DoKit团队开发了30多个基础研发效率的工具(包含很多测试和视觉效率工具),并全部收拢在了一个入口中,所有工具功能都清晰可见、便于寻找。同时,为了解决日常开发过程中工具入口分散杂乱、工具开发成本过高等问题,DoKit还开发了高度可定制化能力,集成业务强相关的自定义扩展工具等,希望做好广大开发者在移动端的研发效率工具。

1. 一机多控遇到的两大问题

DoKit一机多控,简单来说是可以通过操作一部手机,同时控制多部手机同步执行操作的功能,旨在提升质量团队的测试效率,尤其是在多设备兼容性测试方面。在过去一年里我们对它进行了持续的研发和改进,功能已经比较完善和稳定。在分别完成了原生侧的一机多控功能和H5一机多控功能后,发现使用H5一机多控功能需要在测试环境发布H5页面时引入dokit-for-web.js文件,才能拥有一机多控功能。

虽然在原生侧,一机多控同样也是通过引入DoKit依赖包进行编译并初始化的,但是当App业务流程中存在H5页面时,如果不能同时开启原生和H5的一机多控功能,测试流程就会因为遇到H5页面而使一机多控控制流程中断从而导致无法正常同步操作。

9b0fd31e919e49e21c037d312598979b.png

(DoKit一机多控演示截图)

要让H5支持一机多控其实并不难,只需要在H5代码中结成dokit-for-web.js即可,但是H5一机多控一般只允许在测试环境下运行,不会把一机多控代码带到线上正式环境运行。

而原生App在Debug包中,可以随时通过开关切换不同运行环境(测试/正式环境),这会使得当App切到正式环境后,H5一机多控功能就不可用了。

为了保证顺畅的用户体验,使H5一机多控可以同时在测试和正式环境下运行,需要让H5一机多控可以和原生侧一样可以通过同一个环境切换开关来控制。但是,Web前端研发体系和客户端存在差异,虽然也有测试环境部署服务,但一键切换H5到测试环境存在较多困难,如H5页面众多且分散、团队协调成本高等。

因此,通过客户端来实现dokit-for-web.js代码的注入就变成了较为理想的选择,既能解决环境同步切换的问题,也能解决H5正式环境服务不能够集成一机多控代码的问题。

我们通过在WebView中注入JavaScript代码的不断探索和尝试,沉淀出了一套符合DoKit设计理念的实现方式来完成JavaScript代码的注入。

下面我们一起来看一下DoKit在Android端WebView中注入JavaScript的探索实践过程。

2. 有哪些常规JS注入方式?

搜索查询资料,常用的注入方案是在WebView中设置WebViewClient,通过WebViewClient回调在onPageFinished()中,最早可以再onPageStart()之后,通过loadUrl()或evaluateJavascript() 去加载需要注入的JS代码,或者直接修改html文件插入<script>标签来注入JS代码。

使用loadUrl注入

使用WebView提供的loadUrl注入JS代码,这个API是Android系统最早支持的,在Android各版本中均可使用,需要打开WebView的js运行支持开关。

示例代码:

//打开js运行支持开关
webView.getSettings().setJavaScriptEnabled(true);


public void onPageFinished(WebView webView, String url) {
    webView.loadUrl("javascript:javacalljs()"); 
    supper.onPageFinished(view, url);
}

使用evaluateJavascript注入

使用WebView的evaluateJavascript注入JS代码,需要注意这个API在Android 4.4及以上版本可用。evaluateJavascript 注入代码后可以直接返回执行结果,与loadUrl需要通过复杂的回调方式才能拿到结果相比,在需要返回值时非常方便。

示例代码:

public void onPageFinished(WebView webView, String url) {
    //在android4.4及以上使用
    webView.evaluateJavascript("javacalljs()", new ValueCallback<String>  () {
        @Override
        public void onReceiveValue(String value) {
            //todo 执行js方法的返回结果
        }
    })
}

修改html插入<script>标签注入

修改html插入<script>标签注入,是一种纯前端的JS注入方式,相当于直接编写代码加入一段JS代码。通常比较多的使用在一些恶意通过网络拦截修改注入代码的场景中。这种方式不受浏览器Api限制,只要能拦截到网络通信即可。

正常的html文件如下:

<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <script type="text/javascript" src="https://dokit.cn/js/h.js/></script>
</head>
<body>
    <div class="main">...</div>
    <div class="pan">....</div>
    <script type="text/javascript" src="https://dokit.cn/js/a.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/b.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/c.js/"/> <script>
</body>
</html>

修改后的html文件如下:

<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <script type="text/javascript" src="https://dokit.cn/js/h.js/></script>
</head>
<body>
    <div class="main">...</div>
    <div class="pan">....</div>
    <script type="text/javascript" src="https://dokit.cn/js/a.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/b.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/c.js/"/> <script>
    //以下是注入代码
    <script>javacalljs()</script>
</body>
</html>

3. 为什么需要首行执行?

失败的经历

开始我们使用的是loadUrl和evaluateJavascript来注入一机多控的JS代码,在测试页面中运行很快测试通过,但迁移到实际业务场景中很多问题就暴露出来了。经过排查后,其中就发现网络请求并没有全部拦截到,部分请求数据主机不能同步给从机导致从机无法加载数据正常显示页面,或者部分事件拦截失败。

最后确定是因为测试页面过于简单,未考虑到实际使用的场景,业务方通常会使用各种框架,这些框架通常会做一些保证自己首先执行的操作。会导致一机多控的hook失败,一方面需要对业务使用到的框架做兼容适配,另一方面框架中往往会做一些操作影响hook点,所以必须要让一机多控的代码首先执行,才能提前hook到关键点。

需要首行执行

如果不能保证注入代码首先执行,导致部分注入需要的hook点不能正常工作。比如网络请求的拦截不能在最早时间完成,将造成部分请求数据没有被拦截到,无法实现主机和从机的数据同步。页面渲染后才对页面渲染进行拦截,将无法hook到页面的部分用户操作事件。

通过loadUrl和evaluateJavascript来注入一机多控的JS代码,使用的是WebView提供的能力,用这些接口来注入代码,没有一个准确的注入时机既能保证注入代码成功运行,也能在其他JS代码执行前执行。

html插入<script>标签注入

经过与前端同学的沟通,要实现首行执行注入代码,需要通过前端的方式来实现注入,WebView并没有能满足业务需求的方式,除非使用自己魔改的浏览器引擎,提供这样的能力。

使用插入<script>标签能够保证首行运行的基础,WebView设计采用的是单线程模型。即在不使用多线程API时网页的加载和JS执行均为顺序执行。

那么只要遵循html的设计规则就能够准确的控制插入的<script>标签在什么时间执行。

4. 如何实现HTML插入<script>标签注入

为什么能实现首行执行?

除前面提到的WebView采用的单线程模型外,html加载页面有一个固定的规则。html 加载时先加载<head>标签,然后加载<body>标签。

如果在<head>标签里面碰到<script>标签会判断是引入外部JS文件还是JS代码,如果是文件会开始下载外部文件,如果是代码则html页面加载会暂停,此时javascript引擎开始执行代码,等JS代码执行完了继续加载其他标签中内容。等待<head>标签里面的内容都加载完之后,才开始加载<body>标签的内容。

如果在<body>标签里面遇到<script>标签与<head>标签处理一致。会判断引入的是外部JS文件还是JS代码。如果是外部文件就开始下载外部文件,如果是代码又会暂停加载页面,转而让Javascript引擎开始执行代码,等JS代码执行完毕之后才会继续加载页面。

所以插入的<script>标签应该插入在<head>标签中,并且应该插入在<head>标签的最前面,而且必须是插入的代码而非JS文件。

示例代码:

<html>
<head>
    //以下是注入代码,必须放在head的起始位置
    <script>javacalljs()</script>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit">
    <script type="text/javascript" src="https://dokit.cn/js/h.js/></script>
</head>
<body>
    <div class="main">...</div>
    <div class="pan">....</div>
    <script type="text/javascript" src="https://dokit.cn/js/a.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/b.js/"/> <script>
    <script type="text/javascript" src="https://dokit.cn/js/c.js/"/> <script>
    //以下是注入代码,在这里的不会被首先执行
    <script>javacalljs()</script>
</body>
</html>

如何拦截HTML文件加载?

查看WebView及WebViewClient代码,发现WebView发出的网络请求是可以被拦截的,通过 WebViewClient的shouldOverrideUrlLoading() 方法就能拦截到Webview的全部网络请求,其中包含html文件的加载请求。

通过webRequest.isForMainFrame()识别其中用于html文件的请求,对于更低版本的url可以判断文件后缀是否为.html来判断。拦截到请求后可以直接使用返回的WebResourceResponse,或者通过自己网络库,比如OkHttp请求加载到html文件。需要注意应阻塞当前线程的方式去请求html文件。

示例代码:

// 拦截网络请求的回调,在android 21以后被废弃
public WebResourceResponse shouldInterceptRequest(WebView view, String request) {
    if(DoKitUtils.isHtmlRequest(request)){
      //todo 拦截代理请求html并完成JS代码注入
      return DoKitUtils.hookWebViewHtmlRequest(request);
    }
    return supper.shouldInterceptRequest(view, request)
}

示例代码:

// 拦截网络请求的回调,在android 21新增加
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    if(request.isForMainFrame()){
      //todo 拦截代理请求html并完成JS代码注入
      return DoKitUtils.hookWebViewHtmlRequest(request);
    }
    return supper.shouldInterceptRequest(view, request)
}

如何在HTML文件中插入<script>标签?

解析HTML文本

通过WebViewClient提供的回调shouldInterceptRequest()可以拦截到html文件的网络请求,并获取到了文件,需要解析html文件才能将注入的<script>标签插入到想要插入的位置。

如果自己使用xml解析库来解析html文件比较复杂,不能直接搜索到想要的标签并进行修改,DoKit中使用Jsoup来解析html文本。

示例代码:

pulic String handleWebViewHtml(String html){
    Document document = Jsoup.parse(html);
    //todo insert dokit <script>
    return document.toString();
}

插入<script>标签

获取到html文件并通过html解析库Jsoup解析html文件,然后就需要找到html中的<head>标签,并在标签起始位置插入一机多控需要注入的<script>标签代码。最后构造一个WebResourceResponse对象return给shouldInterceptRequest()回调。

示例代码:

/**
 * 拦截html请求并注入JS代码
 */
public static WebResourceResponse hookWebViewHtmlRequest(WebResourceRequest request){
    Response response = requestWebViewHtml(request);
    if(response !=null){
        String html = injectScript(toHtml(response));
        return WebResourceResponse("text/html",
            response.header("content-encoding", "utf-8"),
            ConvertUtils.string2InputStream(html, "utf-8")
    }
    return null;
}


/**
 * 插入script标签
 */
private static String injectScript(String html){
    //读取本地js hook 代码
    String dokitScript = ResourceUtils.readAssets2String("dokit/dokit_script.html")
    Document doc = Jsoup.parse(html)
    doc.outputSettings().prettyPrint(true)
    val elements = doc.getElementsByTag("head")
    if (elements.size > 0) {
        elements[0].prepend(dokitScript)
    }
    return doc.toString()
}

5. 如何实现代码无侵入?

一开始觉得设置WebViewClient是一个很容易的事情,就在创建好WebView之后调用setWebViewClient()设置WebViewClientProxy即可实现。在DoKit项目中已经在很多功能中使用到字节码修改。并且对于WebView的字节码修改已经存在参考。实际操作时发现对于实现一个完整的无侵入字节码修改仍有一些地方需要注意。

无侵入设置WebViewClientProxy

首先我们需要对代码无侵入(DoKit功能的一贯风格,代码无侵入,随时可以用也可以移除),就不能够让接入方在创建好Weview后去主动设置WebViewClientProxy。我们选择在DoKit中使用场景比较多的成熟技术,通过ASM在tranform的时候修改字节码来实现给WebView设置WebViewClientProxy。

修改字节码来实现设置WebViewClientProxy需要使用到DoKit插件,并保证插件的开关为开启状态。

插入代码的时机

第一个插入时机

第一个插入时机是WebViewClient创建时,在调用构造函数时通过ASM插入代码设置WebViewClient。但是因为WebView是系统类,不在编译产物中,不是自己写的类,无法在构造函数中注入代码设置WebViewClient。而且通常业务方都会在WebView中设置自己的WebViewClient,即使在构造函数或创建WebView的时候设置了WebViewClient,也会存在被覆盖的风险导致设置失败。在构造函数中设置WebViewClient不能满足要求。

示例代码:

public class WebView{
  //构造函数
  public WebView(Context contex){
    setWebViewClient(new WebViewClientProxy())
  }
}

第二个插入时机

第二个插入时机是在执行setWebViewClient()时通过ASM修改setWebViewClient函数,注入一段代码来设置WebViewClientProxy。同样因为WebView是系统类,不在编译产物中,不是自己写的类,通过修改字节码的方式无法修改。而且因为无法保证所有的WebView都会设置WebViewClient,所以无法保证能够成功插入。如果某个WebView不设置自己的WebViewClient 将导致WebViewClientProxy的设置失败,所以即使能够修改WebView也不能保证覆盖全部场景。

示例代码:

public void setWebViewClient(WebViewClient webViewClient){
  WebViewClientProxy = new WebViewClientProxy(webViewClient);
  super.setWebViewClient(WebViewClientProxy);
}

第三个插入时机

第三个插入时机是在调用WebView的loadUrl()方法加载页面或者JS代码的时候。loadUrl前应该是Webview准备就绪后,如果业务代码上需要设置WebViewClient那么应该是在loadUrl前已经设置好WebViewClient,在设置WebViewClientProxy的时候可以获取到已经设置好的WebViewClient实现代理不影响业务功能。loadUrl也是我们设置WebViewClientProxy的最后机会,同时也是加载页面必须调用的方法。

但是在这里同样面临一个问题 不能直接修改WeView的loadUrl方法字节码插入设置WebViewClientProxy逻辑。

既然不能直接修改WebView的loadUrl方法那么只能再全部调用loadUrl的地方进行字节码修改。需要扫描全部代码行,使用这种方式在修改字节码时效率相对较低。如果接入方可以使用自定义的WebView重写loadUrl方法,能够避免扫描全部带来比较大的字节码处理耗时。

示例代码:

klass.methods.forEach { method ->
    method.instructions?.iterator()?.asIterable()
        ?.filterIsInstance(MethodInsnNode::class.java)?.filter {
            if ("loadUrl".equals(it.name)) {
                "hook loadUrl() all ${className} ^${superName}^${it.owner} :: ${it.name} , ${it.desc} ,${it.opcode}".println()
            }
            (it.opcode == Opcodes.INVOKEVIRTUAL || it.opcode == Opcodes.INVOKESPECIAL)
                && it.name == "loadUrl"
                && (it.desc == "(Ljava/lang/String;)V" || it.desc == "(Ljava/lang/String;Ljava/util/Map;)V")
                && isWebViewOwnerNameMatched(it.owner)
        }?.forEach {
            "${context.projectDir.lastPath()}->hook WebView#loadurl method  succeed in :  ${className}_${method.name}_${method.desc} | ${it.owner}".println()
            if (it.desc == "(Ljava/lang/String;)V") {
                method.instructions.insertBefore(it, createWebViewInsnList())
            } else {
                method.instructions.insertBefore(it, createWebViewInsnList(method))
            }
        }
}

示例代码:

/**
 * 创建webView函数指令集
 * 参考:https://www.jianshu.com/p/7d623f441bed
 */
private fun createWebViewInsnList(): InsnList {
    return with(InsnList()) {
        //复制栈顶的2个指令 指令集变为 比如 aload 2 aload0 / aload 2 aload0
        add(InsnNode(Opcodes.DUP2))
        //抛出最上面的指令 指令集变为 aload 2 aload0 / aload 2  其中 aload 2即为我们所需要的对象
        add(InsnNode(Opcodes.POP))
        add(
            MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "com/didichuxing/doraemonkit/aop/WebViewHook",
                "inject",
                "(Ljava/lang/Object;)V",
                false
            )
        )
        add(
            MethodInsnNode(
                Opcodes.INVOKESTATIC,
                "com/didichuxing/doraemonkit/aop/WebViewHook",
                "getSafeUrl",
                "(Ljava/lang/String;)Ljava/lang/String;",
                false
            )
        )
        this
    }
}

设置WebViewClientProxy

通过上面的代码实现了对全部WebView调用loadUrl的hook,拦截后具体逻辑采用正常java代码编写。判断传入的对象是否为WeView(在插入时已经判断方法名称为loadUrl,但是不能确定一定是WebView)。然后需要开始JS支持开关等设置,保证插入JS代码能够被执行。

示例代码:

private static void injectNormal(Object webView) {
        if (webView instanceof WebView) {
//            webView.setWebContentsDebuggingEnabled(true);
            if (!(WebViewCompat.getWebViewClient(webView) instanceof DoKitWebViewClient)) {
                WebSettings settings = webView.getSettings();
                settings.setJavaScriptEnabled(true);
                settings.setDatabaseEnabled(true);
                settings.setDomStorageEnabled(true);
                settings.setAllowUniversalAccessFromFileURLs(true);
                webView.addJavascriptInterface(new DoKitJSI(), "dokitJsi");
                webView.setWebViewClient(new DoKitWebViewClient(WebViewCompat.getWebViewClient(webView), settings.getUserAgentString()));
            }

兼容问题处理

兼容android不同版本

WebViewCompat.getWebViewClient(webView) 存在版本兼容问题,仅支持26及以上版本。

兼容到21-25版本需要hook WebView 的setWebViewClient方法再设置WebViewClient的时候将WebViewClient对象存储起来再需要使用的时候设置到WebViewClientProxy中。

支持不同的WebView实现

支持X5 Webview在设置WebViewClientProxy的时候如果检测到传入的对象为其他浏览器引擎,替换WebViewClientProxy为对应的代理实现即可。

示例代码:

if (X5WebViewUtil.INSTANCE.hasImpX5WebViewLib()) {
    if (webView instanceof WebView) {
        injectNormal((WebView) webView);
    } else if (webView instanceof com.tencent.smtt.sdk.WebView) {
        injectX5((com.tencent.smtt.sdk.WebView) webView);
    }
} else {
    if (webView instanceof WebView) {
        injectNormal((WebView) webView);
    }
}

6. 总结

我们通过拦截HTML文件下载在HTML的<head>标签起始位置插入包含JS代码的<script>标签,实现了在Android端无侵入的JS代码注入,在DoKit一机多控功能中稳定地支持了H5页面的一机多控功能运行。

整体来看DoKit所使用的方式不是效率最高,也不是代码修改最小的,但确实是适合DoKit一机多控场景需求的。希望通过我们在WebView中注入JS代码这个技术点上的尝试,对有需求的小伙伴有所帮助。

欢迎大家关注【DoKit官方交流群】,有任何使用上的问题都可以在群里反馈给我们,同时也欢迎大家通过DoKit官方代码仓库给我们提issue和PR。

2c7013f5163a47ee0049d75b82476f97.png

 QQ扫码加入DoKit官方交流群

相关推荐

滴滴多篇论文入选 ICML2026,值得一读!

与此同时,在一个滴滴大规模网约车应用场景中的实验进一步显示,本文方法相较于现有基线方法取得了显著提升,其效果可与使用显著更多 RCT 数据训练得到的模型相仿。广泛的实验表明,当前最先进的智能体在这些任务中表现远不如人类,且无法通过简单的扩大规模来提升,其失败的主要原因在于上下文锁定(in-context locking)和基础能力的缺失。通过将记忆构建为一个不断进化的生态系统,DMS在无需任何额外训练的情况下,显著提升了MLLM智能体的任务成功率、执行稳定性与效率。

DiDi_Tech的博客 406

多轮 Agent 场景下,滴滴的 EAGLE-3 训推加速实践

在 64K / 128K 级别的长序列训练中,显存的主要消耗来自“中间状态”,包括 attention 的中间激活(如 softmax 相关中间量、Q/K/V 张量等),以及反向传播必须保留的激活,包括 EAGLE-3 特有的多层特征参与训练所带来的额外激活存储,与 TTT 多步展开引入的 k 轮中间态堆叠。为缓解这一问题,EAGLE-3 在训练阶段引入 TTT 机制(见图 2),按照真实 decode 流程展开:先生成一步预测,再将该预测作为下一步输入,多步递进,从模拟真实推理过程。

DiDi_Tech的博客 666

滴滴的工程师们,都在读什么书?

它兼具技术、商业与历史视角,能帮读者建立宏大产业格局,提升认知高度。从 LoRA/QLoRA 轻量微调、RAG,到服务化部署、监控迭代,每一个技术要点都搭配可视化图表,易懂、易落地、可复用。尤其适配支付、金融等高并发场景的工程化落地,轻松打通大模型「从理解到应用」的第一步,是技术岗从入门到实战的高效进阶手册。它不只教你调 API,更聚焦如何构建健壮、可扩展的 AI 生产系统,是技术人转型 AI 工程师的通关秘籍。直指大模型与自动驾驶的伦理风险,提供长期 AI 安全的底层思路,兼具技术深度与人文思考。

DiDi_Tech的博客 398

一文读懂滴滴OpenClaw专属打车Skill

在复杂场景中,AI 不再只是执行工具调用,而是开始具备一定的推理能力,例如:能够根据“22:20 落地”推算实际用车时间、主动补全你缺失的起点信息,并对整体行程进行合理规划。当你说出“帮我叫车”时,OpenClaw 会识别触发条件,并加载 didi-ride-skill 的相关内容,使 AI 能够懂得并调度滴滴的出行能力。根本的问题在于:IM 通道的异步特性本身就引入了额外复杂度,包括轮询等待、消息乱序处理、以及“如何判断回复结束”等工程问题,而这些都与测试框架本身目标无关,但会显著增加维护成本。

DiDi_Tech的博客 1003

滴滴多篇成果入选CVPR 2026,产学研协同创新结硕果

该论文首先构建了FaceCoT,首个面向人脸反欺诈的、百万级视觉问答式思维链数据集,通过模拟人类思维过程设计六阶段层级式思维链结构,首次引入结构化、可解释的推理标注机制,不仅给出真假标签,更明确呈现“攻击成立的依据与逻辑路径”,为模型学习“为什么是欺诈”提供清晰且高质量的监督信号。通过设计统一的视觉-语言-动作模型的框架,该方案解决了以往工作中推理速度慢与文本轨迹不稳定的问题,并且将多模态信息在隐空间中进行了统一,在保持推理能力的同时提高了模型的效率。图: GeoPredict框架示意图。

DiDi_Tech的博客 395

滴滴邀你一起,迈入智能工作美好协同

发送简历至HR邮箱,开启快速投递通道。

DiDi_Tech的博客 423

滴滴云平台事业群热招中!“云端”有位,虚位以待

发送简历至HR邮箱,开启快速投递通道。

DiDi_Tech的博客 381

清华大学车辆学院联合滴滴自动驾驶提出STAPO算法,解决大模型强化学习微调稳定性问题

前者筛选前20%的优势词元进行训练,而STAPO则通过剔除极少数虚假词元(仅0.01%),确保数据纯洁度和训练稳定性。以六个基准测试(AIME24、AIME25、AMC23、MATH500、Minerva 和 OlympiadBench)和三个大模型(Qwen3 1.7B、8B 和 14B)的实验表明,正成为自动驾驶端到端模型、机器人具身智能模型、语言类多模态模型的重要训练算法,尤其是在大规模神经网络的微调(Fine-tuning)阶段,具有。,所采用的方案是剔除虚假词元的S2T机制。

DiDi_Tech的博客 260

滴滴开源新进展:华佗项目支持国产沐曦GPU,助推信创发展

华佗是由滴滴主导发起开源,依托中国计算机学会(CCF)孵化的操作系统深度观测项目,专注为云原生通用计算,AI 计算,云服务,基础服务等提供操作系统内核级深度观测能力。开发者可通过华佗平台,实时获取沐曦GPU的关键运行指标,这将进一步丰富华佗在异构计算环境下的可观测能力,为云原生、AI训练等场景的运维诊断提供更全面的数据支撑。滴滴开源始终以共建共享为核心,致力于携手产业伙伴共同探索技术创新与落地实践的最佳路径,促进生态资源、能力与经验的共享。有关指标的详细说明,请见后续的"指标介绍"章节。

DiDi_Tech的博客 482

滴滴自动驾驶成立深穹远航实验室,携手清华大学开展前沿研究

滴滴自动驾驶将以实验室为载体,向高校研究团队开放真实场景和工业级算力,为前沿研究提供强力支持,加速研究成果的落地。清华大学车辆与运载学院、人工智能学院李升波教授表示,自动驾驶是全球科技竞争的战略高地,清华大学在汽车智能化领域拥有深厚的基础研究实力和顶尖人才资源,滴滴自动驾驶在自动驾驶关键技术研发和应用上已有近十年的积累。双方的深度合作,将进一步提升科研成果工程化落地效率,共同服务国家科技自立自强与产业高质量发展。展望未来,滴滴自动驾驶将持续加大AI领域的研发投入,加强自主创新,深化与清华大学的产学研合作。

DiDi_Tech的博客 203

滴滴与智谱达成战略合作,将共同探索出行Agent场景落地

基于此次战略合作,双方将共同推进Agent场景落地和大模型领域人才培养,深化出行场景的意图对齐与推理能力建设,推动Agent在更复杂业务场景中的验证与落地。近年来,滴滴持续加大在大模型与智能体方向的技术投入,依托真实复杂出行场景,逐步推进了AI出行助手、商旅助手等智能体的创新应用。滴滴与智谱宣布达成战略合作,双方将围绕通用人工智能(AGI)关键技术及其在出行领域的智能体应用开展前瞻性协同探索。滴滴相关负责人表示,期待双方充分发挥各自优势,共同推动通用人工智能在更广阔真实场景中的应用与发展。

DiDi_Tech的博客 301

<span class=“js_title_inner“>滴滴与智谱达成战略合作,将共同探索出行Agent场景落地</span>

基于此次战略合作,双方将共同推进Agent场景落地和大模型领域人才培养,深化出行场景的意图对齐与推理能力建设,推动Agent在更复杂业务场景中的验证与落地。近年来,滴滴持续加大在大模型与智能体方向的技术投入,依托真实复杂出行场景,逐步推进了AI出行助手、商旅助手等智能体的创新应用。滴滴与智谱宣布达成战略合作,双方将围绕通用人工智能(AGI)关键技术及其在出行领域的智能体应用开展前瞻性协同探索。滴滴相关负责人表示,期待双方充分发挥各自优势,共同推动通用人工智能在更广阔真实场景中的应用与发展。

DiDi_Tech的博客 217

AI 在泛前端领域的思考和实践-上篇

而泛前端从业者自带 “懂交互、懂服务串联、懂用户体验” 的基因,在打造 AI Agent 驱动的无页面方案时,反而更具天然优势,如:在开发 “无页面化” 的服务场景时,泛前端能更快理清 “用户需求 - Agent 交互逻辑 - 后端 API 调用” 的链路,更精准地规避无页面场景下的体验痛点(如交互断层、反馈不及时),甚至能将过往跨端、组件化的技术经验,复用到 AI Agent 的功能模块设计中,让无页面方案更稳定、更易扩展。这意味着,单纯 “会写代码”“能套用方案” 的能力,正在逐渐失去稀缺性;

DiDi_Tech的博客 1529

AI 在泛前端领域的思考和实践

而泛前端从业者自带 “懂交互、懂服务串联、懂用户体验” 的基因,在打造 AI Agent 驱动的无页面方案时,反而更具天然优势,如:在开发 “无页面化” 的服务场景时,泛前端能更快理清 “用户需求 - Agent 交互逻辑 - 后端 API 调用” 的链路,更精准地规避无页面场景下的体验痛点(如交互断层、反馈不及时),甚至能将过往跨端、组件化的技术经验,复用到 AI Agent 的功能模块设计中,让无页面方案更稳定、更易扩展。这意味着,单纯 “会写代码”“能套用方案” 的能力,正在逐渐失去稀缺性;

DiDi_Tech的博客 636

滴滴开源走进浙江大学|共话开源实践与高校共建

Mpx是一款增强型跨端开发框架,以小程序原生语法和技术能力为基础,借鉴Vue框架的优秀语法设计,通过静态转译与运行时适配相结合,实现“一份源码,多端运行”。滴滴开源与CCF(中国计算机学会)重点孵化的HUATUO项目基于eBPF技术实现低损耗、零侵扰的内核数据采集,覆盖TCP/IP协议栈、CPU调度、内存管理等核心模块,并构建异常事件驱动诊断与全自动化追踪(AutoTracing)两大核心引擎,能够自动捕获softlockup、oom、网络延迟等关键事件,精准定位云原生场景下的偶发与突发故障。

DiDi_Tech的博客 877

滴滴开源荣获多项 OSCAR “开源+”典型案例奖

作为一个针对开源操作系统的深度可观测性项目,在滴滴内部,HUATUO 实现了超大规模部署,覆盖通用计算、AI 计算、大数据、存储、消息队列等核心场景,并与阿里云龙蜥、华为欧拉、腾讯、麒麟软件等主流生态合作,联合多家科技企业共建开源生态,实现技术共享与协同创新。秉承这一精神情怀,钱一峰积极引领开源文化生根发芽,鼓励更多内部技术同学参与开源贡献,让开源不再只是技术成果的输出,更成为连接个人与社区、企业与行业的重要桥梁,让“共建共享”的理念真正融入开源技术创新的每一步。OSCAR开源+安全及风险治理。

DiDi_Tech的博客 956

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 773

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 534

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 695

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 695

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 533

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 423

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 1030

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 544

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

标题:Order Acquisition Under Competitive Pressure: A Rapidly Adaptive Reinforcement Learning Approach for Ride-Hailing Subsidy Strategies作者:Fangzhou Shi(史方舟)、Xiaopeng Ke(柯晓鹏)、Xinye Xiong(熊薪叶)、Kexin Meng(孟可欣)、Chang Men(门畅)、Zhengdan Zhu(朱正丹)论文链接:https://arxiv.

DiDi_Tech的博客 915

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 991

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 370

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 926

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 755

ECML-PKDD ‘25 | FCA-RL框架——基于强化学习的出行服务商动态市场环境效率保障方法

这套离线仿真系统将在后续开源,敬请关注。我们的方法(FCA-RL)相较于传统基线方法大幅降低了出行服务商在动态市场环境下的投资预算控制误差且提升了订单的获取效率,但依然存有局限,比如暂未考虑建模乘客对于投资的长期心智变化及长期供需变化,在未来的工作中,将会尝试将这些考虑进来。在我们的背景设定下,站在我方RSP视角,其他RSP不定期投资幅度变化会导致市场环境动态变化,这会导致在原问题下的求解出的最优解在后续竞争的过程中发生偏移,使得最终花费偏离最初的预算约束,以及原始最优解的钱效变低。

DiDi_Tech的博客 671
上一篇: 滴滴CTO张博:滴滴将进一步加强产学研合作,促进产学研合作生态发展
下一篇: eBPF内核技术在滴滴云原生的落地实践
滴滴技术
滴滴技术 企业官方账号 企业官方账号
博客等级 码龄8年 2449粉丝 331原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值