You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DirectLineJS中UserId无法同步至Azure Log Analytics问题求助

问题:Log Analytics中QnA数据的userId字段始终为空

问题描述

我用Angular应用结合DirectLineJS对接Azure Bot(.NET 6),通过后端接口获取Token并启动对话。已配置机器人诊断功能,将QnA数据发送到Log Analytics工作区,但Kusto报表里的userId字段一直为空。

版本信息

  • 前端(Angular应用):DirectLineJS 0.15.1版本
  • 后端(.NET 6)使用的NuGet包:
<PackageReference Include="Microsoft.Bot.Builder.AI.QnA" Version="4.19.3" />
<PackageReference Include="Microsoft.Bot.Builder.Dialogs" Version="4.19.3" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.19.3" />

相关代码实现

前端Angular获取Token的方法

getToken(iframeQueryParams: IFrameQueryParams): Observable<FCChatTokenDTO> {
    return this.http.get<FCChatTokenDTO>(
      `${environment.fcChatbotAPIUrl}/api/token?userId=${iframeQueryParams.userId}&divisionId=${iframeQueryParams.divisionId}`
    );
}

前端发送消息到机器人的方法

sendMessage(text: string) {
    const msg = {
      from: { id: this.userId, name: 'Test name' },
      type: 'message',
      text,
    } as FCChatMessage;
    return this.directline.postActivity(msg);
}

注:this.userId遵循DirectLine约定,以dl_开头,例如dl_123456

后端.NET生成Token的接口

public async Task<ActionResult<ChatConfig>> token([FromQuery] string? userId,[FromQuery] int? divisionId)
{
    if (!string.IsNullOrWhiteSpace(_configuration["DirectLineSecret"]))
    {
        _DirectLineSecret = _configuration["DirectLineSecret"];
    }

    HttpClient client = new HttpClient();

    HttpRequestMessage request = new HttpRequestMessage(
        HttpMethod.Post,
        $"https://directline.botframework.com/v3/directline/tokens/generate");

    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _DirectLineSecret);

    if(string.IsNullOrEmpty(userId))
    {
        userId = Guid.NewGuid().ToString();
    }

    if (divisionId == null)
    {
        divisionId = 0;
    }

    //Important: User Id value needs to start with dl_ prefix, otherwise request will fail with 401
    var userParam = $"dl_u_{userId}_d_{divisionId}";

    request.Content = new StringContent(
        Newtonsoft.Json.JsonConvert.SerializeObject(
            new { User = new { Id = userParam } }),
            Encoding.UTF8,
            "application/json");

    var response = await client.SendAsync(request);
    string token = String.Empty;
    string conversationId = String.Empty;

    if (response.IsSuccessStatusCode)
    {
        var body = await response.Content.ReadAsStringAsync();
        var directLineToken = JsonConvert.DeserializeObject<DirectLineToken>(body);
        token = directLineToken.token;
        conversationId = directLineToken.conversationId;
    }

    var config = new ChatConfig()
    {
        token = token,
        userId = userParam,
        conversationId = conversationId
    };

    return Ok(config);
}

Kusto查询语句

// All QnA Traffic
AzureDiagnostics
| where ResourceProvider == "MICROSOFT.COGNITIVESERVICES"
| where OperationName=="CustomQuestionAnswering QueryKnowledgebases" // This OperationName is valid for custom question answering enabled resources
| sort by TimeGenerated desc

查询结果示例(userId为空)

{
"kbId": "FCKB",
"userId": "",
"question": "how do I create an account?",
"id": "2609",
"answer": "To create a deduction code for a health savings account (HSA), go to the SETUP tab > Payroll > Payroll Deductions. Click Add. Click the Add button for Health Savings Account (Single) or Health Savings Account (Family). Click OK in the confirmation window. Click the X in the top-right corner to close the Add Deduction panel. To make changes, click the Edit icon (pencil) next to the new code, and make your changes. 

The Health Savings Account (Single) or Health Savings Account (Family) code is used for a pre-tax flat amount deduction of an employee's wages that they can opt-in to set aside to go into an HSA, which can pay for certain qualified medical expenses, such as copayments, deductibles, etc. For the Family option, the taxable wage limit is per family.",
"score": "68.37",
"source": "Q&As for earnings and deductions for FCKB.xlsx",
"isQnaOverDocumentRequest": "True",
"isAnswerFromDocumentText": "Microsoft.CognitiveServices.QnAMaker.Runtime.Models.QnASearchResult",
"azure-Resource-Id": "/subscriptions/XXXXXXXXXXX/resourcegroups/qna-bot-dev/providers/microsoft.cognitiveservices/accounts/fc-bot-language",
"apim-request-id": "XXXXXXXXX"
}

预期行为

我已通过正确格式的UserId生成Token,并且在directLine.postActivity中传入了UserId,Kusto查询结果里的userId字段应该被填充,但实际为空。

尝试过的操作

尝试调用directLine.setUserId,但收到警告:

if (userIdFromToken) {
    return console.warn('DirectLineJS: user id is already set in token, will ignore this user id.');
}

解决方案

要让userId字段出现在Log Analytics的QnA数据中,需要在调用QnA Maker服务时,手动将用户ID传递到QnA请求的context参数里,具体步骤:

  1. 在Bot后端的QnA查询逻辑中,从当前对话的TurnContext获取用户ID(即turnContext.Activity.From.Id),然后将其添加到QnA请求的QnAMakerOptions的Context属性中:
var qnaOptions = new QnAMakerOptions
{
    Context = new QnARequestContext
    {
        UserId = turnContext.Activity.From.Id
    },
    // 其他配置参数
};

var response = await _qnaMaker.GetAnswersAsync(turnContext, qnaOptions);
  1. 确认Bot的诊断设置已正确配置,确保QnA的上下文数据被包含在发送到Log Analytics的诊断日志中。

原理:默认情况下,QnA Maker不会自动将对话中的用户ID传递到诊断日志里,需要显式在请求中指定UserId参数,这样Log Analytics才能捕获到该字段的值。


内容的提问来源于stack exchange,提问作者Adolfo Perez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 06:30:11