65.9K
CodeProject 正在变化。 阅读更多。
Home

实时检测社交新闻帖子中的暴力威胁

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.64/5 (4投票s)

2019 年 10 月 14 日

CPOL

10分钟阅读

viewsIcon

14944

NewsAlpha 是一个运行在 Microsoft Azure 上的社交新闻分析器,它聚合和分析来自不同互联网论坛和社交媒体网站的社交新闻帖子,以近乎实时的方式寻找暴力或自残的威胁。

背景

在发生大规模枪击事件后,据称肇事者 可能在 8chan 和 4chan 等互联网论坛或 Twitter 等社交媒体网站上发布了他们的宣言或意图。这导致了对能够通过社交媒体信号监控和检测潜在威胁的技术的需求增加。7 月份,FBI 发布了一份 RFP,寻求能够 执行 这些功能的 工具

引用

FBI 发布了一份 征求建议书,寻求一种基于订阅的社交媒体警报工具,该工具将筛选和评估来自 Twitter、Facebook、Instagram 和其他社交媒体平台的宏观数据,同时确保隐私和公民自由合规要求得到满足。它需要一个 Web 系统——也可以通过移动应用程序访问——该系统能够识别潜在威胁,并通过警报、分析和地理定位服务,在近乎实时地协助完成当前任务。

引用

该机构在 RFP 中表示:“随着 FBI 当前调查的对象和对美国构成威胁的个人越来越多地使用社交媒体平台,获取一项能够及时让 FBI 从 Twitter、Facebook、Instagram 和其他社交媒体平台中识别相关信息的服务至关重要。” “因此,FBI 需要近乎实时地访问全范围的社交媒体交流,以便在其执法和情报任务中获得可用的最新信息。”

与技术挑战分开,这项技术对许多人来说,其伦理道德是可疑的。最近,一位开源 Chef 开发者在发现 Chef Software 公司与 ICE 有合同后,从 GitHub 上撤回了他的源代码,该公司表示,由于其开发者对该机构所采取行动的道德性的看法,将不再续签此类合同。现在,开源开发者之间正在就与他们认为令人反感的政府机构合作的公司,以及使用软件进行人脸识别和其他形式的数字监控和监视的道德问题进行广泛讨论。

但就像我其他的 项目一样,我自己的观点是,实用主义是更好的方法。有如此多的商业实体拥有资金和资源来构建这些闭源通信监控系统,以至于不清楚暂停开发这些系统会产生什么积极影响。这些问题在技术角度来看非常有趣,需要从机器学习和自然语言处理到数据库和云系统设计的各种技能和知识。免费或开源软件允许其他人研究其工作原理,从而解决安全或伦理问题。自由软件意味着在自由软件许可证的条款下,无论您自己的政治或伦理信念如何,都可以让其他人自由地研究和使用您创造的东西。

设计

Canaan(计算机辅助新闻聚合与分析)是一个正在开发的开源 .NET 框架,用于聚合和分析社交和传统新闻。Canaan 允许您构建管道,从不同来源聚合和提取新闻帖子和文章,应用文本分析、自然语言和机器学习处理到新闻内容,并将生成的工件存储在不同类型的本地和云存储中。

NewsAlpha 被实现为一组 Canaan 管道,它们聚合来自社交媒体网站的新闻帖子,应用 NLU 任务,如意图和实体识别,然后将结果存储在 CosmosDB 数据库中。使用 Azure LUIS 训练 NLU 模型,以识别构成伤害他人或自身意图的陈述,并附加一个衡量威胁意图的数字置信度分数以及其他注解到每个帖子。

然后使用 Azure Search 为结果创建全文索引。然后,NewsAlpha 前端——无论是 CLI 还是未来的 Web 界面——都可以查询此索引,允许操作员快速搜索数百万条社交新闻帖子和注解。聚合器和索引器频繁运行——通常每五分钟一次——允许在社交新闻帖子发布后不久对其进行分析和查询。

Using the CLI to search posts related to the Oct. 9th shooting

NewsAlpha 目前聚合来自 4Chan 的 /pol/ 论坛和 Gab 微型博客网站的帖子。未来将添加更多用于 Reddit 和 Twitter 等论坛的聚合器。

实现

Components

每个 Canaan 组件都只是一个继承自基类 Api 的类 。基类提供了常见的函数,如日志记录、计时和配置管理,以及诸如初始化和调用远程服务(如 Azure 存储)等常见模式。基类 API 的设计目的是消除样板代码,以便每个组件的代码都可以尽可能轻松清晰地编写,例如 CosmosDB 存储 组件 的构造函数是

