Files
jizhi/backend/MiaoJiZhang.Api/Services/LlmClient.cs
T

158 lines
5.0 KiB
C#

namespace MiaoJiZhang.Api.Services;
public interface ILlmClient
{
bool IsEnabled { get; }
Task<IntentResult?> TryParseIntentAsync(string userText, CancellationToken ct = default);
Task<string?> TryGenerateReplyAsync(string systemPrompt, string userText, CancellationToken ct = default);
Task<IReadOnlyList<ImageParseResult>?> AnalyzeImageAsync(
byte[] imageBytes,
string mimeType,
CancellationToken ct = default);
Task<IReadOnlyList<RecognitionBatchModelAction>?> ReconcileRecognitionBatchAsync(
RecognitionBatchModelInput input,
CancellationToken ct = default);
Task<(bool Ok, string? Error)> TestConnectionAsync(CancellationToken ct = default);
Task<AgentRunResponse> RunAgentAsync(
string systemPrompt,
string userText,
IReadOnlyList<AgentToolDefinition> tools,
Func<AgentToolCall, CancellationToken, Task<string>> executeTool,
Func<string, CancellationToken, Task>? onToken = null,
Func<string, CancellationToken, Task>? onToolRunning = null,
CancellationToken ct = default);
/// <summary>流式生成回复。将 LLM 返回的 token 逐个写入 writer,完成时返回。</summary>
Task StreamReplyAsync(
string systemPrompt,
string userText,
Func<string, CancellationToken, Task> onToken,
CancellationToken ct = default);
}
public record AgentToolDefinition(
string Name,
string Description,
object Parameters);
public record AgentToolCall(
string CallId,
string Name,
string Arguments);
public record AgentRunResponse(
string Text,
int ToolCallCount);
public record ImageParseResult(
string Type,
decimal Amount,
string CategoryName,
string? PaymentMethod,
string Note,
DateTime? OccurredAt,
string? TransferDirection = null,
string? Counterparty = null);
public record RecognitionBatchModelCandidate(
string CandidateId,
string? FlowSessionId,
string PackageName,
string Type,
decimal Amount,
string? Merchant,
string? OrderId,
DateTime OccurredAt,
string RecognitionKind,
string? CategoryHint,
string Confidence,
IReadOnlyList<string> EvidenceIds,
string? TransferDirection,
string? Counterparty,
string? ProviderTransactionId,
string? RecognitionOccurrenceId,
string? IdentityConfidence);
public record RecognitionBatchModelEvidence(
string EvidenceId,
string? CandidateId,
string? FlowSessionId,
string PackageName,
DateTime CapturedAt,
byte[] ImageBytes,
string MimeType);
public record RecognitionBatchModelInput(
string BatchId,
IReadOnlyList<RecognitionBatchModelCandidate> Candidates,
IReadOnlyList<RecognitionBatchModelEvidence> Evidence,
IReadOnlyList<string> ExpenseCategories,
IReadOnlyList<string> IncomeCategories);
public record RecognitionBatchModelAction(
string Action,
string ActionId,
string? CandidateId,
string? EvidenceId,
string? Type,
decimal? Amount,
string? CategoryName,
string? PaymentMethod,
string? Note,
DateTime? OccurredAt,
double Confidence,
string Reason,
string? TransferDirection,
string? Counterparty);
public class NullLlmClient : ILlmClient
{
public bool IsEnabled => false;
public Task<IntentResult?> TryParseIntentAsync(
string userText,
CancellationToken ct = default) =>
Task.FromResult<IntentResult?>(null);
public Task<string?> TryGenerateReplyAsync(
string systemPrompt,
string userText,
CancellationToken ct = default) =>
Task.FromResult<string?>(null);
public Task<IReadOnlyList<ImageParseResult>?> AnalyzeImageAsync(
byte[] imageBytes,
string mimeType,
CancellationToken ct = default) =>
Task.FromResult<IReadOnlyList<ImageParseResult>?>(null);
public Task<IReadOnlyList<RecognitionBatchModelAction>?> ReconcileRecognitionBatchAsync(
RecognitionBatchModelInput input,
CancellationToken ct = default) =>
Task.FromResult<IReadOnlyList<RecognitionBatchModelAction>?>(null);
public Task<(bool Ok, string? Error)> TestConnectionAsync(
CancellationToken ct = default) =>
Task.FromResult<(bool, string?)>((false, "API Key 为空"));
public Task<AgentRunResponse> RunAgentAsync(
string systemPrompt,
string userText,
IReadOnlyList<AgentToolDefinition> tools,
Func<AgentToolCall, CancellationToken, Task<string>> executeTool,
Func<string, CancellationToken, Task>? onToken = null,
Func<string, CancellationToken, Task>? onToolRunning = null,
CancellationToken ct = default) =>
Task.FromResult(new AgentRunResponse("", 0));
public async Task StreamReplyAsync(
string systemPrompt,
string userText,
Func<string, CancellationToken, Task> onToken,
CancellationToken ct = default)
{
await Task.CompletedTask;
}
}