news 2026/8/19 10:23:08

Agentics 2.0:用逻辑转换代数重塑智能体工作流的设计与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agentics 2.0:用逻辑转换代数重塑智能体工作流的设计与实现

1. 项目概述:从“智能体”到“逻辑工作流”的范式跃迁

最近和几个做AI应用落地的朋友聊天,大家普遍有个共识:单个大模型(LLM)的能力再强,也像是一个“超级个体户”,能写能画能聊,但一遇到需要多步骤、有逻辑依赖、涉及外部数据与工具的复杂任务,就有点力不从心了。比如,你想让AI帮你分析一份财报,然后根据分析结果自动生成一份投资建议PPT,再调用邮件API把PPT发给相关同事——这个过程,就不是一个简单的“提示词工程”能搞定的。这正是“智能体”(Agent)概念火起来的原因:我们需要的不再是单一模型,而是一个能自主规划、调用工具、协同工作的“智能体系统”。

然而,当大家一窝蜂去构建自己的智能体时,新的问题又出现了。这些智能体之间的协作,数据在不同工具和步骤间的流转,任务成功或失败后的逻辑分支处理,往往变得异常混乱。代码里充斥着大量的if-else、临时状态变量和硬编码的逻辑,整个系统脆弱、难以调试、更难以复用和规模化。这感觉就像用高级语言写汇编,空有智能的“个体”,却缺乏协调它们的“操作系统”和“编程语言”。

“Agentics 2.0: Logical Transduction Algebra for Agentic Data Workflows”这个项目,瞄准的就是这个痛点。它不是一个具体的工具库或框架,而是一套形式化、代数化的理论体系,旨在为智能体驱动的数据工作流(Agentic Data Workflows)提供一套严谨的“语法”和“运算规则”。你可以把它理解为智能体工作流领域的“布尔代数”或“关系代数”。它试图回答:如何用数学般清晰的方式,描述智能体、工具、数据之间的组合、流转与逻辑控制?如何确保复杂的工作流既是可执行的,又是可推理、可验证的?

简单来说,Agentics 2.0想做的,是为“智能体编排”这个当前略显野蛮生长的领域,注入坚实的理论基石和工程化范式。它适合所有正在或计划构建复杂AI应用架构的工程师、研究员和架构师,尤其是那些对系统的可靠性、可维护性和形式化验证有高要求的团队。如果你已经受够了智能体项目里“剪不断、理还乱”的胶水代码,那么这套逻辑转换代数的思想,或许能为你打开一扇新的大门。

2. 核心理念拆解:什么是“逻辑转换代数”?

要理解Agentics 2.0,核心在于拆解其标题中的两个关键概念:“逻辑转换”与“代数”。这并非简单的词汇堆砌,而是其理论体系的支柱。

2.1 超越“管道”:工作流作为“逻辑图”

传统的数据流水线(Data Pipeline)或ETL(抽取、转换、加载)过程,通常被建模为一个线性的或有向无环图(DAG)的“管道”。数据像水一样从一端流入,经过一系列处理节点,从另一端流出。每个节点是一个纯函数或操作,其核心是“数据转换”。

智能体工作流则截然不同。它的核心驱动力是“逻辑”和“目标”,而不仅仅是数据。一个智能体节点接收到输入后,其行为是不确定的:它可能需要“思考”(调用LLM进行规划),可能根据思考结果“决策”(选择调用工具A还是工具B),工具执行可能成功或失败,进而触发重试或备用路径。这里的每个节点,都是一个状态机,其输出不仅依赖于输入数据,还依赖于其内部逻辑状态、外部环境反馈以及全局任务目标。

因此,Agentics 2.0首先将智能体工作流重新定义为“逻辑图”。图中的节点不再是简单的数据处理函数,而是“逻辑单元”。节点之间的边,也不再仅仅是数据流,更是“控制流”和“逻辑依赖”的体现。一条边可能代表“如果条件P满足,则执行节点B”,也可能代表“节点A失败后,应回退到节点C”。

2.2 “转换”的核心:将“逻辑”形式化为“运算”

“转换”在此处有双重含义。一是指数据在流经工作流时发生的形态变化,这是传统意义。但更关键的是第二层含义:逻辑状态的转换。一个智能体从“等待输入”到“规划中”,再到“执行工具”、“评估结果”,最后到“完成”或“错误”,这是一个典型的状态转换序列。