public CosmosDB(string endpointUrl, string authKey, 
                string databaseId, CancellationToken ct) : base(ct)
        {
            EndpointUrl = endpointUrl;
            AuthKey = authKey;
            Client = new CosmosClient(EndpointUrl, AuthKey,
                new CosmosClientOptions()
                {
                    ApplicationName = "Canaan",
                    ConnectionMode = ConnectionMode.Direct,
                    MaxRetryAttemptsOnRateLimitedRequests = 30,
                    MaxRetryWaitTimeOnRateLimitedRequests = TimeSpan.FromSeconds(30),
                    ConsistencyLevel = ConsistencyLevel.Session});
            DatabaseId = databaseId;
            Info("Created client for CosmosDB database {0} at {1}.", 
                                     DatabaseId, Client.Endpoint);
            Initialized = true;
        }

public CosmosDB(string databaseId, CancellationToken ct) : 
    this(Config("CosmosDB:EndpointUrl"), Config("CosmosDB:AuthKey"), databaseId, ct) {}

CosmosD 数据库检索项目的调用看起来像

public async Task<T> GetAsync<T>(string containerId, string partitionKey, string itemId) 
        {
            ThrowIfNotInitialized();
            var container = Client.GetContainer(DatabaseId, containerId);
            var r =  await container.ReadItemAsync<T>
            (itemId, new PartitionKey(partitionKey), cancellationToken: CancellationToken);
            return r.Resource;            
        }

异常处理策略是,所有异常都允许从低级组件冒泡到管道,管道是最高级的 Canaan 组件,也是应用程序逻辑可以做出正确决策的地方,关于操作错误以及如何处理它们。这使得 Canaan 组件的编写可以最大限度地减少 try/catch 处理程序,并使代码更易于编写和阅读。

Newsalpha 使用的 Canaan 组件可分为以下几类

  • 聚合器
  • 提取器
  • 分析器
  • 存储
  • 管道

聚合器

聚合器从论坛和社交媒体网站摄取社交新闻帖子。通常(但不总是),社交新闻帖子可以从网站自己的 JSON API 或通过 RSS 或 Atom XML feed 获取。对于 4chan 聚合器,我们可以使用其 JSON API 来检索特定版块上发布的帖子和主题。例如,获取特定论坛版块当前主题列表的 JSON 代码如下所示:

        public async Task<IEnumerable<NewsThread>> GetThreads(string board)
        {
            using (var op = Begin("Get threads for board {0}", board))
            {
                var r = await HttpClient.GetAsync($"http://a.4cdn.org/{board}/threads.json", 
                                                  CancellationToken);
                r.EnsureSuccessStatusCode();
                var json = await r.Content.ReadAsStringAsync();
                var pages = JArray.Parse(json);
                var threads = new List<NewsThread>();
                foreach (dynamic page in pages)
                {
                    int p = 1;
                    foreach (dynamic thread in page.threads)
                    {
                        var t = new NewsThread()
                        {
                            Source = "4ch.pol",
                            No = thread.no,
                            Id = ((string)thread.no) + "-" + YY,
                            Position = p++,
                            LastModified = DateTimeOffset.FromUnixTimeSeconds
                                           ((long)thread.last_modified).UtcDateTime,
                            ReplyCount = thread.replies
                        };
                        threads.Add(t);
                    }
                }
                op.Complete();
                return threads;
            }
        }

由于帖子通常以 HTML 格式返回,聚合器依赖其他 Canaan 组件来提取可用于分析和存储的文本或其他内容。

提取器

提取器 从 HTML 内容中提取文本、图像、链接和其他内容,例如,WebScraper 类具有以下方法,使用 CsQuery HTML 选择器库从 HTML 片段中提取链接

        public static Link[] ExtractLinksFromHtmlFrag(string html)
        {
            CQ dom = html;
            var links = dom["a"];
            if (links != null && links.Count() > 0)
            {
                return links.Select(l => new Link()
                {
                    Uri = l.HasAttribute("href") && Uri.TryCreate
                    (l.GetAttribute("href"), UriKind.RelativeOrAbsolute, out Uri u) ? u : null,
                    HtmlAttributes = l.Attributes.ToDictionary(a => a.Key, a => a.Value),
                    InnerHtml = l.InnerHTML,
                    InnerText = l.InnerText
                }).ToArray();

            }
            else
            {
                return Array.Empty<Link>();
            }
        }

从社交新闻帖子中提取的文本和链接将由分析器组件进行处理和丰富。未来将添加图像和 PDF 等文档的提取器。

分析器

分析器执行诸如语义标记、实体提取、意图检测、情感分析以及社交新闻帖子文本的其他 NLP 和 NLU 活动。NewsAlpha 目前使用 Azure 的 语言理解 (LUIS) 服务

使用 LUIS Web 界面,通过可能表明威胁的句子(以及可能不表明威胁的句子)来训练 NLU 模型。该模型还可以识别日期和地理位置等实体。该模型通过 HTTP 端点可用,可以通过 Azure LUIS SDK 访问,例如 AzureLUIS 类的构造函数如下所示:

       public AzureLUIS(string endpointUrl, string authKey, 
                        string appId, CancellationToken ct) : base(ct)
        {
            EndpointUrl = endpointUrl ?? throw new ArgumentNullException("endpointUrl");
            AuthKey = authKey ?? throw new ArgumentNullException("authKey");
            AppId = appId ?? throw new ArgumentNullException("appId");
            var credentials = new ApiKeyServiceClientCredentials(authKey);
            Client = new LUISRuntimeClient(credentials, 
                         new System.Net.Http.DelegatingHandler[] { });
            Client.Endpoint = EndpointUrl;
            AppId = appId;
            Initialized = true;
        }

并应用于每个社交新闻帖子的文本

        public async Task<Post> GetPredictionForPost(Post post)
        {
            var prediction = new Prediction(Client);
            var query = post.Text.Length <= 500 ? post.Text : post.Text.Substring(0, 500);
            var result = await prediction.ResolveAsync(AppId, query);
            var results = new Dictionary<string, object>();
            List<string> entities = new List<string>();
            foreach(var e in result.Entities)
            {
                entities.Add(e.Entity);
            }
            post.Entities = entities;
            if (result.TopScoringIntent != null && 
                result.TopScoringIntent.Intent.ToLower() == "threat")
            {
                post.ThreatIntent = result.TopScoringIntent.Score.Value;
            }
            return post;
        }

对于意图为“威胁”的帖子,其得分高于“无”得分,则将意图得分作为注解或附加属性添加到该帖子中。

LUIS 是一个“无代码”NLU 服务,与 IBM Watson 和 AI.ai 等其他在线和离线 NLU 服务相比,其准确性被评为最高。虽然您无法使用代码创建和调整模型,但 luis.au Web 控制台提供了训练模型所需的一切,包括无需额外训练的预构建实体。

LUIS 的最佳功能之一是能够实时使用 HTTP 端点接收到的发音来训练您的模型。LUIS 允许您在不中断服务的情况下更新、重新训练和部署模型。但尽管其准确性和灵活性,LUIS 的主要缺点是成本。对于 NewsAlpha 这种每分钟需要分析数百个发音的规模,使用 LUIS 会变得昂贵。未来的开发将着眼于使用 SnipsNLU 等离线 NLU 库来执行实体和意图提取任务。

存储

存储组件使用不同类型的数据库和其他存储来存储和检索新闻内容、元数据和注解。 CosmosDB 存储组件使用 Azure CosmosDB 云数据库 SDK 来创建和检索实体,例如,从 CosmosDb 容器检索一组实体的函数如下所示:

        public async Task<IEnumerable<T>> GetAsync<T>(string containerId, string partitionKey,
                              string query, Dictionary<string, object> parameters)
        {
            ThrowIfNotInitialized();
            var container = Client.GetContainer(DatabaseId, containerId);
            QueryDefinition q = new QueryDefinition(query);
            if (parameters != null)
            {
                for (int i = 0; i < parameters.Count; i++)
                {
                    q = q.WithParameter(parameters.Keys.ElementAt(i), 
                                        parameters.Values.ElementAt(i));
                }
            }
            var r = container.GetItemQueryIterator<T>(q,
                requestOptions: new QueryRequestOptions()
                {
                    PartitionKey = new PartitionKey(partitionKey)
                });
            var items = new List<T>();
            while (r.HasMoreResults)
            {
                var itemr = await r.ReadNextAsync(CancellationToken);
                items.AddRange(itemr.Resource);
            }
            return items;
        }

NewsAlpha 使用 CosmosDB 来存储社交新闻帖子和主题及其由分析器添加的相关元数据和注解,例如,在 Media Matters 文章中提到的 4chan 主题以 JSON 文档的形式存储在 socialnews 数据库的 threads 容器中。

socialnews CosmosDB 数据库目前约有 200 万条社交新闻帖子,并以低成本提供良好的查询性能。未来将添加其他数据库存储组件,如 SQL Server 和 Sqlite。

索引

存储在 CosmosDB 中的社交新闻帖子及其注解通过 Azure Search 服务进行索引。

Azure Search 主要提供开源 Lucene 全文搜索服务器的 Web 界面。使用 Search 界面,您可以指定要索引的数据源字段

目前,我们在 4Chan 索引中约有 150 万条帖子,可追溯到 9 月 7 日左右。NewsAlpha 搜索索引允许用户对这些帖子运行复杂的查询和过滤器,响应时间非常快。

管道

一个 管道 是 Canaan 组件的高级别连接。例如,FourChanAzure 管道使用 FourChan 聚合器摄取给定 4Chan 版块的主题和帖子,从 AzureLUIS 分析器添加实体和威胁意图的注解,然后将数据存储在 socialnews CosmosDB 数据库中,该数据库将被 Azure Search 索引,然后可以通过 NewsAlpha CLI 进行搜索。GabAzure 管道为 Gab 帖子执行相同操作。GabAzure 管道的 Update 方法如下所示:

        public async Task Update()
        {
            ThrowIfNotInitialized();
            Info("Listening to Gab live stream for 100 seconds.");
            var posts = await Aggregator.GetUpdates(100);
            if (!string.IsNullOrEmpty(Config("CognitiveServices:EnableNLU")))
            {
                using (var op = Begin("Get intents for {0} posts from Azure LUIS", 
                                       posts.Count()))
                {
                    foreach (var post in posts)
                    {
                        await NLU.GetPredictionForPost(post);
                        if (post.Entities.Count > 0)
                        {
                            Info("Detected {0} entities in post {1}.", 
                                  post.Entities.Count, post.Id);
                        }
                        if (post.ThreatIntent > 0.0)
                        {
                            Info("Detected threat intent {0:0.00} in post {1}.", 
                                  post.ThreatIntent, post.Id);
                        }
                    }
                    op.Complete();
                }
            }

            using (var op = Begin("Insert {0} posts into container {1} in database {2}", 
                   posts.Count(), "posts", "socialnews"))
            {
                foreach (var b in posts.Batch(4))
                {
                    await Task.WhenAll(b.Select(p => Db.CreateAsync("posts", "gab", p)));
                }
                op.Complete();
            }
        }

NewsAlpha 的聚合器作为计划的 Azure Functions 运行,这意味着它们根据预设的时间表(例如每 5 分钟)触发,而不是由 HTTP 请求触发。使用 Azure Functions 消除了对 ASP.NET Core 等后端框架的需求,并极大地简化了聚合器的实现和测试。

日志记录

日志记录是云应用程序的关键部分,也是监控远程基础设施上运行的服务唯一的方式。Canaan 具有专用的日志记录组件,NewsAlpha 聚合器依赖 Azure Functions 的日志记录基础设施。我们可以使用 Canaan 的 Serilog 日志记录器组件,并配置 Serilog 事件接收器将日志写入每个 Azure Function 可用的 TraceWriter

            Serilog.Core.Logger logger = new LoggerConfiguration()
            .WriteTo.Console(Serilog.Events.LogEventLevel.Debug)
            .MinimumLevel.Debug()
            .Enrich.FromLogContext()
            .WriteTo.TraceWriter(log)
            .CreateLogger();
            Api.SetLogger(new SerilogLogger(logger));

通过此配置,NewsAlpha 的聚合器将使用 Azure Functions 日志记录基础设施记录所有事件。

接口

NewsAlpha 目前有一个 CLI 界面,可以从 GitHub 仓库的 发布页面下载。

尽管 CLI 比 Web 界面更快、响应更灵敏,但为了更广泛的受众,将开发一个 Web 界面来查询 NewsAlpha 索引。

性能

索引本身的性能很好,因为查询 100 万多条 4Chan 帖子的索引只需几秒钟,当索引服务器预热时甚至更快。

但正如演示视频所示,由于缺乏训练示例以及论坛上人们言论的广泛差异,该模型目前在检测实际威胁方面效果不佳。NLU 模型通常需要数百个或更多的示例才能获得良好的性能,尤其是在如此广泛的陈述中。

结论

NewsAlpha 仍处于开发 Alpha 阶段,但前端和后端都可以运行并投入使用,我相信基本设计是可靠的。目前最大的需求是使用离线 NLU 框架进行威胁意图检测,因为我负担不起运行 LUIS 服务超过几天。我计划继续对 NewsAlpha 和 Canaan 进行开发,并将其扩展到索引 Reddit 的 /The_Donald/ 和 Twitter 等其他论坛和社交媒体网站。

历史

  • 初稿提交
  • 修正了拼写错误
  • 更新了内容
  • 格式修复和拼写错误
© . All rights reserved.