-
Notifications
You must be signed in to change notification settings - Fork 405
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
feat: method-by-method OAS doc generation strategy #6023
feat: method-by-method OAS doc generation strategy #6023
Conversation
packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts
Outdated
Show resolved
Hide resolved
packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts
Outdated
Show resolved
Hide resolved
packages/salesforcedx-vscode-apex/src/oas/generationStrategy/prompts.ts
Outdated
Show resolved
Hide resolved
const responsePromises = this.prompts.filter(p => p?.length > 0).map(prompt => llmService.callLLM(prompt)); | ||
|
||
// Execute all LLM calls in parallel and store responses | ||
this.llmResponses = await Promise.all(responsePromises); |
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.
@mingxuanzhangsfdx If one promise fails then they all do. Is that what you want. If you would like an opportunity to examine each of these, then have a look at Promise.allSettled
} | ||
} | ||
|
||
cleanYamlString(input: string): string { |
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.
consider adding the @apos;
handling here, changing instances to '
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 is resolved by Cristi's tip above
Object.assign(combined.paths[path], methods); | ||
} | ||
// Merge components | ||
if (parsed.components?.schemas) { |
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.
@mingxuanzhangsfdx should this check if the schema already exists, as is being done above with paths
input += `${prompts.SYSTEM_TAG}\n${prompts['METHOD_BY_METHOD.systemPrompt']}\n${prompts.END_OF_PROMPT_TAG}\n`; | ||
input += `${prompts.USER_TAG}\n${prompts.METHOD_BY_METHOD_USER_PROMPT}\n`; | ||
input += '\nThis is the Apex method the OpenAPI v3 specification should be generated for:\n```\n'; | ||
const documentText = fs.readFileSync(new URL(this.metadata.resourceUri.toString()), 'utf8'); |
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.
Reading the Apex class for each method is expensive. this should be done in constructor.
if (methodContext?.returnType !== undefined) { | ||
input += `The return type of the method is ${methodContext.returnType}.\n`; | ||
} | ||
if (methodContext?.parameterTypes && methodContext.parameterTypes.length > 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.
if (methodContext?.parameterTypes && methodContext.parameterTypes.length > 0) { | |
if (methodContext?.parameterTypes?.length > 0) { |
packages/salesforcedx-vscode-apex/src/oas/generationStrategy/tmp.ts
Outdated
Show resolved
Hide resolved
@@ -73,7 +73,7 @@ export class ApexActionController { | |||
// Step 5:Initialize the strategy orchestrator | |||
const promptGenerationOrchestrator = new PromptGenerationOrchestrator(eligibilityResult, context); | |||
// Step 6: bid on the strategy, and the best one is available | |||
promptGenerationOrchestrator.bid(); | |||
// promptGenerationOrchestrator.bid(); | |||
// Step 7: use the strateg to generate the OAS | |||
const openApiDocument = await promptGenerationOrchestrator.generateOASWithStrategySelectedByBidRule(BidRule.MOST_CALLS); |
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 bid rule is set to always enable method-by-method strategy
packages/salesforcedx-vscode-apex/src/commands/apexActionController.ts
Outdated
Show resolved
Hide resolved
const responsePromises = this.prompts.filter(p => p?.length > 0).map(prompt => llmService.callLLM(prompt)); | ||
|
||
// Execute all LLM calls in parallel and store responses | ||
await Promise.allSettled(responsePromises).then(results => { |
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 Promise.allSettled to populate the methods as many as possible and not be blocked by failed requests
info: { | ||
title: this.context.classDetail.name, | ||
version: '1.0.0', | ||
description: `This is auto-generated OpenAPI v3 spec for ${this.context.classDetail.name}.` |
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 description is templated before we elaborate how it should look like
Object.assign(combined.paths[path], methods); | ||
// explicitly define openrationId if missing | ||
for (const [method, props] of Object.entries(combined.paths[path] as object)) { | ||
if (props?.operationId === undefined) { |
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 tried several different prompts to remind LLM always enabling operationId, but found out it still failed to fulfill my will constantly. So I added this mandatory check.
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.
an example how it could fail
@RestResource(urlMapping='/simpleResource/*')
global with sharing class SimpleRestResource {
@HttpGet
global static String doGet() {
return 'Hello World';
}
@HttpPost
global static String doPost(String message) {
return 'You posted: ' + message;
}
@HttpPut
global static String doPut(String message) {
return 'You put: ' + message;
}
@HttpDelete
global static String doDelete() {
return 'Goodbye';
}
}
'{ClassName}/{MethodName}. For every `type: object`, generate a `#/components/schemas` entry for that object. The method should have a $ref entry pointing to the generated `#/components/schemas` entry. I do not want AUTHOR_PLACEHOLDER in the result.' + | ||
'For each path, you define operations (HTTP methods) that can be used to access that path.' + | ||
'IMPORTANT: Each operation includes a MANDATORY *operationId* property, which should be a unique string matching the operations name.' + | ||
'Do NOT add any explanations of your answer that are not able to be parsed as YAML!', |
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 to emphasize the rule No.5 above again here in order to avoid unnecessary explanation in the response to block YAML parsing
'Generate an OpenAPI v3 specification for the following Apex method. The OpenAPI v3 specification should be a YAML file. The path should be /' + | ||
'{ClassName}/{MethodName}. For every `type: object`, generate a `#/components/schemas` entry for that object. The method should have a $ref entry pointing to the generated `#/components/schemas` entry. I do not want AUTHOR_PLACEHOLDER in the result.' + | ||
'For each path, you define operations (HTTP methods) that can be used to access that path.' + | ||
'IMPORTANT: Each operation includes a MANDATORY *operationId* property, which should be a unique string matching the operations name.' + |
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.
Update the rule a bit, but still could see some responses failing. So that's why I added a mandatory check above.
|
||
// Step 7: use the strategy to generate the OAS | ||
// promptGenerationOrchestrator.bid(); | ||
// Step 7: use the strateg to generate the OAS | ||
const openApiDocument = await promptGenerationOrchestrator.generateOASWithStrategySelectedByBidRule( |
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.
@mingxuanzhangsfdx what happens if there is a tie on number of calls?
* Mz/apply generation strategy (#6018) * feat: integrate apex action controller with prompt generation orchestrator * chore: update framework * chore: add error entries * feat: whole class gen strategy (#6024) * feat: integrate apex action controller with prompt generation orchestrator * feat: whole class gen strategy * chore: sort imports * chore: asdfghj --------- Co-authored-by: mingxuanzhang <mingxuanzhang@salesforce.com> * feat: update jar with changes in lsp to add comments in context (#6028) * feat: update jar with changes in lsp to add comments in context (#6025) * feat: update jar with changes in lsp to add comments in context * feat: update jar with changes in lsp to add comments in context * fix: add comment property to context (#6026) @W-17645605@ moved comments from ApexClassOASGatherContextResponse and added comment proeprty to class/method/property --------- Co-authored-by: peternhale <peternhale@users.noreply.github.com> * feat: method-by-method OAS doc generation strategy (#6023) * feat: create open api doc method by method * chore: update for generating ESR * chore: refine * chore: refine prompt structure * feat: enable comments for prompt generation * chore: sync jorje jar * chore: sync generation strategy with latest change (#6031) * feat: update jar with changes in lsp to add comments in context (#6025) * feat: update jar with changes in lsp to add comments in context * feat: update jar with changes in lsp to add comments in context * fix: add comment property to context (#6026) @W-17645605@ moved comments from ApexClassOASGatherContextResponse and added comment proeprty to class/method/property * chore: remove deploy and retrieve commands for oas and hide create oas from method command (#6029) * Madhur/w 17619393 (#6017) * feat: adding spectral library and validation based on OAS3 spec * feat: adding spectral library and validation based on OAS3 spec * feat: adding spectral library and validation based on OAS3 spec * feat: adding spectral library and validation based on OAS3 spec * fix: increase minimum supported node version to v20.17.0 * feat: adding spectral library and validation based on OAS3 spec --------- Co-authored-by: Daphne Yang <daphne.yang@salesforce.com> --------- Co-authored-by: Cristina Cañizales <113132642+CristiCanizales@users.noreply.github.com> Co-authored-by: peternhale <peternhale@users.noreply.github.com> Co-authored-by: madhur310 <madhur.shrivastava@salesforce.com> Co-authored-by: Daphne Yang <daphne.yang@salesforce.com> * chore: remove eslint disable * chore: move schemas to oas folder * chore: sort imports --------- Co-authored-by: Mingxuan Zhang <132491513+mingxuanzhangsfdx@users.noreply.github.com> Co-authored-by: mingxuanzhang <mingxuanzhang@salesforce.com> Co-authored-by: peternhale <peternhale@users.noreply.github.com> Co-authored-by: madhur310 <madhur.shrivastava@salesforce.com> Co-authored-by: Daphne Yang <daphne.yang@salesforce.com>
What does this PR do?
Implement the strategy of generating OAS within a class method by method, and combine the separate YAML into one.
What issues does this PR fix or reference?
@W-17587223@
Functionality Before
only generate the OAS doc on class level.
Functionality After
method-by-method strategy is available, which could potentially avoid the prompt size limit.