Agentics 2.0的野心在于,它试图用一套代数符号和运算规则,来形式化地描述这些逻辑状态转换以及它们之间的组合关系。这就像我们用“+”、“-”、“×”、“÷”来描述数的运算,用“∧”、“∨”、“¬”来描述逻辑命题的运算一样。它试图为智能体工作流中的基本操作定义出类似的“运算符”。

例如,可能定义:

  • 序列运算;: 节点A执行后,无论结果如何,都执行节点B。这描述了时间或依赖上的先后顺序。
  • 条件运算?条件P ? 节点A : 节点B。根据某个谓词(可能是数据内容,也可能是上一个节点的输出状态)的真假,选择执行不同的分支。
  • 并行运算||: 节点A和节点B同时执行,等待所有/任一完成后再进行后续合并。
  • 循环运算*: 当条件C满足时,反复执行节点A。
  • 错误处理运算节点A ▷ 处理程序H。表示如果节点A执行失败,则转而执行错误处理程序H。

通过将这些基本运算作为“原子操作”,我们就可以用代数表达式来组合和描述极其复杂的工作流逻辑:工作流 = (A ; (B ? C : D)) || (E*) ▷ H。这样的表达式不仅对人类可读,更重要的是,它可能为机器推理、自动化验证和优化提供了可能。

2.3 “代数”的力量:组合性、等价性与优化

引入“代数”的概念,是为了赋予这套体系数学上的严谨性和威力。

  • 组合性:复杂的工作流可以通过基本运算符组合而成。这使得构建工作流像搭积木,我们可以先定义和验证小模块(如一个可靠的问答智能体单元),再通过代数运算将它们安全地组合成更大系统。
  • 等价性:代数允许我们定义工作流表达式的“等价”。例如,(A ; B) ; C在逻辑上可能等价于A ; (B ; C)(结合律)。或者,通过分析,我们可能发现某个工作流表达式可以简化为一个更高效但逻辑等价的表达式。这为工作流编译和优化提供了理论基础。
  • 推理与验证:基于代数规则,我们可以对工作流进行形式化推理。例如,我们可以尝试证明某个工作流“无论分支如何选择,最终都会执行节点Z来清理资源”(某种程度的安全性验证),或者证明“工作流W1在任何情况下的输出集合都包含于工作流W2的输出集合”(精化关系)。这对于构建高可靠性的关键任务AI系统至关重要。

所以,“逻辑转换代数”的本质,是为智能体工作流建立一套形式化描述语言和演算系统。它不关心智能体内部是用GPT-4还是Claude实现的,也不关心工具调用的是哪个API,它关注的是这些黑盒单元之间,逻辑与控制流应该如何被精确地定义、组合和分析。这是将智能体应用从“艺术”和“手艺”推向“工程”的关键一步。

3. 核心组件与代数运算详析

理解了核心理念,我们深入到Agentics 2.0理论框架的内部,看看它如何定义核心组件,以及这些组件之间通过哪些代数运算进行交互。我们可以将其类比为构建一个电路系统:先定义基本的门电路(与门、或门、非门),再定义它们连接和组合的规则。

3.1 基本类型与逻辑单元

在Agentics 2.0的代数体系中,一切都被抽象为具有特定类型的“项”。最核心的几种类型包括:

  • 数据项: 在工作流中流转的实际信息,例如用户查询的字符串、从数据库查询出的JSON、一张图片的二进制数据等。通常用D表示。
  • 逻辑单元: 这是工作流的基本执行节点,也是代数的核心操作数。一个逻辑单元U可以看作一个函数,但它映射的不是简单的数据到数据,而是上下文到动作。更形式化地,一个单元可以定义为:U :: Context -> Action + State。它接收一个上下文(包含输入数据、环境变量、历史记录等),输出一个要执行的动作(如调用某个工具、请求LLM生成、返回最终结果)并更新自身及全局状态。
  • 谓词: 一个返回布尔值的函数,用于条件判断。例如,HasKey(data, “price”)LLM_Judgment(context) == “APPROVE”。谓词是驱动工作流逻辑分支的关键。
  • 动作: 逻辑单元执行的具体操作,如CallTool(“calculator”, args)GenerateText(prompt)Return(result)。动作执行后会产生效果(如外部工具调用)并输出新的数据项。

