Skip to content
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

split cli #586

Merged
merged 17 commits into from
Jul 19, 2024
Merged

split cli #586

merged 17 commits into from
Jul 19, 2024

Conversation

pelikhan
Copy link
Member

@pelikhan pelikhan commented Jul 18, 2024

Improve startup time by moving various non-critical dependencies as dynamic imports

  • The math_eval tool has been updated in two ways. First, in system.mdx an await keyword has been added when calling the parsers.math function, indicating that this is now an asynchronous operation 🔄. Second, in system.math.genai.js similarly, an await has been added when calling parsers.math, again suggesting this function is now asynchronous.
  • A new library mathjs has been added as a dependency in the package.json of packages cli and core, likely to provide advanced math operations for the application 🧮.
  • A new azuretoken.ts file has been created in the packages/cli/src directory. This looks to be handling Azure token creation logic, by importing the DefaultAzureCredential from @azure/identity 🆔.
  • The Azure token handling logic in nodehost.ts has been updated with the content from the newly added azuretoken.ts file. This suggests a refactoring of the Azure token logic into its own module for better code organization and reuse ⌗.
  • Some file dependency imports (like mammoth for docx parsing and mathjs for math operations) have been changed to dynamic imports, likely to help improve application startup performance by only loading the actual module code when it's needed (lazy-loading) 🚀.
  • The xlsx file parser has been changed from a synchronous function to an async function. This will allow the .xlsx parsing to occur in asynchronous manner, likely improving the performance of this operation in the system 📊.
  • A minor code readability improvement has been made in packages cli & core's package.json by increasing the indentation of the file content, making it easier to read 📝.
  • Last but not least, there were other minor changes such as updating the code format/style in some files and fixing a missing new line at the end of the files. These changes are typically done to keep the codebase clean and consistent, as well as adhering to best practices in coding style 💅.

generated by pr-describe

@@ -548,7 +548,7 @@ defTool("math_eval", "Evaluates a math expression", {
required: ["expression"],
}, async (args) => {
const { expression } = args
return "" + (parsers.math(expression) ?? "?")
return "" + (await parsers.math(expression) ?? "?")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function is now awaited, but the containing function is not marked as async.

generated by pr-docs-review-commit async_missing

)
}
if (!this._azureToken)
this._azureToken = await createAzureToken(signal)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no error handling for the createAzureToken function. If it fails, the error will not be caught and handled properly, which could lead to unexpected behavior. Consider adding a try-catch block around this function call. 😊

generated by pr-review-commit missing_error_handling

