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

Add comments and documentation, replace angle brackets in CLI documentation #724

Merged
merged 5 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/src/content/docs/reference/cli/run.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@
`run` takes one or more [glob](<https://en.wikipedia.org/wiki/Glob_(programming)>) patterns to match files in the workspace.

```bash sh
npx genaiscript run <script> "**/*.md" "**/*.ts"

Check failure on line 40 in docs/src/content/docs/reference/cli/run.mdx

View workflow job for this annotation

GitHub Actions / build

HTML entities should not be used in markdown files; replace '&lt;' with '<' and '&gt;' with '>'.

Choose a reason for hiding this comment

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

HTML entities should not be used in markdown files; replace '<' with '<' and '>' with '>'.

generated by pr-docs-review-commit html_entity

```

### --excluded-files <files...>
### --excluded-files &lt;files...&gt;

Excludes the specified files from the file set.

Expand All @@ -59,10 +59,10 @@
## Output

### --prompt

Check failure on line 62 in docs/src/content/docs/reference/cli/run.mdx

View workflow job for this annotation

GitHub Actions / build

HTML entities should not be used in markdown files; replace '&lt;' with '<' and '&gt;' with '>'.

Choose a reason for hiding this comment

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

HTML entities should not be used in markdown files; replace '<' with '<' and '>' with '>'.

generated by pr-docs-review-commit html_entity

Skips the LLM invocation and only prints the expanded system and user chat messages.

### --out <file|directory>
### --out &lt;file|directory&gt;

Saves the results in a JSON file, along with markdown files of the output and the trace.

Expand Down
60 changes: 59 additions & 1 deletion docs/src/content/docs/samples/cmt.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
for (const file of files) {
console.log(`processing ${file.filename}`)
... add comments
... format generated code (optional) -- keep things consistent
... build generated -- let's make sure it's still valid code
... check that only comments were changed -- LLM as judge

Choose a reason for hiding this comment

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

Comments in code snippets should be more descriptive and not use ellipsis '...'.

generated by pr-docs-review-commit comment_guidance

... save changes
}
```
Expand All @@ -66,14 +69,69 @@

We provide a detailed set of instructions to the AI for how to analyze and comment on the code.

## Judge results with LLM

We issue one more prompt to judge the modified code and make sure the code is not modified.

```ts
async function checkModifications(filename: string): Promise<boolean> {
const diff = await host.exec(`git diff ${filename}`)
if (!diff.stdout) return false
const res = await runPrompt(
(ctx) => {
ctx.def("DIFF", diff.stdout)
ctx.$`You are an expert developer at all programming languages.

Your task is to analyze the changes in DIFF and make sure that only comments are modified.
Report all changes that are not comments and print "MODIFIED".
`
},
{
cache: "cmt-check",
}
)

const modified = res.text?.includes("MODIFIED")
console.log(`code modified, reverting...`)

Choose a reason for hiding this comment

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

Console log statement 'code modified, reverting...' should be inside a conditional block to reflect the actual modification status.

generated by pr-docs-review-commit log_without_condition

return modified
}
```

## How to Run the Script

To run this script, you'll first need to install the GenAIScript CLI. [Follow the installation guide here](https://microsoft.github.io/genaiscript/getting-started/installation).

```shell
```sh

Check failure on line 104 in docs/src/content/docs/samples/cmt.mdx

View workflow job for this annotation

GitHub Actions / build

Incorrect code fence 'sh' should be 'shell' for consistency with the rest of the documentation.

Choose a reason for hiding this comment

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

Incorrect code fence 'sh' should be 'shell' for consistency with the rest of the documentation.

generated by pr-docs-review-commit incorrect_code_fence

Choose a reason for hiding this comment

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

Replace 'shell' with 'sh' to maintain consistency in code block language identifiers.

generated by pr-docs-review-commit shell_to_sh

genaiscript run cmt
```

## Format and build

One important aspect is to normalize and valid the AI generated code. The user can provide a `format` command to run a formatter
and a `build` command to check if the code is still valid.

```ts

script({...,
parameters: {
format: {
type: "string",
description: "Format source code command",
},
build: {
type: "string",
description: "Build command",
},
},
})

const { format, build } = env.vars.build

Check failure on line 128 in docs/src/content/docs/samples/cmt.mdx

View workflow job for this annotation

GitHub Actions / build

Incorrect variable access, 'env.vars.build' should be 'env.vars' to access 'format' and 'build' variables correctly.

Choose a reason for hiding this comment

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

Incorrect variable access, 'env.vars.build' should be 'env.vars' to access 'format' and 'build' variables correctly.

generated by pr-docs-review-commit incorrect_variable_access

```

```sh
genaiscript run cmt --vars "build=npm run build" "format=npm run format"

Check failure on line 132 in docs/src/content/docs/samples/cmt.mdx

View workflow job for this annotation

GitHub Actions / build

Incorrect flag format, use '--vars.build="npm run build"' and '--vars.format="npm run format"' instead of the current format.

Choose a reason for hiding this comment

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

Incorrect flag format, use '--vars.build="npm run build"' and '--vars.format="npm run format"' instead of the current format.

generated by pr-docs-review-commit incorrect_flag_format

```

## Full source ([GitHub](https://github.com/microsoft/genaiscript/blob/main/packages/vscode/genaisrc/cmt.genai.mts))

<Code code={source} wrap={true} lang="ts" title="cmt.genai.mts" />
3 changes: 2 additions & 1 deletion packages/core/src/aici.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function renderAICINode(node: AICINode) {
if (regex) args.push(`regex: ${regex.toString()}`)
return `await gen({${args.join(`,\n`)}})`
default:
return "undefined" // Fallback case for unknown node types
return "undefined" // Fallback for unknown node types
}
}