一个最简单的智能体工作流,可能就是一个逻辑单元:接收用户问题,调用LLM,返回答案。但Agentics 2.0关注的是如何将多个这样的单元用代数规则组合起来。

3.2 核心代数运算及其语义

以下是基于该理念可能定义的一组核心代数运算。每个运算不仅定义了语法,更关键的是定义了其操作语义——即它如何改变工作流的执行状态。

1. 序列组合

  • 语法U1 ; U2
  • 语义: 先执行逻辑单元U1。只有当U1成功执行并产生输出(非错误终止状态)后,才会将U1的输出作为(部分)输入上下文,传递给U2并执行它。U1的失败会导致整个序列失败。
  • 实操要点: 这是最基础的组合方式。在实际编码中,需要明确U1的输出如何与原有上下文合并,以形成U2的输入。是覆盖、合并还是追加?这需要在代数语义或具体实现中定义清楚。例如,可以约定每个单元的输出都是一个命名空间下的键值对,序列组合执行的是上下文的增量更新。

注意:序列组合看似简单,但在智能体场景下,“成功”的定义需要仔细界定。是LLM输出了非空内容就算成功,还是必须调用工具并得到有效返回?这需要根据单元类型预先定义好状态转移规则。

2. 条件选择

  • 语法P ? U_t : U_f
  • 语义: 首先计算谓词P(基于当前上下文)。如果P为真,则执行逻辑单元U_t;如果为假,则执行U_f。执行后,工作流继续。
  • 实操要点: 谓词P的求值本身可能是有代价的(例如,需要调用一个LLM来做判断)。在代数模型中,可以将谓词求值也视为一个特殊的逻辑单元。此外,条件选择可以嵌套,形成复杂的决策树:P1 ? (P2 ? U_a : U_b) : U_c

3. 错误处理与回退

  • 语法U ▷ H
  • 语义: 尝试执行逻辑单元U。如果U成功执行,则忽略H,继续后续流程。如果U执行失败(进入错误状态),则转而执行错误处理单元HH的输入通常是U的失败上下文(包含错误信息)。
  • 实操要点: 这是实现鲁棒性的关键。H可以是一个简单的日志记录单元,也可以是一个复杂的恢复流程,比如重试U(可能带有退避策略)、切换到备用方案、或者向用户请求澄清。代数运算提供了一种声明式的方式来附加错误处理逻辑,而不是在每个单元内部写try-catch

4. 并行组合

  • 语法U1 || U2(所有成功)或U1 |+| U2(任一成功)
  • 语义: 并行地执行U1U2。对于||,需要等待两者都执行完毕(无论成功或失败),并根据两者的结果聚合上下文(例如,合并输出字典)。对于|+|,只要其中一个成功,即可继续,另一个可能被取消或忽略其结果。
  • 实操要点: 并行执行涉及资源竞争和状态同步。在代数层面,需要定义清楚并行分支的上下文是共享的、隔离的,还是初始拷贝的。聚合结果时,如何处理命名冲突?这些都需要在代数语义中给出确定性的规则。例如,可以规定并行分支在隔离的上下文副本中运行,最终通过一个用户定义的“合并函数”来整合结果。

5. 循环迭代

  • 语法while P do UU*(Kleene星,表示执行0次或多次)
  • 语义: 只要谓词P在当前上下文中为真,就重复执行逻辑单元U。每次迭代后,用新的上下文重新评估PU*可以看作是while True do U但包含一个隐式的终止条件(如U输出特定信号)。
  • 实操要点: 循环是实现自主规划和迭代优化的关键。必须严防无限循环。在代数框架下,可以为循环设置一个最大迭代次数的元数据,或者要求循环体U必须包含一个能使谓词P最终变为假的动作。在实际系统中,循环常与“规划-执行-评估”模式对应。

通过这些基本运算的组合,我们可以构造出描述复杂智能体协作的表达式。例如,一个文档分析并生成摘要的工作流可能表达为:(FetchDoc(url) ▷ Retry(3) ; (IsLongDoc ? SummarizeChunkwise : SummarizeDirectly)) || ExtractKeywords(doc) ; MergeResults

这个表达式清晰地表达了:获取文档(失败则重试3次),然后根据文档长度选择摘要策略,同时并行提取关键词,最后合并结果。

4. 从代数到实践:构建可执行的工作流引擎

理论再优美,也需要落地。Agentics 2.0的代数体系最终需要被一个“编译器”或“解释器”执行。这部分探讨如何将代数表达式转化为可运行的系统,这是工程实现的核心。

4.1 工作流定义与DSL

首先,我们需要一种方式来“书写”代数表达式。通常,这会体现为一门领域特定语言

  • YAML/JSON声明式: 对于追求简洁和可读性的场景,可以采用声明式配置。每个逻辑单元和运算都有对应的YAML结构。

    workflow: name: “ResearchAndReport” steps: - type: sequence steps: - agent: “WebSearcher” with: { query: “{{user_query}}” } - type: conditional if: “{{steps.WebSearcher.output.count}} > 5” then: - agent: “FilterRelevant” else: - agent: “ExpandSearch” - type: parallel branches: - agent: “Summarizer” - agent: “SentimentAnalyzer” - agent: “ReportCompiler”

    这种方式的优点是直观,易于与现有配置工具集成。缺点是对复杂逻辑的表达能力有限,且难以直接体现代数运算的等价变换。

  • 嵌入式DSL: 在通用编程语言(如Python)中,通过库的形式实现代数运算符的重载,从而可以在代码中直接使用类似代数的语法。

    # 假设有一个实现了Agentics代数的库 from agentics import Agent, condition, sequence, parallel, recover web_searcher = Agent(“WebSearcher”) summarizer = Agent(“Summarizer”) sentiment = Agent(“SentimentAnalyzer”) compiler = Agent(“ReportCompiler”) # 定义谓词函数 def has_many_results(ctx): return len(ctx.get(“search_results”, [])) > 5 # 用代数风格组合工作流 workflow = ( web_searcher .recover(retry_policy=Retry(max_attempts=3)) # 对应 ▷ 运算 .then(condition(has_many_results, FilterRelevant(), ExpandSearch())) # 对应 ?: 运算 .then(parallel(summarizer, sentiment)) # 对应 || 运算 .then(compiler) )

    这种方式灵活强大,能充分利用宿主语言的生态系统,并且代码本身就是代数表达式的直接体现,便于进行静态分析和重构。

4.2 执行引擎与运行时

定义了工作流之后,需要一个执行引擎来解释或编译它,并管理其生命周期。引擎的核心职责包括:

  1. 解析与验证: 将DSL或配置解析成内部的抽象语法树(AST),这棵树本质上就是代数表达式。验证其语法和类型是否正确(例如,检查序列组合中前后单元的数据输出/输入类型是否兼容)。
  2. 状态管理: 维护一个全局的“执行上下文”。这个上下文是一个键值存储,随着工作流的推进而不断演化。每个逻辑单元读取上下文,执行动作,并将结果写回上下文。引擎需要负责上下文的版本管理、快照(用于回滚或调试)以及在并行分支间的隔离与合并。
  3. 调度与执行: 按照代数表达式的语义调度逻辑单元的执行。对于序列,是简单的顺序调用。对于条件,需要先求值谓词(这可能又是一个单元的执行)。对于并行,需要管理线程池或异步任务。对于循环,需要管理迭代状态。
  4. 错误传播与恢复: 严格执行错误处理代数的语义。当某个单元失败时,引擎需要捕获异常,将状态切换为错误,并查找附加的错误处理程序(H)来执行。如果找不到,则整个工作流失败。
  5. 可观测性: 在关键点注入日志、指标和追踪。记录每个单元的输入、输出、开始和结束时间、状态转换。这对于调试复杂、非确定性的智能体工作流至关重要。理想的引擎应该能生成工作流执行的“逻辑轨迹图”,与最初设计的代数表达式进行直观对比。

4.3 逻辑单元的标准化接口

