01项目概述
Kyndsy是一个移动应用程序,回答大多数人无法回答的关于自己的问题:我到底怎么说话?它在普通对话中监听主人的声音,统计粗略的词汇、礼貌用语、填充词以及语调变得尖锐的时刻。它显示出几天和几周的趋势。然后它停止——它不告诉这个人这使他们成为什么样的人。
前提是,自我提升应用程序大多绘制出你自己观点的图表。你报告你的一天,它们可视化报告。Kyndsy 从更难以争辩的地方开始:实际说出的话,在人忙于生活而不是坐下来反思时被统计。
这也是使产品变得困难的原因。计数言语意味着需要一个麦克风,而麦克风意味着这个人必须比信任手机上的几乎任何其他东西更信任这个应用程序。因此,整个产品围绕一个必须是结构性的承诺构建:声音从不被保存,文字从不被记录,其他人的声音不被分析,也没有任何账户与之关联.
我们设计并构建了整个系统:iOS 和 Android 的应用程序,三十种语言的内容,轻量级后端,商店发布路径和产品网站。以下是问题、决策以及我们故意拒绝构建的部分。
02背景和问题
一个倾听的应用程序是一个明显的实现方式也是错误的类别。拆解任务产生了一系列约束,塑造了之后的一切。
- 信任是产品。一个测量语音的应用程序只有一个资产,而这不是算法。如果一个人怀疑音频会离开手机,那么再高的准确性也无济于事——他们会卸载。
- 其他人没有同意。房间里的麦克风会拾取在场的任何人。分析周围的人的行为将是一个完全不同的应用程序,而且会糟糕得多。
- 关于一个人的数字是危险的。任何声称总结一个人的单一分数都是产品无法诚实做出的声明——人们会将其视为裁决,无论免责声明如何。
- 原始计数是谎言。“你今天发誓了九次”奖励沉默。一个什么都不说的人看起来像是一个有所改善的人。
- 语言是模糊的。同一个词根据语气和上下文可以是笑话、引用、自我指责或真正的侮辱。仅仅计算字符串会产生没有人认同的数字。
- 人们并不说一种语言。他们在句子中间切换。只跟随其中一种语言的计数器每次其拥有者切换语言时都会报告一个可疑的平静日。
- 商店有规则关于麦克风使用、关于健康和心理学声明,以及关于订阅可能限制的内容——这些规则在提交时执行,而不是在发布日。
所有这些都必须在手机上运行,在后台,不消耗电池或人的耐心。
03项目目标
- 在设备上测量语音。分析在手机上进行;音频从不存储,也从不上传。
- 只有主人的声音。其他声音会被丢弃而不是分析,并且没有将应用程序指向其他人的模式。
- 没有账户,没有名字。没有泄露的内容,因为没有收集到可以泄露的东西。
- 比率,而不是原始计数。每千个单词的统计,因此安静的一天就是安静的一天,而不是成就。
- 三十种语言,包括混合语言—— 字典必须同时存在于所有这些语言中,否则对于切换语言的人来说数量就是错误的。
- 区分色调。讽刺、挖苦、玩笑和真正的尖锐评论要区分开来,并标记为猜测,而不是裁决。
- 在没有麦克风的情况下也有用。日记、价值观指南、测试和晚间问题可以独立工作。
- 无法被操控的动机。通过测量而不是打开应用程序来评估运行、级别和程序。
- 没有个人的总体评分。在版本一中没有,之后也没有。
04我们做了什么
该应用程序分为四个部分,每个部分回答一个不同的问题,以及支撑它们的部分:
- 今天 — 刚刚发生了什么:演讲分数、当天的目标和一个单一建议,而不是六个建议的列表。
- 进展 — 是否有任何进展:运行、级别、程序和每周报告。
- 指南针 — 个人决定要追求的目标:他们自己选择的三到五个价值观,以及朝着这些目标的努力。
- 您 — 一切只属于他们的东西:自我检查测试、家庭访问、他们的数据和支持。
下面是使这四个诚实的组成部分:设备上的语音分析、三十种语言的词典和规则、阴影分类器、以速率而非总数工作的计数模型、几乎一无所知的轻量级后端,以及一个允许产品在没有商店发布的情况下进行更改的设置注册表。
05隐私作为代码,而非复制
网站上的隐私声明不是后期优化可能悄然失效的营销文案。它们是构建的属性,项目将使其中任何一个不真实的更改视为缺陷,而不是权衡。
- 声音没有写入任何地方 — 既不写入文件,也不写入磁盘上的临时缓冲区,也不写入日志。调试版本也没有,因为调试版本是这些东西逃逸的方式。
- 只有所有者的声音被分析。其他人的语音在变成单词之前就被丢弃了。
- 没有任何内容被转录。该应用程序生成计数器,而不是文本;没有存储的句子可以泄露、传唤或意外同步。
- 会话仅在某人启动时开始。重启后没有自动启动,也没有在后台静默恢复。
- 语音配置文件永远不会离开手机并且不包括在设备备份中——它是生物识别数据,而备份是人们忘记它可以移动的唯一地方。
- 后端被告知四件事,且不多:请求设置、一次性模型下载、如果有人写了支持消息,以及订阅收据。没有账户。
- 一个人是一对随机数字他们自己的手机组成。我们不发放它们,也不计算它们——这意味着我们不知道有多少安装,这是一种故意的代价。
- 登录是可选的,并不会解锁任何东西。它的存在是为了将订阅和历史记录转移到新手机。强制要求将会创建一个与真实身份的链接,而今天并不存在这样的链接。
最后一点值得深入探讨。所有者的要求是只知道一个匿名ID——而满足这一要求的诱人方式是强制登录,然后我们承诺不去读取。我们做了相反的事情:根本没有账户,且可选的登录仅从令牌中读取一个字段并将其存储为哈希值。
06应用实际计算的内容
四件事:粗鲁的表达、礼貌的表达、填充词和提高或尖锐的语调。所有这些都被报告每千个单词,从不作为原始总数——因为原始计数让沉默看起来像是进步,而一个奖励其拥有者不说话的应用程序误解了自己的工作。
今天的头条是一个尊重言语指数,而围绕它的规则与数字本身一样经过深思熟虑:
- 它在听到五十个单词之前完全隐藏。在听到五十个单词之前完全隐藏。在一个宁静的早晨,零分就像是一种指控,而不是缺失的数据。
- 少于五十个字的天数是显示但不计入—— 作为空白可见,而不是假装是美好的一天。
- 礼貌最多可以提升十分。再多的话,得分就会比通过礼貌来获得更便宜,而不是通过不尖锐来获得。
- 任何单一事件都可以被标记为错误,这样做会改变数字,而不仅仅是从列表中划掉一条。
此外,这些视图在形式上是普通的,在细节上是仔细的:七天的趋势、逐小时的日常图景、每一天一个方格的三十天网格。逐小时视图在有十个事件作为基础之前拒绝声明“最糟糕的时刻”;三十天网格将安静的日子保持为米色,而不是将其涂成平静。依赖薄弱数据的自信图表是测量产品失去读者信任的方式——通常是永久的。
07言语的色彩:讽刺、笑话、讽刺
笑话和侮辱不是同一个词两次。Kyndsy 将讽刺与真正的尖锐评论分开,将笑话与讽刺分开,将引用与某人所意图的内容分开——并在事件旁边展示它认为听到的内容。
有两个规则保持该功能的诚实。首先,它被呈现为一个猜测,而不是一个裁决:应用程序说“可能是讽刺”或“一个笑话——不计入”并展示其依据。其次,更重要的是,阴影分类从不移动指数。它通知个人;它不会默默地调整他们的分数。一个基于信心的加权数字对任何人来说都是不可能检查的,并且会悄悄地成为产品最具争议的特征。
同样的关注适用于上下文:当个人引用某人、谈论自己或在争论中时,同一个词的计数是不同的。并且因为没有字典能够知道特定个人的话对他们意味着什么,他们可以保留自己的列表。
08三十种语言 — 及其混合
该应用程序支持三十种语言——英语、西班牙语、葡萄牙语、德语、法语、意大利语、荷兰语、瑞典语、丹麦语、挪威语、芬兰语、波兰语、捷克语、克罗地亚语、罗马尼亚语、匈牙利语、希腊语、土耳其语、俄语、乌克兰语、白俄罗斯语、希伯来语、阿拉伯语、印地语、印尼语、越南语、泰语、中文、日语和韩语——并且可以同时使用其中几种,因为这正是许多人实际说话的方式。
三十种语言并不是三十种界面的翻译。它是三十组词典——粗略的表达、礼貌的公式、填充词——它们必须同时到位在同一时间。一个词典半成品的语言不会大声失败;它报告的是一个平静的日子。这个人看到一个好数字并相信它,这比错误信息更糟。
这个项目的一个教训很好地推广到更广泛的领域:从文本的形状检测到的特性在第一种书写方式不同的语言中会崩溃。将“一个短语”视为“一个包含空格的字符串”在日语、中文和泰语中是有效的,因为它们是没有空格的——而在这里,应用程序完全找不到任何东西,默默地看起来像是在工作。语言行为必须来自语言自身的数据,并且必须通过一个跨越所有三十种语言的测试来覆盖。
09指南针和日记
语言只是产品的一半。另一半是这个人决定要瞄准的目标:他们从七个价值观中选择三到五个——尊重、诚实、自我控制、责任、关心、公平、可靠——应用程序显示朝着这些,而不是朝着别人对好人的想法。
运动来源于两个方面:语音测量和个人的日记——遵守承诺、道歉、对某人发火、修复损害。一天结束时,他们想要的三个问题。
而且有没有整体道德分数,现在或以后。这是产品拒绝计算的唯一事情。这也是指南针有效的原因:一个人只会为一个不会根据结果给他们评分的应用选择诚实的价值观。
这一部分的所有内容都不需要麦克风。日记、指南针、测试和晚间问题各自独立,因此一个人可以稍后设置语音部分,或者根本不设置,仍然能从应用中获得一些东西。这是一个对用户留存有实际影响的产品决策,我们会再次做出这个决定——在第一个屏幕上的权限提示是一个隐私敏感应用失去其构建目标用户的地方。
10程序、运行和每周报告
这个应用中的动机必须免受两种常见作弊手段的影响:频繁打开应用和不说话。所以:
- 程序连续7到30天,目标只有一个和一个数字——七天不说粗话,接下来两周说更温和的回答,一个月内减少填充词。是否有效由测量结果决定,而不是打勾。
- 一次运行计算个人实际保持该水平的天数。静默的日子既不会打破它也不会延长它——放下手机并不是获胜的方法。
- 等级是通过天数获得的,而不是通过应用打开次数:观看、控制、平静的言语。
- 保护罩在一定程度上可以掩盖失误,破损的一天可以被买回——但连续三十天中有四天被买回的情况并不算作三十天的连续,因此这些天会被单独计算和显示。
- 每周报告清楚地说明何时没有足够的比较。一个总结,其中某些东西总是有所改善,在第三周停止被阅读。
一个值得提及的故意不对称是:免费层限制了历史的多少,已显示而不是限制了多少被计算。仅在可见窗口内计算一次运行将显示三十天的运行为七天——这不是免费计划的限制,而是对个人的错误陈述。
11一百个自我检查测试
在测量旁边有一百个结构化的自我检查测试:每个测试有二十五个陈述,约四分钟,分别在五个方面打分,因此答案从来不是一个平坦的数字。它们涵盖了语言、情感、亲近的人、工作、自己、习惯和在线生活。
它们明确地不是诊断,也不是人格测量——它们是结构化的自我反思,应用程序在用户会阅读的地方而不是设置屏幕中说明这一点。答案像其他所有内容一样保留在手机上。
这里的工程要点是,无法将一百个测试维护为一百个手写屏幕。它们是一个资源,而不是代码:从源生成,在构建时验证,如果测试没有完整的语句和方面集则拒绝。这个检查使得能够拥有一百个测试成为可能,这也是它们的解锁规则能够一致分发而不是手动分散的原因。
一半通过使用解锁,一半通过购买。付费部分背后的商店产品故意很少,而不是每个测试一个 — 没有人会手动创建一百个商店列表,也没有人会将其中一百个翻译成三十种语言。出售的产品是一个解锁;购买确认后,用户可以在应用内选择将其花费在哪个测试上。
12订阅、家庭和商店
付费层是一个订阅,家庭计划共享它 — 六个位置为期一年,包括购买者的。重要的是家庭共享的内容和不共享的内容:家庭共享权利,而不是数据没有人能看到其他人的数字、事件或日记,付款的人只能看到空位和日期,而不是谁在其中。
这不是小字中的一行;这就是它的构建方式。其他人的测量数据根本不在服务器上,因此在家庭屏幕中没有任何东西会意外暴露。输入代码意味着同意共享订阅,而不是同意被识别。
这一部分的两个实施规则超越了功能。首先,订阅和家庭权利是应用中的一个标志:形式为“或者他们可能在一个家庭中”的第二个问题将在确实重要的地方被遗忘。其次,服务器的沉默并不撤销权利——网络掉线的频率远高于订阅结束的频率,而在火车上锁定付费客户的应用做出了明显的错误选择。
商店政策在这里塑造了很多表面:麦克风应用可以声称的内容,付费层的呈现方式,以及无法通过热修复撤回的破损版本。这就是为什么版本政策——最低支持版本、强制更新、维护模式和显示的消息,所有项目语言同时显示——是服务器端设置,而不是编译在内的内容。
13架构:应用程序、后端、注册表
架构遵循隐私承诺:尽可能多地在手机上,尽可能少地在服务器上。
- 应用程序进行分析,保存历史记录并拥有语音配置文件。它是整个产品;服务器是支持角色。
- 轻量级后端处理四种请求——设置、一次性模型下载、支持消息和订阅收据。它没有用户表,因为没有用户可以放入其中。
- 配置注册表保存本应硬编码在应用程序中的内容:包标识符、API 地址、登录参数、语言列表、功能标志和版本策略。值是生成到源代码中而不是手动输入的,并且生成的文件被标记为不可编辑,原因很简单,因为手动编辑在下次生成时会丢失。
- 预检在每次构建时进行检查:如果包标识符与注册表不一致、版本不高于上一个发布版本、应用程序的服务器没有响应、项目的任何语言字典不完整、静态分析不干净、测试失败,或者在源代码中发现任何类似密钥的内容,它将拒绝构建。它返回一个非零退出代码,这使得它可以作为任何 CI 中的门控。
- 付费层在一个标志后面可以在不重建和不需要新商店版本的情况下关闭。
该网站是一个小型PHP应用程序,除了支持通信外没有自己的数据库——同样的原则适用于一个层级之外。
14技术栈
- Flutter从一个代码库为iOS和Android提供支持——设计系统在代码中,因此颜色、间距和半径在一个地方声明,而不是在每个小部件中。
- 设备上的语音识别和设备上的分析:模型一次下载并在本地运行,清单描述是从文件构建的,而不是手动编写的。
- PHP 8.4作为应用程序后端和网站的支持,只有一个小数据库用于支持通信。
- 配置注册表作为应用程序设置的真实来源,带有生成的代码和预检门。
- 三十个语言包用于应用程序,三个用于网站,通过测试而不是审查来强制字典一致性。
- 严格的内容安全政策在网站上——完全没有内联样式,计算值编译到样式表中,并且使用自托管字体,因此关于隐私的页面不会获取任何第三方资源。
15设计和用户体验
视觉语言是一个深色主题,取自产品网站,以便访客所承诺的内容与他们打开的内容一致。第二个浅色主题被写入了令牌中,但故意没有发布:两个主题意味着两组截图,以及两倍的布局在不被注意的情况下破裂的地方。
颜色、间距和半径都在一个设计文件中,令人不安的颜色与平静颜色之间的过渡是通过温暖的黄色——直接插值会得到一种橄榄泥,这种颜色看起来像是粗心大意,实际上是一个缺失的中途点。
这个应用有一个角色,围绕它的规则与诚实一样重要,和魅力一样:情绪可以从轮廓中读取,不仅仅是从颜色,因此色盲的人看到的和其他人一样;情绪是一个在值之间动画的连续尺度,而不是五个固定的图片,因为跳跃被视为不同的图片而不是同一个朋友;在焦虑的极端,眉毛在内侧翘起,因为向下和向内是愤怒在看的人。
在其他地方,界面遵循产品的核心规则:展示所测量的内容,说明何时没有足够的信息可以说,并且绝不要将一个人简化为一个单一的数字。
16我们的工作方式
- 首先是承诺。我们在设计任何东西之前写下了应用绝不会做的事情——保留音频、分析其他人、询问你是谁、给你打分——因为这些决定限制了架构,而不是从中衍生出来。
- 测量核心。设备内分析,速率中的计数模型,带有阈值的指数及其在薄数据上拒绝出现。
- 语言工作。三十本字典和规则,通过测试同时强制执行一致性。
- 另一半。指南针、日记、程序、运行、周报——所有不需要麦克风的工作。
- 作为资源的测试。生成和验证的一百个自检测试,其解锁梯子由生成器分发。
- 货币化。订阅、家庭、小型商店产品集,以及一个隐藏在标志后的付费层。
- 发布路径。注册、生成的配置、预飞行门、构建注册和版本策略。
- 该网站。三种语言、严格的内容安全政策和展示应用真实界面的着陆页。
在构建过程中,有两件事不断出现,现在都成为了规则。界面对一个人行为的任何声明都必须能够通过测量进行验证,而应用对隐私的任何承诺都必须由代码强制执行,而不是通过文档中的注释来实现——共享理解的存在恰好持续到下一个没有阅读它的人。
17结果
最终推出的是一种测量产品,用于人们通常只能猜测的事物,构建方式使得测量不会侵犯他们的隐私。
- 设备上的语音分析:不记录,不转录,其他声音被忽略。
- 每千字报告一次,因此沉默不会被误认为是进展。
- 讽刺、挖苦和开玩笑 — 并标记为一个永远不会改变分数的猜测。
- 三十种语言的词典齐聚一堂,经过所有语言的测试覆盖。
- 一个价值观指南针,一个日记,程序和一个每周报告,承认当它的比较数据太少时。
- 一百个自我检查测试作为经过验证的资源,后面有一小套可维护的商店产品,属于付费部分。
- 一个家庭计划,分享订阅而无其他,因为数据不在服务器上共享。
18要点
Kyndsy是一个项目,其中最困难的工程在于限制。设备上的分析,没有转录,没有账户,没有总体分数,没有分析旁观者 — 这些都使构建变得更加困难,但也使产品成为可能。这个应用的一个版本如果有服务器端管道和登录功能,会更快编写,但不值得任何人的麦克风。
我们前进的教训是关于如何履行承诺:一个存在于文档中的保证是一个保证,直到下一个没有人检查的更改。这里所持有的那些是以代码形式表达并通过测试覆盖的——在三十种语言之间的对等性,以数字而不是通过观察进行对比,以数值而不是通过截图来验证运动,一个拒绝而不是警告的构建门。
如果您正在构建一个以隐私为特征而非免责声明的移动产品,必须同时在多种语言中工作,或者是一个人们应该信任其数字的应用程序,这就是我们将想法转化为商店的工作。