Expand Down Expand Up @@ -64,6 +64,7 @@ export async function renderAICI(functionName: string, root: PromptNode) {
let indent: string = "" // Current indentation level
const push = (text: string) => program.push(indent + text) // Add text with current indentation
const pushString = (text: string) => {
// Pushes a string to the program if it's not empty
if (text !== undefined && text !== null && text !== "")
push("await $`" + escapeJavascriptString(text) + "`")
}
Expand Down
12 changes: 9 additions & 3 deletions packages/core/src/annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
* of annotations into different formats for integration with CI/CD tools.
*/

// Regular expression for matching GitHub Actions annotations
// Regular expression for matching GitHub Actions annotations.
// Example: ::error file=foo.js,line=10,endLine=11::Something went wrong.
const GITHUB_ANNOTATIONS_RX =
/^\s*::(?<severity>notice|warning|error)\s*file=(?<file>[^,]+),\s*line=(?<line>\d+),\s*endLine=(?<endLine>\d+)\s*(,\s*code=(?<code>[^,:]+)?\s*)?::(?<message>.*)$/gim

// Regular expression for matching Azure DevOps annotations
// Regular expression for matching Azure DevOps annotations.
// Example: ##vso[task.logissue type=warning;sourcepath=foo.cs;linenumber=1;]Found something.
const AZURE_DEVOPS_ANNOTATIONS_RX =
/^\s*##vso\[task.logissue\s+type=(?<severity>error|warning);sourcepath=(?<file>);linenumber=(?<line>\d+)(;code=(?<code>\d+);)?[^\]]*\](?<message>.*)$/gim

// Regular expression for matching TypeScript build annotations
// Regular expression for matching TypeScript build annotations.
// Example: foo.ts:10:error TS1005: ';' expected.
const TYPESCRIPT_ANNOTATIONS_RX =
/^(?<file>[^:\s].*?):(?<line>\d+)(?::(?<endLine>\d+))?(?::\d+)?\s+-\s+(?<severity>error|warning)\s+(?<code>[^:]+)\s*:\s*(?<message>.*)$/gim
Expand Down Expand Up @@ -71,12 +71,14 @@ export function parseAnnotations(text: string): Diagnostic[] {
* @returns A formatted GitHub Action command string.
*/
export function convertDiagnosticToGitHubActionCommand(d: Diagnostic) {
// Maps DiagnosticSeverity to GitHub Action severity strings.
const sevMap: Record<DiagnosticSeverity, string> = {

Choose a reason for hiding this comment

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

Missing semicolon

generated by pr-review-commit missing_semi

["info"]: "notice", // Maps 'info' to 'notice'
["warning"]: "warning",
["error"]: "error",
}

// Construct GitHub Action command string with necessary details.
return `::${sevMap[d.severity] || d.severity} file=${d.filename}, line=${d.range[0][0]}, endLine=${d.range[1][0]}::${d.message}`
}

Expand All @@ -87,8 +89,10 @@ export function convertDiagnosticToGitHubActionCommand(d: Diagnostic) {
* @returns A formatted Azure DevOps command string.
*/
export function convertDiagnosticToAzureDevOpsCommand(d: Diagnostic) {
// Handle 'info' severity separately with a debug message.
if (d.severity === "info") return `##[debug]${d.message} at ${d.filename}`
else
// Construct Azure DevOps command string with necessary details.
return `##vso[task.logissue type=${d.severity};sourcepath=${d.filename};linenumber=${d.range[0][0]}]${d.message}`

Choose a reason for hiding this comment

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

Missing semicolon

generated by pr-review-commit missing_semi

}

Expand All @@ -99,11 +103,13 @@ export function convertDiagnosticToAzureDevOpsCommand(d: Diagnostic) {
* @returns A string of formatted Markdown annotations.
*/
export function convertAnnotationsToMarkdown(text: string): string {
// Maps severity levels to Markdown admonition types.
const severities: Record<string, string> = {
error: "CAUTION",
warning: "WARNING",
notice: "NOTE",
}
// Replace GitHub and Azure DevOps annotations with Markdown format.
return text

Choose a reason for hiding this comment

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

Missing semicolon

generated by pr-review-commit missing_semi

?.replace(
GITHUB_ANNOTATIONS_RX,
Expand Down
9 changes: 6 additions & 3 deletions packages/core/src/chatrender.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
// Import statements for various message parameters used in chat rendering.
import {
ChatCompletionAssistantMessageParam,
ChatCompletionMessageParam,
ChatCompletionSystemMessageParam,
ChatCompletionToolMessageParam,
ChatCompletionUserMessageParam,
} from "./chattypes"

// Import utility functions for JSON5 parsing, markdown formatting, and YAML stringification.
import { JSON5TryParse } from "./json5"
import { details, fenceMD } from "./markdown"
import { YAMLStringify } from "./yaml"
Expand Down Expand Up @@ -83,9 +86,9 @@ export function renderMessagesToMarkdown(
) {
// Set default options for filtering message roles.
const {
system = undefined,
user = undefined,
assistant = true,
system = undefined, // Include system messages unless explicitly set to false.
user = undefined, // Include user messages unless explicitly set to false.
assistant = true, // Include assistant messages by default.
} = options || {}

const res: string[] = []
Expand Down
97 changes: 69 additions & 28 deletions packages/core/src/chattypes.ts
Original file line number Diff line number Diff line change
@@ -1,69 +1,103 @@
/**
* This module defines TypeScript types and interfaces for chat completions using the OpenAI API.
* These types represent structured data for various chat-related functionalities.
*
* Tags: TypeScript, OpenAI, Chat, Types, Interfaces
*/

import OpenAI from "openai"

/**
* Interface representing a custom AI Chat Interface request.
*/
export interface AICIRequest {
role: "aici"
content?: string
error?: unknown
functionName: string
role: "aici" // The role for this type of request
content?: string // Optional content of the request
error?: unknown // Optional error information
functionName: string // Name of the function being requested
}

// Aliases for OpenAI chat completion types

// Text content part of a chat completion
export type ChatCompletionContentPartText =
OpenAI.Chat.Completions.ChatCompletionContentPartText

// General content part of a chat completion
export type ChatCompletionContentPart =
OpenAI.Chat.Completions.ChatCompletionContentPart

// Tool used in a chat completion
export type ChatCompletionTool = OpenAI.Chat.Completions.ChatCompletionTool

// Chunk of a chat completion response
export type ChatCompletionChunk = OpenAI.Chat.Completions.ChatCompletionChunk

// Parameters for a system message in a chat completion
export type ChatCompletionSystemMessageParam =
OpenAI.Chat.Completions.ChatCompletionSystemMessageParam

// Parameters for a tool message in a chat completion
export type ChatCompletionToolMessageParam =
OpenAI.Chat.Completions.ChatCompletionToolMessageParam

/**
* Type representing parameters for chat completion messages, including custom AICIRequest.
*/
export type ChatCompletionMessageParam =
| OpenAI.Chat.Completions.ChatCompletionMessageParam
| AICIRequest

/**
* Type representing a request to create a chat completion, extending from OpenAI's
* streaming parameters minus the 'messages' property.
*/
export type CreateChatCompletionRequest = Omit<
OpenAI.Chat.Completions.ChatCompletionCreateParamsStreaming,
"messages"
> & {
/**
* A list of messages comprising the conversation so far.
* [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models).
*/
// messages: Array<ChatCompletionMessageParam>;
messages: ChatCompletionMessageParam[]
}

// Parameters for an assistant message in a chat completion
export type ChatCompletionAssistantMessageParam =
OpenAI.Chat.Completions.ChatCompletionAssistantMessageParam

// Parameters for a user message in a chat completion
export type ChatCompletionUserMessageParam =
OpenAI.Chat.Completions.ChatCompletionUserMessageParam

// Image content part of a chat completion
export type ChatCompletionContentPartImage =
OpenAI.Chat.Completions.ChatCompletionContentPartImage

// Parameters for creating embeddings
export type EmbeddingCreateParams = OpenAI.Embeddings.EmbeddingCreateParams

// Response type for creating embeddings
export type EmbeddingCreateResponse = OpenAI.Embeddings.CreateEmbeddingResponse

/**
* Interface representing a call to a chat completion tool.
*/
export interface ChatCompletionToolCall {
id: string
name: string
arguments?: string
id: string // Unique identifier for the tool call
name: string // Tool name being called
arguments?: string // Optional arguments for the tool
}

/**
* Interface representing a response from chat completion.
*/
export interface ChatCompletionResponse {
text?: string
cached?: boolean
variables?: Record<string, string>
toolCalls?: ChatCompletionToolCall[]
finishReason?:
text?: string // Optional text response
cached?: boolean // Indicates if the response was cached
variables?: Record<string, string> // Optional variables associated with the response
toolCalls?: ChatCompletionToolCall[] // List of tool calls made during the response
finishReason?: // Reason why the chat completion finished
| "stop"
| "length"
| "tool_calls"
Expand All @@ -72,24 +106,31 @@ export interface ChatCompletionResponse {
| "fail"
}

// Alias for OpenAI's API error type
export const ModelError = OpenAI.APIError

/**
* Interface representing a progress report for chat completions.
*/
export interface ChatCompletionsProgressReport {
tokensSoFar: number
responseSoFar: string
responseChunk: string
inner: boolean
tokensSoFar: number // Number of tokens processed so far
responseSoFar: string // Partial response generated so far
responseChunk: string // Current chunk of response being processed
inner: boolean // Indicates if this is an inner report
}

/**
* Interface representing options for chat completions.
*/
export interface ChatCompletionsOptions {
partialCb?: (progress: ChatCompletionsProgressReport) => void
requestOptions?: Partial<Omit<RequestInit, "signal">>
maxCachedTemperature?: number
maxCachedTopP?: number
cache?: boolean | string
cacheName?: string
retry?: number
retryDelay?: number
maxDelay?: number
inner: boolean
partialCb?: (progress: ChatCompletionsProgressReport) => void // Callback for partial responses
requestOptions?: Partial<Omit<RequestInit, "signal">> // Custom request options
maxCachedTemperature?: number // Max temperature for caching responses
maxCachedTopP?: number // Max top-p for caching responses
cache?: boolean | string // Cache setting or cache name
cacheName?: string // Name of the cache to use
retry?: number // Number of retries for failed requests
retryDelay?: number // Delay between retries
maxDelay?: number // Maximum delay for retry attempts
inner: boolean // Indicates if the option is for inner processing
}
Loading
Loading