如何在问题真正发生之前发现运营中的异常变化?
在 我之前的文章中 ,我探讨了“操作符合性”这一概念:即如何判断观察到的实际情况是否满足既定的操作规范。 这就引出了一个很有意义的问题: 当前这个系统是否仍然符合这些规范? 然而,生产环境中的系统是不会一成不变的。 流量会发生变化,依赖关系可能会恶化,证书也会过期,配置设置会被修改,功能开关的状态也会改变,数据量会不断增加,人们还会进行手动操作,各种代理程序也会执行相应的动作,基础设施也会被替换等等。 一个系统在部署后可能最初是符合规范的,但几小时或几天后就可能不再符合这些规范了。 这就是我想在这里探讨的问题。 “操作漂移”指的是系统的实际运行状态与既定操作规范之间的差异会随着时间逐渐增大。
在我之前的文章中,我探讨了“操作符合性”这一概念:即如何判断观察到的实际情况是否满足既定的操作规范。
这就引出了一个很有意义的问题:
当前这个系统是否仍然符合这些规范?
然而,生产环境中的系统是不会一成不变的。
流量会发生变化,依赖关系可能会恶化,证书也会过期,配置设置会被修改,功能开关的状态也会改变,数据量会不断增加,人们还会进行手动操作,各种代理程序也会执行相应的动作,基础设施也会被替换等等。
一个系统在部署后可能最初是符合规范的,但几小时或几天后就可能不再符合这些规范了。
这就是我想在这里探讨的问题。
“操作漂移”指的是系统的实际运行状态与既定操作规范之间的差异会随着时间逐渐增大。
这个概念比“配置漂移”更为广泛。配置漂移关注的是基础设施或配置设置是否与事先声明的状态有所不同,而操作漂移则关注的是:即使配置本身没有发生变化,系统的行为是否仍然符合我们预期的范围。
一个服务即使其配置与昨天完全相同,也可能会出现操作上的漂移——比如延迟增加、错误率上升、副本可用性下降、某些依赖关系变得不稳定、某些策略不再被执行,或者相关证据消失了等等。
在这篇文章中,我将向您介绍如何对操作漂移进行建模、如何建立符合性基准线、如何随着时间的推移重新评估系统的状态、如何区分暂时性的异常变化与真正的漂移现象、如何保存与漂移相关的证据、如何根据漂移的严重程度来采取相应的措施,以及何时应该触发警报、启动调查或自动响应机制。
核心思想是这样的:符合性可以告诉我们某个时刻上系统的实际运行情况是否与预期目标一致;而漂移则能说明这种关系是否正在发生变化。
先决条件
您需要具备以下基础知识:
软件架构
TypeScript或类似的语言
可观测性技术
操作规范的定义与编写方法
基于证据的评估方法
符合性的概念及评估方法
基本的监控原理
您并不需要使用特定的基础设施平台。文章中的示例虽然使用了部署场景,但同样的模型也适用于基础设施、数据管道、备份系统、访问控制机制、AI代理程序以及其他各种操作工作流程。
目录
什么是运营漂移
假设某个部署在10:00完成。
运营规范规定如下:
版本 = v42
可用副本数 >= 3
错误率 <= 1%
95%延迟时间 <= 400毫秒
部署完成后,实际数据如下:
版本 = v42
可用副本数 = 3
错误率 = 0.4%
95%延迟时间 = 280毫秒
此时系统仍然符合规范要求。
现在假设在14:00时,实际数据变为:
版本 = v42
可用副本数 = 3
错误率 = 0.8%
95%延迟时间 = 370毫秒
系统仍然符合规范要求,但确实发生了某些变化。
错误率和延迟时间正在接近它们的极限值。
到了16:00时:
版本 = v42
可用副本数 = 3
错误率 = 1.4%
95%延迟时间 = 460毫秒
此时系统已经不再符合规范要求了。
运营规范本身并没有改变,执行流程也可能没有重新运行,但实际情况已经发生了变化。
这就是所谓的“运营漂移”。
我们可以用以下方式来理解它:
规范要求
↓
预期的运营状态范围
↓
T0时刻的实际状态
↓
T1时刻的实际状态
↓
T2时刻的实际状态
↓
漂移情况的评估
关键在于时间因素:合规性是一种静态的状态,而漂移则反映了不同时间点上实际状态与规范要求之间的差异。
运营漂移与配置漂移不是一回事
对于你们来说,“配置漂移”这个概念可能已经很熟悉了。
所谓“配置漂移”,是指你声明的配置或基础设施状态与环境中的实际状态之间的差异。
例如:
期望的副本数 = 3
实际的副本数 = 2
在这种情况下,声明的状态要求服务应该有3个副本,但实际上只有2个,因此配置状态与实际运行状态不一致。
或者:
配置偏差
=
声明的配置与实际配置不一致
而“运行状态偏差”则是指:
实际的运行状态超出了预定的范围
这两种偏差可能会同时存在,但它们本质上是不同的。
这种区分非常重要,因为在生产环境中,系统出现故障时,往往首先表现为运行状态的异常,而非配置上的问题。
以合规性基线作为起点
任何偏差都需要一个参考点。最简单的参考点就是已知的合规状态。
例如:
type DeploymentEvidence = {
version?: string;
replicas?: number;
errorRate?: number;
p95LatencyMs?: number;
};
假设在系统部署完成后对其进行了评估:
const baseline: DeploymentEvidence = {
version: "v42",
replicas: 3,
errorRate: 0.004,
p95LatencyMs: 280,
};
而且所有必要的约束条件也都得到了满足。
这样的基线能为你提供两样有用的信息:首先,你可以确定在该评估时刻系统确实符合规范要求;其次,你有了一个具体的参考标准,之后收集到的数据都可以与之进行对比。
这并不意味着后续收集到的数据必须与基线完全一致——那样的要求未免过于严格了。
实际上,后续的数据可以通过两种方式来进行分析:
它是否仍然符合规范要求?
与基线相比,它的状态发生了哪些变化?
这些都是很有意义的分析方向。
type TimedEvidence = { timestamp: string; evidence: DeploymentEvidence; };
例如:
const observations: TimedEvidence[] = [
{
timestamp: "10:00",
evidence: {
version: "v42",
replicas: 3,
errorRate: 0.004,
p95LatencyMs: 280,
},
},
{
timestamp: "12:00",
evidence: {
version: "v42",
replicas: 3,
errorRate: 0.006,
p95LatencyMs: 320,
},
},
{
timestamp: "14:00",
evidence: {
version: "v42",
replicas: 3,
errorRate: 0.008,
p95LatencyMs: 370,
},
},
];
每一份收集到的数据都可以用相同的规范标准来进行评估。
这样就能得到一个反映系统状态变化的趋势图:
10:00 合规
12:00 合规
14:00 合规
乍一看,所有数据似乎都正常;但仔细观察后会发现,这些数据其实是在朝着某个方向变化的。
正是在这种情况下,偏差检测才比单纯的阈值监控更为有用。
type DriftStatus = | "STABLE" | "DEGRADING" | "VIOLATED" | "UNKNOWN";
这为评估者提供了四种明确的状态。STABLE表示观察到的行为仍在预期范围内,没有出现明显的恶化。DEGRADING表示系统仍在允许的范围内,但正在朝着不利的方向发展。VIOLATED表示当前的证据已经超出了规格规定的限制。UNKNOWN表示目前的证据不足以安全地对系统状态进行分类。
接下来是:
type DriftResult = {
constraint: string;
status: DriftStatus;
baseline?: number;
current?: number;
limit?: number;
};
DriftResult这个类型将分类结果以及解释该结果的各项数据结合在一起。baseline代表已知的正常参考值,current代表最新的观测数值,limit则代表规格中规定的界限。这些字段是可选的,因为某些约束条件可能并非数值类型,或者某些数据可能缺失。
以延迟为例:
baseline = 280
current = 370
limit = 400
在这个例子中,延迟最初为280毫秒,现在变为370毫秒,但必须保持在400毫秒及以下。虽然这一约束条件尚未被违反,但目前的数据已经非常接近限制值了。
在这种情况下,将系统状态标记为DEGRADING可能是合理的。
因此,漂移模型并不是用来替代合规性检测的,它只是为评估过程增添了一个新的维度。
有时会出现这样的情况:
conformance = PASS
drift = DEGRATING
这种组合往往比单独使用任何一种指标都能提供更有价值的参考信息。
临时性变化并不一定意味着系统出现漂移
生产环境中的系统往往会存在各种干扰因素。
一次请求处理速度变慢,并不意味着系统出现了漂移;某个样本数据缺失,也不代表服务状态异常;而偶尔出现的短暂性能波动,更不必然需要采取干预措施。
假设我们有以下延迟数据:
280
290
420
285
295
其中420这个数值超出了规定的限制,但系统很快又恢复了正常状态。
再来看另一个例子:
280
310
340
370
395
虽然这个序列中的数据从未超过限制值,但它明显显示出了系统性能的持续下降趋势。
正因为如此,我们不能简单地将“漂移”定义为:current != baseline
甚至也不能仅凭有一个样本超出了阈值就来判断系统出现了漂移。
只有当漂移现象具备持续性和方向性时,它才具有实际的意义。
使用时间窗口而非单个样本进行评估
一种更有效的方法是,在一定的时间窗口内对各项观测数据进行分析。
例如:function average(
values: number[]
): number {
return (
values.reduce(
(sum, value) => sum + value,
0
) / values.length
);
}
现在,假设你计算了最近五次测得的延迟数据:
const latencyWindow = [
300,
320,
340,
360,
380,
];
const currentAverage =
average(latencyWindow);
这种处理方法可以消除一些临时出现的异常数据。
你可以将这个时间窗口与之前的一个时间窗口进行比较:
const baselineWindow = [
270,
275,
280,
285,
290,
];
const baselineAverage =
average(baselineWindow);
之前的时间窗口可以为你提供关于系统典型运行状况的参考数据,而最近的时间窗口则能反映系统当前的运行状态。通过比较这两个平均值,你可以判断整个系统的性能是否发生了变化,而不是仅仅因为某个异常数据就下结论。
const delta =
currentAverage -
baselineAverage;
如果 baselineAverage 是 280 毫秒,而 currentAverage 是 340 毫秒,那么 delta 的值就是 +60 毫秒。这并不意味着系统的延迟限制被违反了,但它确实说明最近的延迟情况比之前的数据更糟糕。
function evaluateLatencyDrift(
baseline: number | undefined,
current: number | undefined,
limit: number
): DriftStatus {
if (
baseline === undefined ||
current === undefined
) {
return "UNKNOWN";
}
if (current > limit) {
return "VIOLATED";
}
if (current > baseline) {
return "DEGRADING";
}
return "STABLE";
}
这个函数会按照一定的顺序来分析各种情况。首先,如果基准值或当前测量数据中的任意一项缺失,它就会返回 UNKNOWN,因为没有足够的数据来进行比较。如果数据存在,并且当前的延迟值已经超过了允许的限度,它会返回 VIOLATED;如果当前的延迟值虽然没有超过限制,但比基准值更差,它会返回 DEGRADING;只有当以上这些情况都不成立时,它才会返回 STABLE。
这种判断方法仍然过于简化了,因为任何超出基线的变化都被视为恶化趋势,即使这种变化非常微小或只是暂时的。在真实的系统中,人们通常会结合容差值、观察窗口长度、变化的持续性以及趋势规则来综合分析这些问题。但这一原则依然非常重要:缺乏证据并不意味着系统处于稳定状态。
当观测系统本身出现故障时,这一点就显得尤为重要了。
增加严重性等级与持续性的判断
只有当你了解某个约束条件的重要性以及这种变化已经持续了多久之后,“漂移”这一概念才会变得有实际意义。
例如:
type DriftSeverity =
| "INFO"
| "WARNING"
| "CRITICAL";
type DriftObservation = {
constraint: string;
status: DriftStatus;
severity: DriftSeverity;
consecutiveWindows: number;
};
在这里,severity用来表示受影响约束条件所造成的实际运营影响,而consecutiveWindows则记录连续多少个观察窗口都显示出了相同的漂移现象。同时考虑这两个因素是非常重要的,因为一次短暂的警告与持续八个观察窗口才出现的警告是截然不同的;此外,即使某个复制错误只出现了两次,但如果其严重性等级为“危急”,那么也确实需要采取相应的措施。
现在你可以这样区分这些情况:
延迟
恶化趋势
警告
1个观察窗口
与:
延迟
恶化趋势
警告
8个观察窗口
以及:
在阈值失效之前检测方向性漂移
在漂移检测中,能够识别出变化的方向是极其有用的。
假设错误率的上限为:
1%
而实际的观测数据如下:
0.2%
0.4%
0.6%
0.8%
虽然目前还没有任何故障发生,但这种变化趋势非常明显。
通过计算简单的斜率就可以判断出变化的方向。
例如:
function slope(
values: number[]
): number {
if (values.length < 2) {
return 0;
}
return (
values[values.length - 1] -
values[0]
) / (values.length - 1);
}
这个函数会计算序列中第一个值和最后一个值之间的差值,然后除以它们之间的间隔数。这是一个设计得相当简单的趋势判断指标:正数表示该指标在观察窗口内呈上升趋势,负数表示下降趋势,接近零的值则表示变化幅度很小。
接下来,我们可以这样使用这个函数:
const errorRates = [
0.002,
0.004,
0.006,
0.008,
];
const trend =
slope(errorRates);
在这里,错误率从0.002上升到了0.008,因此变化趋势是正向的。该代码并不是试图预测未来或进行全面的统计分析,它只是明确了变化的方向,这样系统就能在错误率真正超过1%这一阈值之前,及时察觉到这种持续上升的趋势。
正向的变化趋势并不一定意味着系统出现了故障,但它确实表明系统正在朝着某个临界值方向发展。
这就是“漂移检测”与普通警报机制的不同之处所在。
普通的阈值警报机制:
当错误率超过1%时,立即发出警报。
而漂移检测机制:
当错误率持续朝着1%的方向变化时,才发出警报。
后者能够给人们更多时间来进行调查,从而避免系统在真正违反规定之前就出现故障。
保留漂移现象背后的证据
任何与“漂移”相关的结果都应当是可以被解释清楚的。
例如:
{
"constraint": "error-rate",
"status": "DEGRADING",
"baseline": 0.004,
"current": 0.008,
"limit": 0.01,
"window": "10m",
"consecutiveWindows": 4,
"observedAt": "2026-10-13T18:00:00Z"
}
这样的表述显然比单纯的“检测到漂移现象”要好得多,因为这样人们就可以提出以下问题:
是什么导致了这种变化?是与什么相比而产生的变化?我们距离极限值还有多远?这种现象已经持续了多久?是在什么时候被发现的?
这些问题的答案对于调试系统以及确保系统的可审计性来说都非常重要。
一个可重复使用的漂移检测工具
我们可以将这个模型进行泛化处理。
首先定义一条漂移检测规则:
type DriftRule<T> = {
name: string;
severity: DriftSeverity;
evaluate(
baseline: T,
current: T
): DriftStatus;
};
然后定义一个漂移检测规范:
type DriftSpec<T> = {
name: string;
rules: DriftRule<T>>[];
};
最后再定义一个用于评估这些规则的函数:
type DriftRuleResult = {
name: string;
status: DriftStatus;
severity: DriftSeverity;
};
function evaluateDrift<T>(
spec: DriftSpec<T>>,
baseline: T,
current: T
): DriftRuleResult[] {
return spec.rules.map(
(rule) => ({
name: rule.name,
status:
rule.evaluate(
baseline,
current
),
severity:
rule.severity,
})
);
}
这个评估工具并不需要了解延迟时间、错误率、副本数量或证书信息等内容。
每条检测规则都拥有自己独立的比较逻辑,因此这种机制具有很高的复用性。
一个简单的端到端示例
让我们为某个部署环境创建一个漂移检测规范吧。
首先需要确定一些用于评估的参数:
type DeploymentEvidence = {
replicas?: number;
errorRate?: number;
p95LatencyMs?: number;
};
现在来定义规则:
const driftRules:
DriftRule〈DeploymentEvidence〉>[] = [
{
name: "replicas",
severity: "CRITICAL",
evaluate: (
baseline,
current
) => {
if (
baseline.replicas === undefined ||
current.replicas === undefined
) {
return "UNKNOWN";
}
if (current.replicas < 3) {
return "VIOLATED";
}
if (
current.replicas < baseline.replicas
) {
return "DEGRADING";
}
return "STABLE";
},
},
{
name: "error-rate",
severity: "CRITICAL",
evaluate: (
baseline,
current
) => {
if (
baseline.errorRate === undefined ||
current.errorRate === undefined
) {
return "UNKNOWN";
}
if (current.errorRate > 0.01) {
return "VIOLATED";
}
if (
current.errorRate > baseline.errorRate * 1.5
) {
return "DEGRADING";
}
return "STABLE";
},
},
{
name: "latency",
severity: "WARNING",
evaluate: (
baseline,
current
) => {
if (
baseline.p95LatencyMs === undefined ||
current.p95LatencyMs === undefined
) {
return "UNKNOWN";
}
if (
current.p95LatencyMs > 400
) {
return "VIOLATED";
}
if (
current.p95LatencyMs > baseline.p95LatencyMs * 1.25
) {
return "DEGRADING";
}
return "STABLE";
},
},
];
创建偏差检测规范:
const driftSpec:
DriftSpec〈DeploymentEvidence〉> = {
name: "orders-runtime-drift",
rules: driftRules,
};
现在来定义基准值和当前的实际数据:
const baseline:
DeploymentEvidence = {
replicas: 3,
errorRate: 0.004,
p95LatencyMs: 280,
};
const current:
DeploymentEvidence = {
replicas: 3,
errorRate: 0.007,
p95LatencyMs: 360,
};
进行评估:
const drift =
evaluateDrift(
driftSpec,
baseline,
current
);
可能的评估结果如下:
replicas STABLE CRITICAL
error-rate DEGRADING CRITICAL
latency DEGRATING WARNING
系统可能仍然符合要求,但相对于基准值而言,其运行稳定性已经下降。
这些信息非常有用。
偏差检测在多个执行器中的应用方式
假设有两个执行器都成功部署了相同的服务。
在部署完成后立即:
执行器A → 符合规范
执行器B → 符合规范
但这并不意味着它们在长期运行过程中的表现是完全相同的。
随着时间的推移:
执行器A
错误率稳定
延迟稳定
副本数量稳定
执行器B
错误率上升
延迟上升
副本数量稳定
尽管这两种执行器在初始阶段都符合规范要求,但它们在后续运行中的表现却有所不同。
“漂移”现象为人们提供了另一个比较维度。
你可以这样问:
哪种执行器产生的结果更稳定?
哪种执行器更容易出现漂移现象?
哪种执行器会生成更多不可预测的结果?
哪种执行器需要更频繁地进行恢复操作?
当执行器的选择是动态变化的时,这种分析方法尤其有用。
漂移检测在AI智能体中的应用
AI智能体会带来另一种形式的变异性。
同一个目标,不同的智能体可能会制定出不同的执行方案。
运行1:
扩展规模
进行部署
观察结果
运行2:
部署“探针”节点
观察数据
进一步扩张系统
运行3:
创建并行环境
调整流量分配
每种方案都可能是可行的,而且最初也可能都符合规范要求。
但长期来看,它们的运行结果可能会有所不同。
某种方案可能会让系统保持稳定状态,而另一种方案则可能导致系统逐渐趋向不良状态。
这种区分有助于我们更好地理解各种现象:
何时应采取行动应对漂移现象
并不是所有的漂移信号都意味着需要立即采取自动化的处理措施。
稳定状态
→ 不需采取任何行动
状况正在恶化但严重程度较低
→ 继续观察
状况持续恶化
→ 进行调查
出现违规行为且警告级别较高
→ 发出警报
出现违规行为且严重程度极高
→ 回滚操作/采取补救措施/向上级汇报
结果无法确定
→ 收集更多数据/阻止可能带来风险的自动化操作
具体的应对策略需要根据实际情况来决定。
例如,自动重启一个无状态服务可能是可行的,但自动回滚数据库迁移操作则可能不合适。
因此,漂移检测应该能够提供相关的数据和分类结果,而具体该采取什么行动则应由相应的规则或策略来决定。这样的安排有助于将观察、评估、决策和执行这些环节区分开来。
操作性漂移无法告诉你的信息
操作性漂移本身并不能自动说明系统变化的原因。
假设系统的延迟从280毫秒增加到了390毫秒,我们仍然无法仅凭这一数据就判断出系统变化的具体原因。
漂移检测能够告诉您以下信息:
系统性能正在下降
但它无法自动确定导致这种下降的原因。
造成性能下降的原因可能包括流量增加、数据库竞争、下游依赖问题、网络质量变差、代码出现回归问题,或是资源耗尽等等。
因此,漂移检测只是一种监测机制,并非根本原因分析工具。
基准数据也可能存在误差。
如果基准数据是在系统表现异常良好的时期获取的,那么系统的正常运行状态反而可能被误认为是性能下降。
所以,漂移检测的有效性取决于准确的规格设定、可靠的证据收集、合理的基准数据选择、恰当的观察窗口设置,以及正确的判断规则。
实用的漂移检测工作流程
如果您想将漂移检测机制应用到现有的系统中,我建议按照以下步骤进行操作。
1. 从符合规格要求的操作开始
选择那些您已经确认系统满足相关规格要求的操作来进行检测。
2. 保存基准数据
将反映系统处于良好运行状态时的各项数据保存下来。
3>识别易受漂移影响的约束条件
并非所有的约束条件都需要进行趋势分析。
优先关注以下这些指标:
延迟时间
错误率
处理能力
队列长度
可用性
证书有效期
备份数据更新频率
4>设定观察窗口
根据系统的实际运行情况来选择合适的观察窗口。
5>明确区分“稳定状态”“性能下降状态”“违规状态”及“未知状态”
需要将各种系统状态明确地划分出来。
6>设定严重性等级
要将普通性的性能变化与严重的故障区分开来。
7>考虑数据的持续性
避免因为某个异常数据样本就立即采取行动。
8>保存所有相关数据
将基准数据、当前系统状态、阈值、观察窗口信息以及时间戳全部保存下来。
9>区分检测过程与响应措施
不要让每一个漂移信号都会触发自动响应机制。
10>不断优化检测模型
如果系统经常产生误报,就需要调整判断规则;如果真的存在性能下降的情况,就需要检查数据收集方式或观察窗口设置是否合理。
不要仅仅通过提高阈值来让所有指标看起来都正常了事。
从阶段性合规性检测到持续性的验证机制
合规性检测能为我们提供以下信息:
规格要求
+
相关证据
↓
评估结果
↓
通过/失败/未知
而漂移检测则增加了时间维度:
规格要求
+
T0时刻的证据
+
T1时刻的证据
+
T2时刻的证据
↓
漂移情况评估
↓
稳定状态/性能下降状态/违规状态/未知状态
这改变了运营模式。
我们不再只关注以下两个问题:
操作是否成功?
或者:
系统现在是否符合规范要求?
我们还可以追问:
系统是否正在偏离预定的状态?
这种思考方式为运营控制提供了更坚实的基础,尤其是当系统变得越来越自主时。
结论
“运营符合性”能告诉我们,在某个特定时间点上,观察到的数据是否满足规范要求。
而“运营偏差”则能说明这种对应关系是否正在发生变化。
一个有效的偏差分析模型应当包含以下要素:
基准数据
当前数据
约束条件
观测窗口
变化方向
严重程度
持续时间
未知状态
时间戳
这些要素有助于我们区分暂时性的异常、持续的性能下降、实际的违规行为,以及缺失的数据。
执行者并不需要了解这些细节。执行者只需按照规范要求完成任务即可,而规范本身定义了系统的预期运行边界。
数据能够告诉我们系统当前的状态;符合性判断能帮助我们确定这种状态是否可接受;偏差分析则能揭示系统是否正在偏离这一可接受的状态。
至此,这些要素已经开始构成一个更为完整的运营模式:
预期目标
↓
规范要求
↓
执行者
↓
数据收集
↓>符合性判断
↓>偏差分析
↓>相应的应对措施
下一步就是将这些要素明确地结合起来,形成一个完整的运营体系。
正是在这个过程中,我提出了“规范驱动的运营”这一概念,将其视为一个完备的运营模型。
相关文章
智能代理的可靠性:为工具的使用、安全机制、循环流程以及工作流程的输出结果构建相应的测试框架 [完整书籍]
一个完美的最终结果并不能证明某个具有自主行为能力的人工智能系统的工作流程是正确的。 本书提出了一种基于代码的方法,用于验证系统执行过程及所产生的业务成果,并利用这些证据来决定是否允许该系统正式投入使用。 书中还提供了一个可运行的离线测试工具,用以演示各种核心技术。第19章专门区分了那些已经实现的功能与那些仍处于开发阶段、尚未投入实际应用的扩展功能。 目录 引言 第一部分:可靠性差距 第二部分:基础原理 第三部分:核心结论 第四部分:行为特征 第五部分:跨领域问题 第六部分:决策过程 第七部分:诚实性与普及度 结论 术语表 参考文献 生产就绪性检查清单 引言 那个“虚假的演示” 许多具有自主行为
阅读全文
“从设计层面确保安全性”:在编写任何代码之前,如何将安全机制纳入系统架构之中
在大多数工程团队中,都会进行这样的对话——不过往往为时已晚。 想象一下:某个功能被部署到生产环境中之后,才会进行安全审查;或者在进行渗透测试时发现了问题;更糟糕的是,还会收到事故报告。 这些漏洞确实是存在的,修复它们也需要投入大量成本。而在这些讨论中,总会有人说:“我们需要为这个功能添加安全措施。” 但这个问题就出在这里:安全并不是事后才添加到软件中的东西,而应该从项目一开始就被纳入设计之中。一旦开始考虑为已经存在的东西添加安全功能,那就意味着你已经进入了“事故应对模式”。 “安全驱动设计”是一种完全不同的思维方式——在制定架构决策之前,就应该明确安全要求;在编写任何代码之前,就必须了解潜在的
阅读全文
如何向英国税务海关总署的“数字化纳税”API提交季度更新报告
每年有四次,所有参与“税收数字化”计划的个体经营者和房东都必须向英国税务海关总署提交一份收入与支出的汇总报表。 2026-27纳税年度的第一个截止日期是8月7日,这个期限已经过去;第二个截止日期则是11月7日。每份汇总报表都需要通过软件向英国税务海关总署发送一次API请求,而本教程正是专门讲解如何正确完成这些请求操作的。 您无需事先阅读任何其他资料即可跟随本教程进行操作。每次进行“税收数字化”集成时所需的一次性设置信息(包括沙箱应用程序、OAuth 2.0访问令牌以及防欺诈相关配置)已在下方的简要总结中列出,同时每段代码示例中也都会使用到一些辅助函数。 如果您想深入了解这些设置步骤,我曾在 之
阅读全文
在你们解决数据问题之前,医疗领域的人工智能技术是无法正常运行的。
为临床环境开发人工智能其实比看起来要困难得多。这不仅仅意味着需要选择一个合适的模型或调整正确的参数。 当工程师们进入医院这个生态系统时,他们会很快发现:那些在其他行业中被他们广泛使用的工具,在这里往往无法正常使用。临床数据杂乱无章、极其敏感,而且分散在许多不同的系统中。妥善处理这些数据并非可有可无,而是整个系统能否正常运行的基础。 临床数据有多种形式。其中一部分是结构化的数据,比如存储在表格中的实验室检测结果;另一部分则是非结构化数据,比如医生手写的病历被扫描成PDF文件。所有这些数据都受到严格的隐私保护规定的约束,而且每一条数据都可能直接影响患者的诊疗效果。 与电子商务或广告领域不同,在这些
阅读全文