-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: add telemetry for office agent #11831
refactor: add telemetry for office agent #11831
Conversation
const purifiedResult = await getCopilotResponseAsString( | ||
"copilot-gpt-4", | ||
purifyUserMessage, | ||
token | ||
); | ||
const t1 = performance.now(); | ||
const requestTokens = countMessagesTokens(purifyUserMessage); | ||
const responseTokens = Tokenizer.getInstance().tokenLength(purifiedResult); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use countMessagesTokens here. Same for the rest.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, thanks
… user/haojiangliu/addTelemetry
packages/vscode-extension/src/officeChat/common/samples/sampleProvider.ts
Fixed
Show fixed
Hide fixed
packages/vscode-extension/src/officeChat/commands/nextStep/officeNextstepCommandHandler.ts
Fixed
Show fixed
Hide fixed
packages/vscode-extension/src/officeChat/common/samples/sampleProvider.ts
Fixed
Show fixed
Hide fixed
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #11831 +/- ##
==========================================
+ Coverage 89.34% 89.40% +0.05%
==========================================
Files 566 569 +3
Lines 33150 33311 +161
Branches 6417 6541 +124
==========================================
+ Hits 29619 29781 +162
+ Misses 1612 1601 -11
- Partials 1919 1929 +10
|
OffTopic = "Off Topic", | ||
LanguageModelError = "LanguageModel Error", | ||
} | ||
export class OfficeChatTelemetryData extends ChatTelemetryData { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are implementing all member variables/methods, please implement the interface IChatTelemetryData instead of extend ChatTelemetryData
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
@@ -95,11 +112,11 @@ export function getOfficeTemplateMetadata(): ProjectMetadata[] { | |||
export async function showOfficeSampleFileTree( | |||
projectMetadata: ProjectMetadata, | |||
response: ChatResponseStream | |||
): Promise<string> { | |||
): Promise<object> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Define a object struct { path: string, host: string } instead of returning an object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
const sampleInfos = await showOfficeSampleFileTree(matchedResult, response); | ||
const folder = (sampleInfos as any)?.["path"]; | ||
const hostType = (sampleInfos as any)?.["host"].toLowerCase(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the defined object structure to fetch these variables instead of cast to any
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
const sampleTitle = localize("teamstoolkit.chatParticipants.create.sample"); | ||
officeChatTelemetryData.setHostType(hostType); | ||
const matchResultInfo = "sample"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been defined in matchedResult.type
, remove this variable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
const tmpHostType = (matchedResult.data as any)?.["addin-host"].toLowerCase(); | ||
const tmpFolder = await showOfficeTemplateFileTree(matchedResult.data as any, response); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, use the defined object struct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the type of matchedResult.data is unknown so that I think it should be convert to any
const templateTitle = localize("teamstoolkit.chatParticipants.create.template"); | ||
officeChatTelemetryData.setHostType(tmpHostType); | ||
const tmpmatchResultInfo = "template"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove and use matchedResult.type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
response.markdown(` | ||
${localize("teamstoolkit.chatParticipants.officeAddIn.printer.outputTemplate.intro")}\n | ||
${purified} | ||
`); | ||
const spec = new Spec(purified); | ||
spec.appendix.telemetryData.requestId = telemetryData.requestId; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put it into the constructor
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will fix, thanks
// telemetryData.setCodeClassAndMembers( | ||
// spec.appendix.telemetryData.codeClassAndMembers.toString() | ||
// ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove these lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will remove, thanks
const t1 = performance.now(); | ||
telemetryData.responseTokensPerRequest.push( | ||
OfficeChatTelemetryData.calculateResponseTokensPerRequest(response, t0, t1) | ||
); | ||
telemetryData.chatMessages.push( | ||
...messages, | ||
new LanguageModelChatMessage(LanguageModelChatMessageRole.Assistant, response) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe log the response tokens/LLM call is unnecessary. We can only log all response tokens in an array and calculate this metrics in markComplete. Please feel free to call out if you have other thoughts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
have fixed to distinguish request token and response token and removed response tokens per request
// this.telemetryData.properties[TelemetryProperty.CopilotChatCodeClassAndMembers] = | ||
// this.codeClassAndMembers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove these lines
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will remove, thanks
CopilotMatchResultType = "copilot-match-result-type", | ||
CopilotChatBlockReason = "copilot-chat-block-reason", | ||
CopilotChatRelatedSampleName = "copilot-chat-related-sample-name", | ||
CopilotChatCodeClassAndMembers = "copilot-chat-code-class-and-members", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this unused variable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, thanks
CopilotChatTimeToFirstToken = "copilot-chat-time-to-first-token", | ||
CopilotChatTotalTokensPerSecond = "copilot-chat-total-tokens-per-second", | ||
CopilotChatResponseTokensPerRequest = "copilot-chat-response-tokens-per-request", | ||
CopilotChatTotalTokens = "copilot-chat-total-tokens", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is existing CopilotChatTokenCount
, so we should just use that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the existing name could not distinguish request token and response token. I have added 2 new telemetry names to make it clear
packages/vscode-extension/src/officeChat/commands/create/officeCreateCommandHandler.ts
Fixed
Show resolved
Hide resolved
packages/vscode-extension/src/officeChat/common/skills/codeExplainer.ts
Fixed
Show resolved
Hide resolved
packages/vscode-extension/src/officeChat/common/samples/sampleProvider.ts
Fixed
Show resolved
Hide resolved
packages/vscode-extension/src/officeChat/common/skills/codeIssueCorrector.ts
Fixed
Show resolved
Hide resolved
packages/vscode-extension/src/officeChat/common/skills/codeGenerator.ts
Fixed
Show resolved
Hide resolved
@@ -102,5 +123,5 @@ export async function getOfficeSampleDownloadUrlInfo(sampleId: string) { | |||
if (!sample) { | |||
throw new Error("Sample not found"); | |||
} | |||
return sample.downloadUrlInfo; | |||
return { downloadUrlInfo: sample.downloadUrlInfo, host: sample.types[0] }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change the function name to getOfficeSample
and return the sample object in this method. Fetch the downloadUrlInfo and host type in outer calling function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, thanks
// groupedMethodsOrProperties.forEach((methodsOrPropertiesCandidates, className) => { | ||
// for (let i = 0; i < methodsOrPropertiesCandidates.length; i++) { | ||
// let methodOrProperty = methodsOrPropertiesCandidates[i].codeSample; | ||
// if (methodOrProperty.startsWith("readonly ")) { | ||
// methodOrProperty = methodOrProperty.replace("readonly ", ""); | ||
// } | ||
// const lastColonIndex = methodOrProperty.lastIndexOf(":"); | ||
// if (lastColonIndex !== -1) { | ||
// methodOrProperty = methodOrProperty.substring(0, lastColonIndex); | ||
// } | ||
// const classCode = `${className}.${methodOrProperty}`; | ||
// spec.appendix.telemetryData.codeClassAndMembers.push(classCode); | ||
// } | ||
// }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove these lines if never used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
@@ -367,6 +383,7 @@ ${spec.appendix.codeExplanation | |||
// host, | |||
// codeSpec, | |||
// "" //sampleCode | |||
// spec |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this line if never used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have also changed the function getMostRelevantDeclarationsUsingLLM because there is an interaction with copilot in it. seems like there is no other usage of the function in other code. should I also remove my change on the function?
@@ -40,8 +41,8 @@ export default async function officeCreateCommandHandler( | |||
|
|||
if (request.prompt.trim() === "") { | |||
response.markdown(localize("teamstoolkit.chatParticipants.officeAddIn.create.noPromptAnswer")); | |||
|
|||
officeChatTelemetryData.markComplete(); | |||
officeChatTelemetryData.setBlockReason("Empty Input"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the 'Empty Input' be set in an Enum?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I missed it. will fix, thanks
@@ -11,3 +11,8 @@ export interface ICopilotChatOfficeResultMetadata { | |||
export interface ICopilotChatOfficeResult extends ChatResult { | |||
readonly metadata?: ICopilotChatOfficeResultMetadata; | |||
} | |||
|
|||
export type ProjectMiniData = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thanks
response.markdown( | ||
"\nWe've found a sample project that matches your description. Take a look at it below." | ||
); | ||
const downloadUrlInfo = await getOfficeSampleDownloadUrlInfo(projectMetadata.id); | ||
const { downloadUrlInfo, host } = await getOfficeSampleDownloadUrlInfo(projectMetadata.id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about the host type of the matched templates? seems like there's only telemetry for matched samples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it has been already logged. thanks
if (spec.appendix.telemetryData.isHarmful === false) { | ||
telemetryData.setBlockReason(OfficeChatTelemetryBlockReasonEnum.RAI); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it be set when isHamrful === true
?
Add telemetry for office agent
PM spec: https://microsoft.sharepoint.com/:w:/t/OfficePlatform/ESZVb6Q77nZBhXZr1pWEVaABmLATm2tHDMEPkuo7ITgVvg?e=0LwZO8