为了使代数运算能够通用,所有逻辑单元必须遵守统一的接口契约。一个最小化的接口可能包括:

  • execute(ctx: Context) -> Tuple[Action, ContextDelta]: 核心执行方法,输入当前上下文,输出要执行的动作以及对上下文的更改(增量)。
  • get_input_schema() -> Schema: 声明本单元期望的输入上下文结构。
  • get_output_schema() -> Schema: 声明本单元成功执行后会产生哪些新的上下文数据。
  • get_possible_states() -> List[State]: 声明本单元可能处于的状态(如 READY, RUNNING, SUCCESS, FAILED, WAITING_FOR_TOOL)。

执行引擎利用这些接口信息进行类型检查、静态验证和自动化编排。例如,在验证A ; B时,引擎可以检查A的输出模式是否满足B的输入模式,从而在运行前发现潜在的不匹配。

通过这样一套从代数理论到DSL再到执行引擎的完整栈,Agentics 2.0的理念才能从纸面走向现实,真正用于构建可靠、可维护的智能体系统。

5. 实战应用:设计一个基于代数的客服工单处理智能体

让我们通过一个具体的、简化的案例,来看看如何运用Agentics 2.0的思想来设计一个工作流。假设我们要构建一个自动处理用户客服工单的智能体系统。

业务场景:用户提交工单(文本描述+可选图片)。系统需要:1) 理解工单内容并分类;2) 根据类别查询知识库获取解决方案;3) 若知识库有答案则自动回复;4) 若无答案或用户对自动回复不满意,则转交人工客服,并附上初步分析摘要。

5.1 定义逻辑单元与谓词

首先,我们识别并定义工作流中所需的原子逻辑单元:

  1. ParseTicket: 解析原始工单,提取结构化信息(用户ID、问题描述、图片URL、紧急程度等)。
  2. ClassifyIntent: 基于问题描述,调用LLM对工单进行意图分类(如“退款申请”、“技术故障”、“账户问题”)。
  3. QueryKB: 根据分类结果和关键词,查询内部知识库,返回最相关的解决方案文章列表。
  4. EvaluateKBMatch: 评估知识库返回的解决方案与用户问题的匹配度(例如,通过LLM判断相关性分数)。这是一个谓词单元,输出布尔值。
  5. GenerateReply: 根据匹配的解决方案,生成一封友好、专业的回复邮件。
  6. EscalateToHuman: 创建人工客服工单,并附上所有已有的分析上下文。
  7. NotifyUser: 向用户发送通知(邮件或应用内消息)。

5.2 用代数表达式组合工作流

接下来,我们用代数运算将这些单元组合起来,形成完整的工作流逻辑。

工作流表达式 W = ParseTicket ; ClassifyIntent ; ( (QueryKB ; EvaluateKBMatch) ? (GenerateReply ; NotifyUser) : (EscalateToHuman ; NotifyUser) )

让我们拆解这个表达式:

  1. ParseTicket ; ClassifyIntent: 先解析工单,再进行意图分类。这是标准的序列操作。
  2. 外层是一个大的条件选择运算(…) ? (…) : (…)
  3. 条件判断的部分是(QueryKB ; EvaluateKBMatch)。注意,这里是一个序列:先查询知识库,然后用查询结果进行评估。EvaluateKBMatch这个谓词单元的输出(真/假)将作为整个条件判断的依据。
  4. 如果条件为真(知识库匹配度高),则执行GenerateReply ; NotifyUser,自动回复用户。
  5. 如果条件为假(无匹配或匹配度低),则执行EscalateToHuman ; NotifyUser,升级给人工并通知用户已转交。

5.3 增强鲁棒性:注入错误处理

上述基础流程很清晰,但缺乏容错。现实中,任何一个步骤都可能失败:LLM调用超时、知识库宕机、邮件发送失败。我们需要使用错误处理运算来增强鲁棒性。

增强版工作流表达式 W_robust = (ParseTicket ▷ LogAndUseDefault) ; (ClassifyIntent ▷ Retry(2) ▷ FallbackToGenericCategory) ; ( ((QueryKB ▷ Retry(3) ▷ UseCachedKB) ; EvaluateKBMatch) ? ((GenerateReply ▷ ValidateReply) ; (NotifyUser ▷ Retry(2) ▷ QueueForRetry)) : ((EscalateToHuman ▷ LogEscalationError) ; NotifyUser) )

这个版本在每个可能出错的环节都附加了错误处理程序(H):

  • ParseTicket失败,则记录日志并使用一个默认的工单结构(LogAndUseDefault)。
  • ClassifyIntent失败,先重试2次,若仍失败则归为“通用”类别(FallbackToGenericCategory)。
  • QueryKB失败,重试3次,若仍失败则使用一个本地的、可能过时的缓存知识库(UseCachedKB)。
  • GenerateReply生成回复后,用一个简单的验证单元检查回复是否合理(如是否包含敏感词、是否为空)。
  • NotifyUser发送通知失败,重试2次,若仍失败则将通知任务放入重试队列稍后处理。

通过这种声明式的方式,我们将核心业务逻辑(代数表达式)与容错、降级等非功能性需求(错误处理程序)清晰地分离开来。整个工作流的设计就像在编写一个可读性极强的、专注于“做什么”的规格说明书,而“出错时怎么办”的细节被封装在独立的处理单元中。

5.4 实现与调试心得

在实际实现这个工作流时,基于Agentics代数思想,我倾向于使用嵌入式DSL的方式。以下是一些关键的实操心得:

  • 上下文设计是关键: 定义一个全局的、强类型的上下文数据结构。每个单元读写上下文中的特定字段。例如,ParseTicket写入ctx[“structured_ticket”]ClassifyIntent读取它并写入ctx[“intent_category”]。这避免了数据在函数间隐式传递带来的混乱。
  • 谓词单元要纯: 像EvaluateKBMatch这样的谓词单元,应尽量设计为无副作用的纯函数(或至少副作用可忽略)。它的输出应只依赖于输入上下文,这样才便于推理和测试。避免在谓词中执行修改数据库等重量级操作。
  • 为所有单元实现idempotency: 尽可能让每个逻辑单元是幂等的。这意味着用相同的上下文多次执行同一个单元,结果应该相同。这对于错误恢复和重试机制至关重要。例如,QueryKB单元在重试时,应使用相同的查询参数。
  • 可视化与追踪: 执行引擎必须输出详细的执行轨迹。理想情况下,应该能生成一个与代数表达式结构对应的可视化流程图,其中每个节点的状态(成功、失败、重试中)、输入/输出快照都一目了然。这是调试非确定性智能体工作流的最有力工具。
  • 从简单开始,逐步组合: 不要试图一次性写出完整的复杂表达式。先独立实现和测试每个原子单元。然后用序列组合两个单元进行测试,再加入条件分支测试。这种“自底向上”的组合方式,与代数的组合性思想完美契合,能极大降低开发和调试的复杂度。

通过这个案例可以看出,Agentics 2.0的逻辑转换代数并非空中楼阁。它提供了一种强大的抽象工具,让我们能以更清晰、更模块化、更可靠的方式来设计和实现日益复杂的智能体应用。它将智能体系统的构建,从面向过程的脚本编写,提升到了面向逻辑的声明式编排层面。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/19 10:22:08

基于代码知识图谱与LLM智能体的项目分析与自动化重构实践

1. 项目概述:当LLM智能体“看见”代码仓库最近在AI圈子里,一个概念讨论得越来越热:让大型语言模型(LLM)驱动的智能体(Agents)去“看见”并理解整个代码仓库。这听起来有点科幻,但背后…

作者头像 李华
网站建设 2026/8/19 10:17:40

Pico多功能入门套件:从嵌入式开发到物联网项目实战指南

1. 项目概述:从“开发板”到“多面手”的蜕变 最近在捣鼓嵌入式开发的朋友,估计没少听人提起“Pico”这个名字。它早已不是某个单一产品的代号,而是演变成了一个充满活力的开源硬件生态。从最初那个小巧的树莓派Pico,到后来各种基…

作者头像 李华
网站建设 2026/8/19 10:15:54

类和对象(构成,定义)

一.类与对象 面向对象编程的2个非常重要的概念:类和对象。 类:拥有相同属性和行为的对象分为一组,即为一个类。(对拥有相同属性和行为对 象的一个抽象)。 对象:类的一个具体实例。类是创建对象实例的”模板。 二.类的构成 类(Clas…

作者头像 李华
网站建设 2026/8/19 10:15:43

把电脑游戏串流到手机和电视,凭什么一分钱不用花

把电脑游戏串流到手机和电视,凭什么一分钱不用花 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你有没有算过,花大几千配的游戏电脑,一天真正坐…

作者头像 李华