演练:使用VB开发多智能体协作的荣格八维分析器
在大语言模型高速发展的时代,我们面对困难的语义分析任务,通过构建智能体进行处理是一个流行趋势。本文将介绍如何使用 Visual Basic .NET 开发一个多智能体协作系统,用于分析聊天记录中特定人物的荣格八维人格类型。
本文使用 CC-BY-NC-SA 4.0 协议。转载或者 AI 模型/智能体使用请注明出处并标注作者 Nukepayload2。
背景知识
什么是荣格八维?
荣格八维理论是心理学家卡尔·荣格提出的认知功能理论,后发展为多个分支,其中人气较高的是 MBTI。该理论认为人的认知功能可以分为八种,在不同的位置中担任不同的原型。这些功能随着人的成长而发展,并且具有先天性。
本文的软件工具分析的是什么?
工具分析的是对话中的人使用的人格面具。由于人的八个认知功能担任的原型是先天确定的,为了适应环境,人们会发展并使用人格面具。以树作为比喻,如果先天确定的功能偏好是树根,那么人格面具就是顶部的树枝和树叶。在对话中,人格面具以及其中的气质能被 AI 捕捉到,作为输入进行相应的分析。
智能体协作的意义
在荣格八维分析任务中,单一智能体往往难以处理所有方面。通过多个专门化智能体协作,我们可以:
- 提高分析准确性
- 并行处理不同维度的信息
- 更好地控制分析流程
- 精准提供实时反馈
- 避免超长的提示词导致推理费用失控
需求分析
目标用户场景
想象你是一个心理学研究者,需要分析一段多人对话记录中特定人物的人格特征(使用了怎样的人格面具)。你希望系统能够:
- 从聊天记录中识别目标人物的发言
- 分析该人物在八维功能上的倾向性
- 确定各功能在人格中的可能位置
- 生成详细的分析报告
- 允许在分析过程中提供补充信息
- 实时查看分析过程
核心功能需求
- 聊天记录分析 - 能够解析多人对话记录
- 多维度评估 - 并行分析八种认知功能
- 流程控制 - 按照预定义顺序执行分析步骤
- 实时反馈 - 显示分析过程和中间结果
- 交互式答疑 - 分析完成后回答用户问题
- 中断处理 - 允许用户在分析过程中插入信息
系统架构设计
整体架构
系统采用主从式智能体架构:
主智能体
├── 八维得分分析器 (8个子智能体)
├── 八维位置分析器
├── 报告生成器
└── 共享工具系统
├── 笔记管理工具
├── 待办事项工具
└── 分析工具
数据流设计
- 输入阶段:用户提交聊天记录和目标人物
- 分析阶段:并行调用八个子智能体分析各维度
- 整合阶段:综合分析结果确定功能位置
- 输出阶段:生成报告并进入答疑模式
状态管理
系统的智能体是无状态的,它们通过共享上下文(MbtiAnalysisContext)传递信息。
Public Class MbtiAnalysisContext
Public Property Note As New ConcurrentDictionary(Of String, String)
Public Property TodoList As New List(Of TodoItem)
' 其它内容省略
End Class
开发工具选择
既然是自己做研究,就选自己最擅长的,最大化研究效率。
- VB 17.13(最新的 .NET SDK 9.x 自带)
- Avalonia UI(使用 Nukepayload2.SourceGenerators.AvaloniaUI 提供设计时支持)
- 一些 AI 辅助编程插件
关键技术实现
1. 工作流控制
在智能体的用户界面加载时,初始化分析器上下文并启动主循环。通过一个无限循环,系统持续运行分析任务,直到用户取消操作。当发生取消操作时,系统会根据情况重置分析器或设置中断请求标志。
Private Async Sub MbtiStatelessAnalyzerView_Loaded() Handles Me.Loaded
' 设计时和重入处理(省略)
' 启动分析器
_analyzer.ResetContext()
Do
Try
Await _analyzer.RunAnalysisLoopAsync(_cancelSrc.Token)
Catch ex As OperationCanceledException When ex.CancellationToken = _cancelSrc.Token
' 省略取消处理
End Try
Loop
End Sub
智能体内采用项目管理的方式来追踪待办事项。为了确保分析按正确顺序进行,硬编码待办事项列表。
' 被 ResetContext 调用
Private Sub InitializeTodoList()
With _context.TodoList
.Add(New TodoItem("1", "收集聊天记录和目标用户", "..."))
.Add(New TodoItem("2", "八维分数统计", "..."))
.Add(New TodoItem("3", "八维位置的可能性", "..."))
.Add(New TodoItem("4", "产生报告", "..."))
End With
End Sub
主循环会按顺序处理这些任务:
Public Async Function RunAnalysisLoopAsync(cancellationToken As CancellationToken) As Task
Dim result As String
Do
result = Await ProcessMessageAsync(cancellationToken)
If result <> Nothing Then
_chatHistoryItems.Add(MessageHistoryItem.CreateBotMessage(result))
End If
Loop Until cancellationToken.IsCancellationRequested
End Function
核心的任务处理逻辑在ProcessMessageAsync方法中实现:
Private Async Function ProcessMessageAsync(cancellationToken As CancellationToken) As Task(Of String)
' 查找第一个未完成的任务
Dim currentTask As TodoItem = _context.TodoList.FirstOrDefault(Function(it) Not it.IsCompleted) ' 处理任务
If currentTask IsNot Nothing Then
' 处理用户中断插嘴(简化)
' ... ' 根据任务类型调用相应的处理方法(简化)
Select Case currentTask.Title
Case "收集聊天记录和目标用户"
Return Await CollectChatRecordsAndTargetAsync(cancellationToken)
Case "八维分数统计"
Return Await ProcessFunctionScoresAsync(cancellationToken)
Case "八维位置的可能性"
Return Await ProcessFunctionPositionsAsync(cancellationToken)
Case "产生报告"
Return Await ProcessGenerateReportAsync(cancellationToken)
Case Else
Return "错误:未知任务 " & currentTask.Title
End Select
' 清理用户中断插嘴(简化)
' ...
Else
' 所有任务都已完成,进入答疑状态
Return Await AnswerQuestionsAsync(cancellationToken)
End If
End Function
子任务处理函数包括:
CollectChatRecordsAndTargetAsync:负责收集用户提供的聊天记录和目标分析对象ProcessFunctionScoresAsync:调用八个并行的子智能体计算目标人物在八维功能上的得分ProcessFunctionPositionsAsync:分析各功能在人格中的可能位置ProcessGenerateReportAsync:综合所有分析结果生成最终报告AnswerQuestionsAsync:所有分析任务完成后,进入交互式答疑模式
这些函数会根据任务类型调用相应的工具(主要是查看笔记、调用子智能体和记录笔记),然后标记任务完成并返回结果。
2. 实时推理显示
系统通过数据绑定和事件处理机制实现实时更新。例如,在XAML视图中定义日志显示区域:
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:MbtiAnalysisLogItem">
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Padding="4">
<Expander IsExpanded="True" HorizontalAlignment="Stretch">
<Expander.Header>
<TextBlock Text="{Binding StepName}" FontWeight="Bold" Foreground="Blue"/>
</Expander.Header>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="0,2,0,0"/>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
用了数据绑定,智能体只要修改集合和属性,UI 就能自动更新。
Await My.AI.Chat.ChatAsyncWithRetry(chatHistory,
Sub(response)
responseBuilder.Append(response)
' 更新消息内容,这会让绑定了属性的控件显示最新的数据
botMessage.Text = responseBuilder.ToString()
End Sub,
cancellationToken)
智能体 UI 代码还使用 Handles 子句进行消息变更事件处理,使得滚动条自动滚动到最新项:
Private Sub LogItems_CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs) Handles LogItems.CollectionChanged
If e.Action = System.Collections.Specialized.NotifyCollectionChangedAction.Add Then
LastLogItem = LogItems.ElementAtOrDefault(LogItems.Count - 1)
AutoScrollToLastItem()
End If
End Sub Private Sub LastLogItem_PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles LastLogItem.PropertyChanged
If e.PropertyName = NameOf(MbtiAnalysisLogItem.Content) Then
AutoScrollToLastItem()
End If
End Sub
聊天栏也需要实时显示推理信息。如法炮制,不再赘述。
3. 工具系统实现
所有功能(包括传统算法和智能体)都封装为工具,通过字典进行管理:
Private ReadOnly _tools As New Dictionary(Of String, AIFunction)
' 注册工具
_tools("record_note") = New RecordNoteTool(_context)
_tools("view_note") = New ViewNoteTool(_context)
_tools("function_scores") = New FunctionScoresTool(_context)
_tools("function_positions") = New FunctionPositionsTool(_context)
_tools("generate_report") = New GenerateReportTool(_context)
' ...其它工具
工具基类确保统一的调用接口(基于 Microsoft.Extensions.AI.Abstractions):
Public MustInherit Class AIFunctionBase
Inherits AIFunction ' 模仿 WPF 的 Measure ... MeasureCore ... MeasureOverride 设计,确保与不支持 MyClass 的语言兼容,增强扩展性
Protected Overrides Function InvokeCoreAsync(arguments As AIFunctionArguments, cancellationToken As CancellationToken) As ValueTask(Of Object)
Return New ValueTask(Of Object)(InvokeCoreAsyncOverride(arguments, cancellationToken))
End Function Protected MustOverride Function InvokeCoreAsyncOverride(arguments As AIFunctionArguments, cancellationToken As CancellationToken) As Task(Of Object)
End Class
为了限制调用权限,我封装了 My.AI.Chat.SetTools 函数,用于控制当前智能体能用哪些工具。如有必要,子智能体也可以暴露类似的函数。
工具调用的自由度权衡
- 对于业务已经确定的场景,提前写好代码进行强制工具调用(直接找到对应工具,调用 InvokeAsync)。这样即使模型能力不足,也能保证正确性。但是这样的弊端是限制了 AI 的创造力。
- 对于需要灵活的场景,把工具列表提供给 AI,让它自己调用。坏处是不稳定。如果你能使用能力极强的模型,推荐使用这种模式。
- 灵活的极致:项目管理和子智能体的调遣,以及请求用户输入,都是工具调用。开发人员只提供工具和指示。甚至允许部分子智能体的指示,以及允许使用哪些工具,都是负责管控的智能体生成的。
- 稳定的极致:把工作流完全硬编码,智能体之间的任何不协调都提前写好代码处理。
4. 中断处理机制
系统支持两种类型的中断处理机制:
- 插嘴中断:用户在分析过程中提供补充信息
- 完全重置:用户清空当前分析任务,重新开始
插嘴中断
插嘴中断主要在ProcessMessageAsync方法中处理,在 OnCancelInference 触发:
' 按钮事件处理程序
Private Sub OnCancelInference() Handles ctlChat.CancelInference
_cancelSrc.Cancel()
End Sub ' ProcessMessageAsync 里面:
' 处理用户中断插嘴
Dim clearInterruptMessage = False
If UserInterruptRequested Then
UserInterruptRequested = False
clearInterruptMessage = True
Dim interruptMsg = Await UntilUserInputAsync(cancellationToken)
RecordNote("用户补充", interruptMsg, False, cancellationToken)
End If
' 调用工具(省略)
' 清理用户中断插嘴的信息
If clearInterruptMessage Then
RecordNote("用户补充", String.Empty, True, cancellationToken)
End If
完全重置
完全重置的事件处理程序:确认要重置才会调用重置
Private Async Sub OnClearMessageList() Handles ctlChat.ClearMessageList
If _pendingReset Then Return
Dim confirm = Await MsgBoxAsync("将清空当前分析任务的所有信息和日志,返回到初始状态,是否继续?",
MsgBoxButtons.YesNo, "清空", TopLevel.GetTopLevel(Me))
If confirm Then
_pendingReset = True
_cancelSrc.Cancel()
LogItems.Clear()
End If
End Sub
在MbtiStatelessAnalyzerView_Loaded方法内的循环中,系统会根据取消原因决定是重置分析器还是设置中断请求标志:
Try
Await _analyzer.RunAnalysisLoopAsync(_cancelSrc.Token)
Catch ex As OperationCanceledException When ex.CancellationToken = _cancelSrc.Token
_cancelSrc = New CancellationTokenSource
If _pendingReset Then
_pendingReset = False
_analyzer.ResetContext()
Else
_analyzer.UserInterruptRequested = True
End If
End Try
5. 答疑模式实现
分析完成后,系统进入交互式答疑模式。这其实就是个普通的对话智能体,它不仅拥有分析报告和原始数据,还能自己决定调用哪些工具来补充上下文(比如查看笔记):
Private Async Function AnswerQuestionsAsync(cancellationToken As CancellationToken) As Task(Of String)
' 限制工具集,只允许答疑相关的工具
My.AI.Chat.SetTools(_qaTools) ' 构建初始上下文消息(简化)
Dim contextMessage As String = $"以下是你之前提供的聊天记录和分析结果:
用户:{targetSpeaker}
聊天记录:{chatRecords}
八维分数统计结果:{scoreResults}
八维位置分析结果:{positionResults}
最终报告:{report}" ' 一问一答循环。简化的代码是:
Do
Dim message As ChatMessage = Await UntilUserInputAsync(cancellationToken) ' 获取用户问题内容
Dim question As String = GetMessageContent(message) ' 将用户问题添加到聊天历史
chatHistory.Add(New ChatMessage(ChatRole.User, question)) Dim responseBuilder As New StringBuilder
Await My.AI.Chat.ChatAsyncWithRetry(chatHistory,
Sub(response)
responseBuilder.Append(response)
' 更新消息内容
botMessage.Text = responseBuilder.ToString()
End Sub,
cancellationToken) Dim answer As String = responseBuilder.ToString() ' 将助手回答添加到聊天历史
chatHistory.Add(New ChatMessage(ChatRole.Assistant, answer)) ' 通知用户输入(确保界面更新)
_requestUserInput() ' 循环继续,等待用户下一次提问
Loop
End Function
一些技术细节
1. 并行处理优化
在分析八维得分时,系统并行调用八个子智能体:
' 创建任务数组并行化调用每个分析器的 ProcessMessageAsync 方法
Dim tasks As Task(Of Integer)() = {
niAgent.ProcessMessageAsync(personToAnalysis, messagesToAnalysis, reportLog, cancellationToken),
neAgent.ProcessMessageAsync(personToAnalysis, messagesToAnalysis, reportLog, cancellationToken),
' ... 其他五个智能体
} ' 等待所有任务完成
Dim results As Integer() = Await Task.WhenAll(tasks)
这种设计充分利用推理 API 并发的特性,显著缩短分析时间。
2. 错误处理与重试机制
每个子智能体都实现了重试机制,确保分析的可靠性:
Dim retryCount As Integer = 0 Do
' 调用AI分析
' ... 使用 My.AI.Chat.ChatAsyncWithRetry
' 分析字符串以取得 score 的值 ' 验证结果有效性
If score >= 0 AndAlso score <= 100 Then
Exit Do ' 成功提取有效分数,退出循环
End If ' 增加重试计数
retryCount += 1
If retryCount >= maxRetries Then
Throw New AILowIQException("重试次数过多,请检查AI模型是否正确配置")
End If
Loop
对于与推理服务的交互,我封装了 My.AI.Chat.ChatAsyncWithRetry,它也做了错误分类和重试。
3. UI线程安全更新
通过Dispatcher确保UI更新在正确的线程上执行:
Private Sub ReportLog(logItem As MbtiAnalysisLogItem)
' 在UI线程上更新日志列表
Avalonia.Threading.Dispatcher.UIThread.Post(
Sub()
LogItems.Add(logItem)
End Sub)
End Sub
4. 上下文清洗过滤
这一步对于稳定性至关重要。对于用户输入,要通过子智能体挑选有效的输入数据,并确保输入数据符合要求。另外,如果上下文过长需要压缩,用这种办法也能减少数据丢失。
例如,在CollectChatRecordsAndTargetAsync函数中,实现了独立的智能体,它辅助验证用户输入的内容是否为有效的聊天记录格式,并提取要分析的目标用户名称。这种方法确保了后续分析步骤能够获得正确的数据,避免了因输入数据格式不正确或不完整而导致的分析错误。
' 代码经过简化,只展示核心逻辑
Private Async Function CollectChatRecordsAndTargetAsync(cancellationToken As CancellationToken) As Task(Of String)
Dim chatRecordOk = False
Dim analysisTargetOk = False Do
Dim message As ChatMessage = Await UntilUserInputAsync(cancellationToken)
Dim messageContent As String = GetMessageContent(message) If Not chatRecordOk Then
' 调用 AI 判断是否是聊天记录
Dim isChatRecord As Boolean = Await IsChatRecordAsync(message, cancellationToken)
If isChatRecord Then
' 记录用户的聊天记录到笔记中
RecordNote("聊天记录", messageContent, True, cancellationToken)
chatRecordOk = True
End If
End If If Not analysisTargetOk Then
' 提取分析目标
Dim analysisTarget As String = Await ExtractAnalysisTargetAsync(messageContent, cancellationToken)
If Not String.IsNullOrEmpty(analysisTarget) Then
RecordNote("分析目标", analysisTarget, True, cancellationToken)
analysisTargetOk = True
End If
End If
Loop Until chatRecordOk AndAlso analysisTargetOk
' 其它逻辑
End Function
总结
通过这个项目,我展示了如何使用 Visual Basic .NET 构建一个复杂的多智能体协作系统。关键设计决策包括:
- 强制工作流:通过硬编码待办事项列表确保分析按预期顺序进行,部分子智能体会强制调用指定的工具
- 具有图形界面:通过事件处理机制提供分析过程的实时可视化
- 工具化设计:将所有功能封装为工具,便于管理和扩展
- 无状态智能体:通过共享上下文实现智能体间的数据传递
- 实时交互体验:提供中断处理和答疑模式,增强交互性
这个系统不仅能够准确分析人格类型,还提供了良好的可解释性和用户体验。这种设计方式也能套用到其它智能体,而不仅局限于荣格八维分析。
本文使用 CC-BY-NC-SA 4.0 协议。转载或者 AI 模型/智能体使用请注明出处并标注作者 Nukepayload2。
演练:使用VB开发多智能体协作的荣格八维分析器的更多相关文章
- 用nodejs 开发的智能提示
用nodejs 开发的智能提示 时间:2014-07-01 03:50:18 类别:搜索引擎 访问: 2576 次 感谢:http://lutaf.com/223.htm 智能提示对于搜索非常重要,相 ...
- 将AE开发的专题图制作功能发布为WPS
AE开发可以定制化实现ArcGIS的地理处理功能,并实际运用于其他方面的工作,有时候我们还希望将AE开发的功能发布为网络地理信息处理服务(WPS),从而能在Web端更自由便利地调用所需要的地学处理算法 ...
- iOS开发UI篇—简单介绍静态单元格的使用
iOS开发UI篇—简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果, ...
- 打通C/4HANA和S/4HANA的一个原型开发:智能服务创新案例
今年6月SAP发布C/4HANA之后,有顾问朋友们在微信公众号后台留言,询问C/4HANA如何同SAP的数字化核心S/4HANA系统结合起来,从而打通企业的前后端业务,帮助企业实现数字化转型. 有的顾 ...
- 迅为IMX6核心板开发平台智能交通解决方案
智能交通系统它是将先进的信息技术.数据通讯传输技术.电子传感技术.控制技术及计算机技术等有效地集成运用于整个地面交通管理系统而建立的一种在大范围内.全方位发挥作用的,实时.准确.高效的综合交通运输管理 ...
- 基于Arduino开发的智能蓝牙小车
基于Arduino的智能蓝牙小车 材料准备: Arduino开发板一块.四驱小车底板及相关配件一套.L298N驱动模块一个.HC-05/06蓝牙模块一块,九伏电源一块(用于主板供电).12V锂电池一块 ...
- VB开发类似IIS简易的WebServer,代码不到100行
最近遇到三个人问关于VB写网页服务器的问题,所以今天抽时间写一下,演示其实没有多复杂. 代码里自定义的方法只有四个,没有公共变量绕来绕去,该注释的也都注释了. 想扩展更复杂的功能,就需要自己补脑HTT ...
- VB开发ActiveX控件的一些记录
注意,下面很多语句的用法,不能放在Private Sub UserControl_Initialize()里使用,要放在Private Sub UserControl_InitProperties() ...
- android音乐播放器开发 SweetMusicPlayer 智能匹配本地歌词
上一篇写了使用MediaPlayer播放音乐,http://blog.csdn.net/huweigoodboy/article/details/39861539. 代码地址:https://gith ...
- windows下webstorm开发react-native智能提示
webstorm破解版地址:点这里 1.随便在一个目录下下载ReactNative-LiveTemplate插件,命令为: git clone https://github.com/virtoolsw ...
随机推荐
- Django中图片不显示
很多教程没教对,导致Django中的图片不能正确的显示出来,经过多次踩坑,发现如下方法可以解决该问题. 1.setting.py中添加: STATIC_URL = '/static/' STATICF ...
- Solon Ai Flow 编排开发框架发布预告(效果预览)
Solon Ai 在推出 Solon Ai Mcp 后,又将推出 Solon Ai Flow. 1.Solon Ai Flow 是个啥? Solon Ai Flow 是一个智能体编排开发框架(基于 s ...
- [极客大挑战 2019]FinalSQL 1
[极客大挑战 2019]FinalSQL 1 这篇主要是考察布尔盲注,而且他很贼,弄了两个输入框,但过滤的东西很多:真正的注入点在search.php传入的参数.说来惭愧,之前就做过布尔盲注的题目,结 ...
- [读书笔记]《大数据之路》——阿里数据整合及管理体系——OneData模型
阿里数据整合及管理体系--OneData模型 摘要 阿里的<大数据之路>第9章介绍了其内部进行数据整合及管理的方法体系和工具OneData.他们在这一体系下,构建统 .规范.可共的全域数据 ...
- Linux常用命令介绍-系统管理
find命令 - 根据路径和条件搜索指定文件 ind命令的功能是根据给定的路径和条件查找相关文件或目录,其参数灵活方便,且支持正则表达式,结合管道符后能够实现更加复杂的功能,是Linux系统运维人员必 ...
- 聊聊@Autowired注解的Field injection is not recommended提示问题
1. 前言 在我接触过的大部分Java项目中,经常看到使用@Autowired注解进行字段注入: import org.springframework.beans.factory.annotation ...
- K8S的API Server认证介绍
一.说明 kube-apiserver是k8s最重要的制组件之一,主要提供以下功能: 提供集群管理的REST API 接口, 包括认证授权.数据校验以及集群状态变更等 k8s 中所有模块与 etcd ...
- PHP框架中用户认证和授权的实现方法与示例
本文由 ChatMoney团队出品 在Web开发中,用户认证(Authentication)和授权(Authorization)是构建安全应用程序的核心组件.用户认证是验证用户身份的过程,确保用户是他 ...
- [推荐收藏]JavaScript书籍精读笔记系列导航
写在前面 去年我整理了一份「前端工程师必备书籍清单.md」,得到很多人的关注.这份清单里面的书籍大部分我都看过了,但有些知识点难免看后就忘.之前看这些书对一些重点都进行了记录,最近一段时间计划把这些重 ...
- 超实用!SpringAI提示词的4种神级用法
提示词(Prompt)是输入给大模型(LLM)的文本指令,用于明确地告诉大模型你想要解决的问题或完成的任务,也是大语言模型理解用户需求并生成准确答案的基础.因此 prompt 使用的好坏,直接决定了大 ...