@@ -94,7 +95,8 @@ export function createParsers(options: {
await resolveFileContent(file, { trace })
return await treeSitterQuery(file, query, { trace })
},
math: (expression) => MathTryEvaluate(expression, { trace }),
math: async (expression) =>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The math function is declared as async but there is no await keyword used in its body. This could lead to unexpected behavior as the function might not wait for promises to resolve before continuing execution. Please ensure that the async keyword is used correctly. 😊

generated by pr-review-commit async_without_await

try {
return XLSXParse(data, options)
return await XLSXParse(data, options)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no error handling for the XLSXParse function. If it fails, the error will not be caught and handled properly, which could lead to unexpected behavior. Consider adding a try-catch block around this function call. 😊

generated by pr-review-commit missing_error_handling

@@ -210,7 +210,7 @@ const captures = await parsers.code(file, "(interface_declaration) @i")
The `parsers.math` function uses [mathjs](https://mathjs.org/) to parse a math expression.

```js

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function should be used with await as it returns a Promise.

generated by pr-docs-review-commit await_usage

@@ -548,7 +548,7 @@ defTool("math_eval", "Evaluates a math expression", {
required: ["expression"],
}, async (args) => {
const { expression } = args

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function should be used with await as it returns a Promise.

generated by pr-docs-review-commit await_usage

@@ -15,6 +13,7 @@ export async function DOCXTryParse(
): Promise<string> {
const { trace } = options || {}
try {
const { extractRawText } = await import("mammoth")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic import of "mammoth" module is used. This could lead to performance issues as it might cause delays in execution. Consider importing the module at the top of the file if it does not have side effects. 😊

generated by pr-review-commit dynamic_import

@@ -94,7 +95,8 @@ export function createParsers(options: {
await resolveFileContent(file, { trace })
return await treeSitterQuery(file, query, { trace })
},
math: (expression) => MathTryEvaluate(expression, { trace }),
math: async (expression) =>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The math function is now asynchronous but the function signature in the interface Parsers in packages/core/src/types/prompt_template.d.ts has not been updated to reflect this change. This could lead to confusion and potential bugs. Please update the interface to match the implementation. 😊

generated by pr-review-commit async_function

Copy link

The changes in the pull request consist of the following modifications:

  1. Import of modules has been moved inside functions to improve performance by loading them only when necessary.
  2. The createAzureToken function has been refactored out of the NodeHost class into a separate module.
  3. Async-await syntax has been introduced in place of direct function returns for methods that include asynchronous operations.

The changes look good overall with the following specific observations:

  1. The usage of dynamic imports will help to improve the startup time of the code by loading modules only when they are needed.
  2. Refactoring of the createAzureToken function provides a more modular structure and allows for easier unit testing.
  3. The async-await syntax introduced improves readability and error handling in asynchronous code.

However, one potential concern that I have is with error handling. The updates added several await keywords, but did not add try-catch blocks around them. This might lead to unhandled promise rejections if the promises reject.

For example:

+export async function MathTryEvaluate(
     expr: string,
     options?: { defaultValue?: number } & TraceOptions
-): string | number | undefined {
+): Promise<string | number | undefined> {
     const { trace, defaultValue } = options || {}
     try {
         if (!expr) return defaultValue
+        const { evaluate } = await import("mathjs")
         const res = evaluate(expr)
         return res
     } catch (e) {

In the above code snippet, if import("mathjs") rejects, it will lead to an unhandled promise rejection.

This could be handled by updating the code to:

 export async function MathTryEvaluate(
     expr: string,
     options?: { defaultValue?: number } & TraceOptions
 ): Promise<string | number | undefined> {
     const { trace, defaultValue } = options || {}
     try {
         if (!expr) return defaultValue
+        let evaluate;
+        try {
+            const mathjs = await import("mathjs");
+            evaluate = mathjs.evaluate;
+        } catch (e) {
+            console.error(`Failed to import mathjs: ${e}`);
+            return defaultValue;
+        }
         const res = evaluate(expr)
         return res
     } catch (e) {

So, with the exception of the missing error handling for promises, the changes look fine. Apart from this, LGTM 🚀.

generated by pr-review

@@ -272,14 +272,6 @@ for the current model. This is useful for estimating the number of prompts that
const count = parsers.tokens("...")
```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The section on parsers.math is duplicated and should be removed as it is already defined under the .env section.

generated by pr-docs-review-commit duplicate_section

@@ -210,7 +210,7 @@ const captures = await parsers.code(file, "(interface_declaration) @i")
The `parsers.math` function uses [mathjs](https://mathjs.org/) to parse a math expression.

```js
const res = parsers.math("1 + 1")
const res = await parsers.math("1 + 1")
```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function usage example should use await consistently with the function being asynchronous.

generated by pr-docs-review-commit async_mismatch

@@ -548,7 +548,7 @@ defTool("math_eval", "Evaluates a math expression", {
required: ["expression"],
}, async (args) => {
const { expression } = args
return "" + (parsers.math(expression) ?? "?")
return "" + (await parsers.math(expression) ?? "?")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function usage example should use await consistently with the function being asynchronous.

generated by pr-docs-review-commit async_mismatch

@@ -49,13 +49,14 @@ export function createParsers(options: {
CSV: (text, options) =>
CSVTryParse(filenameOrFileToContent(text), options),
XLSX: async (file, options) =>
XLSXTryParse(await host.readFile(file?.filename), options),
await XLSXTryParse(await host.readFile(file?.filename), options),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XLSXTryParse function is async and returns a promise, but it's not being awaited here. This could lead to unexpected behavior. Please add await before XLSXTryParse. 🔄

generated by pr-review-commit async_await

@@ -984,7 +984,7 @@ interface Parsers {
* Parses and evaluates a math expression
* @param expression math expression compatible with mathjs
*/
math(expression: string): string | number | undefined
math(expression: string): Promise<string | number | undefined>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The math function in the Parsers interface is declared to return a Promise<string | number | undefined>, but the actual implementation of the function in parsers.ts returns string | number | undefined. This discrepancy could lead to type errors. Please ensure that the function's return type matches its implementation. 😊

generated by pr-review-commit incorrect_type

const { trace, defaultValue } = options || {}
try {
if (!expr) return defaultValue
const { evaluate } = await import("mathjs")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dynamic import of 'mathjs' can lead to performance issues and makes the code harder to statically analyze. Consider importing this module at the top of the file if it does not have side effects. 😊

generated by pr-review-commit dynamic_import

@@ -49,13 +49,14 @@ export function createParsers(options: {
CSV: (text, options) =>
CSVTryParse(filenameOrFileToContent(text), options),
XLSX: async (file, options) =>
XLSXTryParse(await host.readFile(file?.filename), options),
await XLSXTryParse(await host.readFile(file?.filename), options),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The await inside the XLSXTryParse function call is inside a loop. This can lead to performance issues as it forces each iteration of the loop to wait for the promise to resolve before continuing. Consider refactoring this code to use Promise.all to allow the promises to resolve concurrently. 😊

generated by pr-review-commit await_in_loop

@@ -210,7 +210,7 @@ const captures = await parsers.code(file, "(interface_declaration) @i")
The `parsers.math` function uses [mathjs](https://mathjs.org/) to parse a math expression.

```js
const res = parsers.math("1 + 1")
const res = await parsers.math("1 + 1")
```

## .env

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate section 'math' in documentation.

generated by pr-docs-review-commit duplicate_section

@@ -49,13 +49,14 @@ export function createParsers(options: {
CSV: (text, options) =>
CSVTryParse(filenameOrFileToContent(text), options),
XLSX: async (file, options) =>
XLSXTryParse(await host.readFile(file?.filename), options),
await XLSXTryParse(await host.readFile(file?.filename), options),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XLSXTryParse function is asynchronous and returns a promise, but it's not being awaited here. This could lead to unexpected behavior. Please use the await keyword to ensure the promise is resolved before proceeding. 🔄

generated by pr-review-commit async_await_usage

@@ -984,7 +984,7 @@ interface Parsers {
* Parses and evaluates a math expression
* @param expression math expression compatible with mathjs
*/
math(expression: string): string | number | undefined
math(expression: string): Promise<string | number | undefined>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing the return type of the math function from string | number | undefined to Promise<string | number | undefined> is a breaking change. This could break existing code that uses this function.

generated by pr-review-commit breaking_change

const { trace, defaultValue } = options || {}
try {
if (!expr) return defaultValue
const { evaluate } = await import("mathjs")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The evaluate function from mathjs is called without any error handling. If the evaluation fails (for example, if the expression is not valid), an unhandled exception will be thrown. Consider adding error handling to improve the robustness of the code. 😊

generated by pr-review-commit missing_error_handling

@@ -49,13 +49,14 @@ export function createParsers(options: {
CSV: (text, options) =>
CSVTryParse(filenameOrFileToContent(text), options),
XLSX: async (file, options) =>
XLSXTryParse(await host.readFile(file?.filename), options),
await XLSXTryParse(await host.readFile(file?.filename), options),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XLSXTryParse function is now asynchronous, but it's called without await here. This could lead to unexpected behavior as the function might not have completed before its result is used. Consider adding await before the function call. 😊

generated by pr-review-commit missing_await

@@ -210,7 +210,7 @@ const captures = await parsers.code(file, "(interface_declaration) @i")
The `parsers.math` function uses [mathjs](https://mathjs.org/) to parse a math expression.

```js
const res = parsers.math("1 + 1")
const res = await parsers.math("1 + 1")
```

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsers.math function call should be awaited with async.

generated by pr-docs-review-commit async_missing

@@ -49,13 +49,14 @@ export function createParsers(options: {
CSV: (text, options) =>
CSVTryParse(filenameOrFileToContent(text), options),
XLSX: async (file, options) =>
XLSXTryParse(await host.readFile(file?.filename), options),
await XLSXTryParse(await host.readFile(file?.filename), options),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XLSX function is declared as async but there is no await keyword used in its body. This might lead to unexpected behavior. Please ensure that the function is using the await keyword correctly. 🧐

generated by pr-review-commit async_function_without_await

@@ -15,6 +13,7 @@ export async function DOCXTryParse(
): Promise<string> {
const { trace } = options || {}
try {
const { extractRawText } = await import("mammoth")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mammoth module is dynamically imported but there is no check to ensure that the module is actually installed. Consider adding a check to ensure that the module is installed before importing it.

generated by pr-review-commit missing_dependency

@pelikhan pelikhan merged commit 7f328c0 into main Jul 19, 2024
8 checks passed
@pelikhan pelikhan deleted the splitcli branch July 19, 2024 08:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant