Bitzsoft.Integrations.AI.Conversation
1.1.0
dotnet add package Bitzsoft.Integrations.AI.Conversation --version 1.1.0
NuGet\Install-Package Bitzsoft.Integrations.AI.Conversation -Version 1.1.0
<PackageReference Include="Bitzsoft.Integrations.AI.Conversation" Version="1.1.0" />
<PackageVersion Include="Bitzsoft.Integrations.AI.Conversation" Version="1.1.0" />
<PackageReference Include="Bitzsoft.Integrations.AI.Conversation" />
paket add Bitzsoft.Integrations.AI.Conversation --version 1.1.0
#r "nuget: Bitzsoft.Integrations.AI.Conversation, 1.1.0"
#:package Bitzsoft.Integrations.AI.Conversation@1.1.0
#addin nuget:?package=Bitzsoft.Integrations.AI.Conversation&version=1.1.0
#tool nuget:?package=Bitzsoft.Integrations.AI.Conversation&version=1.1.0
Bitzsoft.Integrations.AI.Conversation
面向企业多租户 AI 对话应用的零 ORM 依赖、零业务词汇会话协议与运行时编排包。统一封装富消息分片与确定性 JSON 落盘预算、前后端流式事件帧协议、推理模型采样防踩坑选项工厂、跨任意分块的思考标签拆分与五维多轮 Token 去重累加投影器、两阶段上下文预算器、非阻断数字事实对账器、幂等请求四态台账与会话互斥租约协调器以及无锁 19 位单调递增主键生成器。
版本与兼容性
dotnet add package Bitzsoft.Integrations.AI.Conversation
- 目标框架:
net8.0;net10.0; - 项目依赖:
Bitzsoft.Integrations.AI.Governance、Bitzsoft.Integrations.AI.Skills; - 第三方依赖:仅复用
Microsoft.Extensions.AI.Abstractions、DI、Options、Logging,零新增第三方 NuGet 包; - 不依赖
SqlSugar、EntityFrameworkCore、StackExchange.Redis或 ASP.NET Core Web 框架(HTTP 写出独立位于Bitzsoft.Integrations.AI.AspNetCore)。
核心模块与设计边界
| 模块 | 核心类型 | 解决的工程问题 |
|---|---|---|
| A. 富消息分片与落盘预算 | AIMessagePart、AIMessagePartTypes、AIMessagePartSerializer |
覆盖 text、reasoning、tool_call、tool_result、data、file、approval_required、citation、warning 九类标准分片;向下兼容 BitzOrcas(tool-call/source)与 BitzOrcasVNext(tool_call/citation)历史载荷,按 MaxTotalChars/MaxPartChars/MaxArrayItems 确定性裁剪并保持合法 JSON 且置 Truncated = true |
| B. 统一流式事件帧 | AIStreamFrame、AIStreamFrameTypes |
统一 start、reasoning、tool_call、tool_result、data、file、approval_required、citation、warning、message、done、error 十二种 camelCase 事件帧 |
| C. 模型对话选项工厂 | AIChatOptionsFactory、AIChatSessionRequest |
推理模型(DeepSeek V4/Flash 思考模式、o1/o3/o4-mini、QwQ 等)强制清空 Temperature = null 与 TopP = null,通过 AdditionalProperties["reasoning_effort"] 注入思考强度,并原样保留 AIConcurrentTurnToolCollection 实时列表引用以支持同轮渐进挂载技能工具 |
| D. 流式与非流式投影器 | AIChatResponseProjector、AIChatProjectorOptions、AIUsageSnapshot |
内置跨任意字符边界 <think>...</think> 状态机(含单字符切块与 EOF 未闭合兜底)、五维多轮去重累加器(Input/Output/Total/Reasoning/CachedInput)、approval_required 回执最高优先级提取、结构化表格/指标/附件帧分流、max_iterations_reached 与 ungrounded_numbers 告警帧注入 |
| E. 两阶段上下文预算器 | AIConversationContextBudgeter、DefaultTokenEstimator |
区分中日韩宽字符与拉丁代码符号保守估算 Token;固定保护系统提示词、最新用户提问与最近 MinRecentTurnsToKeep 轮,先将较早历史工具大 JSON 压缩为紧凑摘要,仍超预算再整轮淘汰最早历史避免孤立工具调用对 |
| F. 非阻断数字事实对账 | AINumericGroundingChecker、AINumericGroundingResult |
提取回复中的金额、百分比与四位以上业务数值(自动排除日期、单据编号、条款章节号与 < 10 短数),与当轮业务工具输出执行千分位及 万/亿 单位等价对账,永不阻断输出 |
| G. 幂等请求台账与会话租约 | IAIRequestLedgerStore、AIMessageRequestCoordinator |
计算长度前缀防碰撞的确定性 sha256: 请求指纹,编排 Acquired / InProgress / CompletedReplay / PayloadConflict 四态状态机、基于 UpdatedAt ?? CreatedAt 心跳的僵尸请求 (Status, Version) 单赢家接管及会话互斥租约 |
| H. 单调递增主键生成器 | AISequentialIdGenerator |
无锁 CAS 生成定长 19 位十进制正整数文本主键(恒在 [10^18, long.MaxValue] 区间,绝不产出 "0"),消除雪花或随机 ID 跨节点时钟微偏导致的历史消息乱序 |
| I. 千人千面工作台与三级星标置顶 | IAIWorkbenchSurfaceResolver、DefaultAIWorkbenchSurfaceResolver、AISkillWorkbenchBridge |
按「RBAC + 数据分级硬门禁 → 岗位角色蓝图 → 四维上下文联动 → 三级星标合成 ((SystemFeatured ∪ RoleDefaultPinned) \ UserUnpinnedSystem \ UserHidden) ∪ UserPinned」生成表面快照与 EffectivePinnedPills / EffectivePinnedToolNames |
| J. 四级对话风格偏好级联 | AIPreferenceResolver、AIPreferencePromptBuilder、AIConversationPreferenceProfile |
按「租户默认 → 岗位角色蓝图 → 用户个人偏好 → 会话单轮临时覆盖」四级合并详略密度、语气基调、排版结构与引用标注风格,清洗自定义指令并生成确定性中文系统提示词附录 |
K. 双轨制语义深链接(entity_ref) |
AISemanticDeepLinkBuilder、AIEntityRefPayload、AIMessagePartTypes.EntityRef |
生成可配置私有协议 bitz://{domain}/{action}?id=... 与跨端 UniversalUrl,投影器自动从工具结果顶层与列表项提取 _entityRef/_route 生成卡片分片与流式帧(显式 universalUrl 仅在与配置网关主机一致时采纳);文件下载卡片仅放行站内相对路径或 AllowedDownloadUrlHosts 白名单内绝对 HTTPS 外链,协议注入一律拒绝合成 |
| L. 通用在场页面上下文与客户端委托工具网关 | AIPageContext、AIPageContextPromptBuilder、ClientDelegatedAIFunction、AIClientToolPassThroughRegistry |
递归脱敏敏感凭据并以 <page_context trust="untrusted-client-state"> 包裹不可信客户端视图状态;向模型暴露 client:*(如 client:form:patch RFC 6902 草稿修补)Schema,阻断服务端写库,推送客户端 tool_call 帧并返回 delegated_to_client 合成回执;调用编号配对与事件帧路由收敛在 WrapExecutionClient 创建的每轮作用域内,函数实例可安全跨请求复用 |
| M. 流式分片间空闲超时看门狗 | AIStreamIdleTimeoutExtensions、AIStreamIdleTimeoutException |
WithInterChunkIdleTimeout 感知 TimeProvider,每收到一帧重置计时、下游消费期间暂停计时,上游卡死超限时立即取消底层枚举并抛出 stream_idle_timeout |
| N. 纯函数会话分叉规划与待审批卡片重写 | AISessionBranchPlanner、AIPendingApprovalPartRewriter |
零 ORM 耦合维护 user/assistant/tool 完整轮次切片(IncludeAnchorTurnReply / ExcludeAnchorTurn)、校验滚动摘要分段继承安全性,并将克隆历史中未决审批卡片改写为 superseded_by_branch(保护已终态记录)或按 actionId 迁移至 executed/rejected/expired |
| O. 防炸弹内存文档文本提取与扫描页嵌图 OCR 桥接 | AIDocumentTextExtractor、IAIDocumentTextExtractor、IAIDocumentPageOcrPort、AIDocumentByteImageOcrPort |
在严格 MaxCompressedBytes、MaxDecompressedBytes 与 MaxArchiveEntries 防炸弹保护(另含页面树深度、间接对象总量与统一码映射累计展开三项硬上限)下流式提取 .docx、/FlateDecode .pdf 及 .txt;当单页少于阈值字符且配置了 OCR 端口时,按需遍历页面 /Resources -> /XObject(含嵌套 /Subtype /Form)提取有界 /Subtype /Image 图像字节流至 CandidateImageStreams,并通过 AIDocumentByteImageOcrPort 直接对接通用字节流图片 OCR 服务 |
| P. 历史工具结果实体与序号压缩摘要构建器 | AIToolResultDigestBuilder、AIToolResultDigestOptions、AIToolDigestHistoryItem |
从最近 N 轮持久化 AIMessagePart 分片提取只读工具调用的关键主键、单据编号、标题、金额及 #1/#2 列表项序号生成极简文本摘要,自动跳过客户端委托工具(client:* / client_*)与自定义忽略列表,低 Token 开销支撑“把第 2 条打开/统计刚才那笔”的多轮指代追问 |
双宿主流式事件帧对照表
统一帧类型 (AIStreamFrameTypes) |
BitzOrcas 存量前端语义 |
BitzOrcasVNext 前端语义 |
关键载荷字段 (camelCase) |
|---|---|---|---|
start |
会话握手 | 流开始元数据 | conversationId, requestId, modelId, replayed |
reasoning |
深度思考增量 | 思考链分片 | content |
tool_call |
工具调用开始 | 工具调用事件 | callId, toolName, toolArguments |
tool_result |
工具返回摘要 | 工具结果事件 | callId, toolName, structuredData, isError |
approval_required |
高风险写工具待审批卡片 | 待办确认动作 | actionId, toolName, structuredData |
data / file / citation |
报表表格、指标卡、导出文件、引用来源 | 结构化视图分片 | structuredData, fileId, fileName, mediaType, url, title |
warning |
非阻断治理提示 | 运行时告警提示 | warningCode, content, structuredData |
message |
助手可见正文增量 | 文本增量 | content |
done |
正常收敛帧 | 结束统计帧 | conversationId, requestId, modelId, inputTokenCount, outputTokenCount, totalTokenCount, reasoningTokenCount, cachedInputTokenCount, timeToFirstTokenMs, latencyMs, replayed |
error |
终端脱敏错误帧 | 异常终止帧 | errorCode, errorMessage, traceId |
IAIRequestLedgerStore 双 ORM(SqlSugar / EF Core)实现走查
建议在宿主请求台账表建立 (TenantId, SessionId, RequestId) 唯一索引,并在会话租约表建立 (TenantId, SessionId) 主键或唯一索引(或直接使用 Redis SET NX PX + Lua 释放):
- 原子插入或回查(
CreateOrGetExistingAsync):直接尝试插入Version = 1, Status = Pending新行;若命中唯一索引冲突异常,立即按(TenantId, SessionId, RequestId)回查既有行并返回new AIRequestLedgerCreateResult(CreatedNew: false, existing)。 - 双条件乐观并发跃迁(
TryTransitionAsync):- SqlSugar 宿主:使用
db.CopyNew().Updateable<SysAiRequestLedger>()并在WHERE子句严格限定TenantId == tenantId && SessionId == sessionId && RequestId == requestId && Status == (int)expectedStatus && Version == expectedVersion,同时将Version更新为expectedVersion + 1、UpdatedAt更新为transition.TransitionedAt,仅当受影响行数== 1时返回true; - EF Core 宿主:查询侧统一加
.AsNoTracking(),更新侧使用ExecuteUpdateAsync在单条 SQL 内匹配Status == expectedStatus && Version == expectedVersion并原子递增Version。
- SqlSugar 宿主:使用
- 契约测试基类验收:宿主测试项目直接继承
Bitzsoft.Integrations.AI.Testing.AIRequestLedgerStoreContractTestsBase调用RunAllContractAssertionsAsync(),一行代码自动验证唯一键幂等、多租户与跨会话隔离、16 路并发抢占单赢家、心跳续期版本保护、会话租约令牌防伪释放与过期自动接管。
完整最小示例
以下示例演示单调 19 位主键生成、推理模型安全选项构建、跨块 <think> 流式投影与数字事实对账以及幂等请求抢占与重放:
using Bitzsoft.Integrations.AI.Conversation;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
var services = new ServiceCollection();
services.AddBitzsoftAIConversation();
services.AddInMemoryBitzsoftAIConversationStores();
await using var provider = services.BuildServiceProvider(
new ServiceProviderOptions { ValidateOnBuild = true, ValidateScopes = true });
using var scope = provider.CreateScope();
var idGenerator = scope.ServiceProvider.GetRequiredService<AISequentialIdGenerator>();
var coordinator = scope.ServiceProvider.GetRequiredService<IAIMessageRequestCoordinator>();
var projector = scope.ServiceProvider.GetRequiredService<AIChatResponseProjector>();
// 1. 构建推理模型选项:自动清空不兼容的 Temperature / TopP 并注入 reasoning_effort。
ChatOptions chatOptions = AIChatOptionsFactory.Create(new AIChatSessionRequest
{
ModelId = "deepseek-flash",
IsReasoningModel = true,
ReasoningEffort = "high",
Temperature = 0.7f,
TopP = 0.9f,
});
// 2. 计算确定性请求指纹并声明幂等执行权。
string fingerprint = coordinator.ComputeFingerprint(new AIRequestFingerprintInput(
TenantId: "tenant-demo",
UserId: "user-01",
SessionId: "sess-100",
Prompt: "汇总本月已审结账单金额"));
var claim = await coordinator.TryClaimOrGetExistingAsync(new AIRequestClaimRequest(
TenantId: "tenant-demo",
UserId: "user-01",
SessionId: "sess-100",
RequestId: "req-20261107-01",
RequestFingerprint: fingerprint,
UserMessageId: idGenerator.NextId()));
if (claim.Outcome == AIRequestClaimOutcome.Acquired && claim.Entry is not null)
{
// 3. 投影跨分块 <think> 流式更新并执行工具结果数字事实对账。
static async IAsyncEnumerable<ChatResponseUpdate> MockStreamAsync()
{
yield return new ChatResponseUpdate(ChatRole.Assistant, [new FunctionCallContent("call-1", "query_bill_summary")]);
yield return new ChatResponseUpdate(ChatRole.Tool, [new FunctionResultContent("call-1", """{"totalAmount":1200000}""")]);
yield return new ChatResponseUpdate(ChatRole.Assistant, "<thi");
yield return new ChatResponseUpdate(ChatRole.Assistant, "nk>核对账单金额 1200000 元</think>本月已审结总额为 120万元。");
await Task.CompletedTask;
}
await foreach (AIStreamFrame frame in projector.ProjectStreamAsync(
MockStreamAsync(),
conversationId: "sess-100",
requestId: "req-20261107-01",
modelId: chatOptions.ModelId))
{
if (frame.Type == AIStreamFrameTypes.Done)
{
string? partsJson = AIMessagePartSerializer.Serialize(projector.Parts);
await coordinator.MarkCompletedAsync(new AIRequestCompletionUpdate(
TenantId: "tenant-demo",
SessionId: "sess-100",
RequestId: "req-20261107-01",
ExpectedVersion: claim.Entry.Version,
AssistantMessageId: idGenerator.NextId(),
ResponseText: projector.PersistenceContent,
PartsJson: partsJson,
Usage: projector.Usage));
}
}
}
Console.WriteLine($"正文输出:{projector.AssistantText},思考参数已清理:{chatOptions.Temperature is null}");
var sessionStore = provider.GetRequiredService<IAIConversationSessionStore>();
var createdSession = await sessionStore.CreateSessionAsync(new AIConversationSessionCreateRequest(
TenantId: "tenant-demo",
UserId: "user-demo",
Title: "合规账单复核",
ModelId: chatOptions.ModelId));
var reducer = provider.GetRequiredService<AICompactingChatReducer>();
var reducedMessages = (await reducer.ReduceAsync(new[]
{
new ChatMessage(ChatRole.System, "你是严谨的法务财务助手。"),
new ChatMessage(ChatRole.User, "请核对本月合同总额。"),
new ChatMessage(ChatRole.Assistant, "本月已审结总额 120 万元。"),
})).ToList();
var jobQueue = provider.GetRequiredService<Bitzsoft.Integrations.AI.Abstractions.IAIBackgroundJobQueue>();
string bgPayloadJson = System.Text.Json.JsonSerializer.Serialize(
new AIChatContinuationJobPayload(createdSession.SessionId, "输出完整风险报告"),
AIConversationJsonContext.Default.AIChatContinuationJobPayload);
var bgJob = await jobQueue.EnqueueAsync(new Bitzsoft.Integrations.AI.Abstractions.AIBackgroundJobSubmission(
TenantId: "tenant-demo",
UserId: "user-demo",
JobType: AIBackgroundJobTypes.ChatContinuation,
PayloadJson: bgPayloadJson,
SessionId: createdSession.SessionId));
Console.WriteLine($"会话已建档:{createdSession.SessionId},归约后消息数:{reducedMessages.Count},后台任务:{bgJob.JobId}");
全域对话持久编排、后台长任务与合规定价扩展
- 会话仓储、分叉管理与断线回放(
IAIConversationSessionStore/InMemoryAIConversationSessionStore/AITurnReplayBuilder):- 提供租户/所有者强隔离的会话 CRUD、工作区载体与焦点实体绑定(
BindWorkspaceAsync)、分叉切片克隆(自动重映射压缩游标并将未决审批卡重写为superseded_by_branch)及断线重连回合快照重建(按afterSequenceNumber增量输出标准AIStreamFrame回放序列与SuggestedAction)。
- 提供租户/所有者强隔离的会话 CRUD、工作区载体与焦点实体绑定(
- 全链路回合编排器(
IAIConversationTurnOrchestrator/AIConversationTurnOrchestrator):- 串联会话租约与幂等请求抢占、用户偏好四级求解与单航班纪元缓存、上下文窗口预算与滚动压缩、出站脱敏与驻留政策拦截、有序通道故障转移(复用
OrderedFailoverChatClient与AIUpstreamExceptionClassifier)、客户端断流半残消息补偿以及 FinOps 精确扣费。
- 串联会话租约与幂等请求抢占、用户偏好四级求解与单航班纪元缓存、上下文窗口预算与滚动压缩、出站脱敏与驻留政策拦截、有序通道故障转移(复用
- 用户偏好单航班纪元缓存(
AIUserPreferenceCache):- 基于
IAICacheEpochCoordinator(AICacheEpochKeys.UserPreferenceEpochScope)与AITenantSingleFlightEpochCache<AICachedUserPreferenceSnapshot>提供 L1/L2 单航班防击穿、可配置负缓存与保存/删除自动纪元失效。
- 基于
- M.E.AI 对话缩减桥接与后台长任务引擎(
AICompactingChatReducer/ChannelAIBackgroundJobQueue/AIBackgroundJobWorker):- 对接
Microsoft.Extensions.AI内置MessageCountingChatReducer与SummarizingChatReducer,并支持切换回退至确定性数字对账滚动压缩器DefaultAIConversationCompactor。 - 完整实现
IAIBackgroundJobStore(InMemoryAIBackgroundJobStore)、IAIBackgroundJobQueue(基于System.Threading.Channels的ChannelAIBackgroundJobQueue)与支持租约认领、心跳续约、乐观 CAS 跃迁、取消信号传播及ChatOptions.AllowBackgroundResponses/ResponseContinuationToken(AIContinuationTokenCodec)挂起续传的AIBackgroundJobWorker/AIChatContinuationJobHandler。
- 对接
- FinOps 计费、出站脱敏、HITL 协同与 Native AOT:
AIConversationFinOpsRecorder调用AIFinOpsCostCalculator精确计算常规输入、缓存命中输入、输出及推理令牌成本,并按AIOpenTelemetryTagNames写入遥测标签与度量指标。- 出站前强制经
IAIOutboundRedactor+AIDataResidencyPolicy校验,越权或跨区阻断立即 Fail-Closed 抛出AIDomainException(AIExecutionErrorCodes.OutboundRedactedBlocked)。 - 流式投影完整协同 HITL
Suspended挂起检查点与DryRunMode试运行预览帧(dry_run)。 - 工程已启用
<IsAotCompatible>true</IsAotCompatible>(双目标框架net8.0;net10.0),配合源生成AIConversationJsonContext消除反射序列化以支持 Native AOT 与 Trim 编译无警告通过。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Bitzsoft.Integrations.AI (>= 1.1.0)
- Bitzsoft.Integrations.AI.Governance (>= 1.1.0)
- Bitzsoft.Integrations.AI.Skills (>= 1.1.0)
- Microsoft.Extensions.AI (>= 10.11.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.11.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Options (>= 10.0.14)
-
net8.0
- Bitzsoft.Integrations.AI (>= 1.1.0)
- Bitzsoft.Integrations.AI.Governance (>= 1.1.0)
- Bitzsoft.Integrations.AI.Skills (>= 1.1.0)
- Microsoft.Extensions.AI (>= 10.11.0)
- Microsoft.Extensions.AI.Abstractions (>= 10.11.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Hosting.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- Microsoft.Extensions.Options (>= 10.0.14)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on Bitzsoft.Integrations.AI.Conversation:
| Package | Downloads |
|---|---|
|
Bitzsoft.Integrations.AgentFramework
Microsoft Agent Framework 集成 — Provider-neutral Agent、BitzAgentBuilder、会话持久化桥接、技能与上下文供给、长任务续传、HITL 审批与迭代循环编排 |
|
|
Bitzsoft.Integrations.AI.AspNetCore
ASP.NET Core AI 基础设施包 — 提供零缓冲 SSE/NDJSON 流式写出器(HITL/DryRun/Continuation/FinOps)、源生成 RFC 9457 ProblemDetails 异常映射、HttpContext 身份绑定、多模态与后台任务端点辅助,以及标注 AOT 边界的 MVC 只读工具反射发现与构建器 |
|
|
Bitzsoft.Integrations.AI.Testing
Bitzsoft AI 与 MCP 测试支持包 — 无测试框架锁定的存储端口契约测试基类、进程内测试替身、受控测试时钟与 FDE 黄金评估运行器 |
GitHub repositories
This package is not used by any popular GitHub repositories.