Skip to content

Commit

Permalink
Merge pull request #2 from Arjun-A-I/ai
Browse files Browse the repository at this point in the history
AI integration to Console
  • Loading branch information
riya461 authored Jul 28, 2024
2 parents c541405 + 3ec7fd7 commit 03db77d
Show file tree
Hide file tree
Showing 9 changed files with 473 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ typings/
# dotenv environment variables file
.env
.env.test

.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache

Expand Down
36 changes: 36 additions & 0 deletions editor/src/ai/openai.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import axios from 'axios';
import { generateRightRegularGrammarPrompt } from './rg_prompt';

// const OPENAI_API_KEY = import.meta.env.VITE_OPENAI_API_KEY;
const OPENAI_API_KEY = "sk-arjun-ai-6W4PtIcGb7g6XNAZStLJT3BlbkFJ7GUh2rjPm5uClCMoUd14";
const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions';

export async function generateRightRegularGrammar(userRequest: string, exampleStrings: string[] = []): Promise<string> {
if (!OPENAI_API_KEY) {
throw new Error('OpenAI API key is not set. Please check your environment variables.');
}

const prompt = generateRightRegularGrammarPrompt(userRequest,exampleStrings);

try {
const response = await axios.post(
OPENAI_API_URL,
{
model: "gpt-4o", // or "gpt-4" if you have access
messages: [{ role: "user", content: prompt }],
temperature: 0.0,
},
{
headers: {
'Authorization': `Bearer ${OPENAI_API_KEY}`,
'Content-Type': 'application/json',
},
}
);

return response.data.choices[0].message.content;
} catch (error) {
console.error('Error calling OpenAI API:', error);
throw new Error('Failed to generate response from OpenAI');
}
}
82 changes: 82 additions & 0 deletions editor/src/ai/rg_prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
export const generateRightRegularGrammarPrompt = (userRequest: string,exampleStrings:string[]=[]): string => `
You are tasked with generating a right-regular grammar based on a user request and validating it against example strings. Follow these instructions carefully:
1. A right-regular grammar is a formal grammar (N, Σ, P, S) where all production rules in P are of the following forms:
A → a
A → a B
A → ε
where A, B ∈ N are non-terminal symbols, a ∈ Σ is a terminal symbol, and ε denotes the empty string.
Ensure that non-terminal symbols can derive terminal symbols either directly or indirectly.Keep the grammar simple and avoid unnecessary rules.The process of deriving a string should proceed from the start symbol to terminal symbols, using rightmost derivations
2. Use the following syntax for writing the grammar:
- Start symbol: S
- Follow symbol: ->
- Empty string: ε or λ or #
- Or symbol: |
- End each rule with: .
- Comments: // comment
- Non-terminals: start with uppercase character
- Terminals: start with any other character
Process:
1. Generate a right-regular grammar based on the user request.
2. Validate the grammar against the provided example strings.
3. If the grammar cannot generate all example strings, modify and retry.
4. Provide the final grammar that satisfies all examples.
Here are some few-shot examples to guide you:
<example-1>
S -> 0 A | 1 B .
A -> 0 S | 1 C .
B -> 0 C | 1 S .
C -> 0 B | 1 A .
</example-1>
<example-2>
S -> a A .
A -> b B .
B -> a B | b B | # .
</example-2>
<example-3>
S -> A | 1 B | 0 .
A -> 0 A | S .
B -> 0 S | 1 B | # .
</example-3>
<example-4>
S -> 0 S | 1 S | 0 A | 1 B .
A -> 1 .
B -> 0 .
</example-4>
3. Generate a right-regular grammar based on this user request:
<user_request>
${userRequest}
</user_request>
4. Validate the grammar against these example strings:
<example_strings>
${exampleStrings}
</example_strings>
5. If the grammar fails to generate any of the example strings, retry generating the grammar. Continue this process until you have a grammar that can generate all the example strings or you have made 3 attempts.
6. Provide your final answer in the following format:
<answer>
<grammar>
[Insert the generated right-regular grammar here]
</grammar>
<validation>
[For each example string, state whether it can be generated by the grammar and provide a brief explanation]
</validation>
<conclusion>
[State whether the grammar successfully generates all example strings. If not, explain why it was not possible to create a grammar that satisfies all examples.]
</conclusion>
</answer>
Remember to think carefully about the grammar rules and how they relate to the example strings. If you're unsure about a step, you can use <scratchpad> tags to work through your thought process before providing the final answer.
`;
4 changes: 2 additions & 2 deletions editor/src/components/NewPlaygroundModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ import KeyboardKey from '../components/ui/KeyboardKey.vue';
const props = defineProps<{ show: boolean }>();
const emit = defineEmits<{ (e: 'close'): void }>();
const addNewPlayground = async (type: PlaygroundType) => {
playgrounds.push(newPlayground(`Program ${playgrounds.length + 1}`, type));
const addNewPlayground = async (type: PlaygroundType,input: string="") => {
playgrounds.push(newPlayground(`Program ${playgrounds.length + 1}`, type,input));
await nextTick();
router.replace({ params: { id: playgrounds.length-1 } });
emit('close');
Expand Down
106 changes: 103 additions & 3 deletions editor/src/utils/JitterConsole.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
import minimist from 'minimist';
import split from 'argv-split';
import { ConsoleStream, getActivePlayground, Playground, playgrounds } from '../store/code';
import { ConsoleStream, getActivePlayground, Playground,playgrounds, PlaygroundType } from '../store/code';
import { generateRightRegularGrammar } from '../ai/openai';
import { newPlayground } from '../store/code';
import { nextTick, watchEffect } from 'vue';
import router from '../router';

type CommandParamValue = number | string | boolean;
//Playground code from vue
const addNewPlayground = async (type: PlaygroundType,input: string="") => {
playgrounds.push(newPlayground(`Program ${playgrounds.length + 1}`, type,input));
await nextTick();
router.replace({ params: { id: playgrounds.length-1 } });
emit('close');
};

//Regex from reponse
function extractGrammar(input: string): string | undefined {
const grammarRegex = /<grammar>([\s\S]*?)<\/grammar>/;
const match = input.match(grammarRegex);

if (match && match[1]) {
return match[1].trim();
}

return undefined;
}

type CommandParamValue = number | string | boolean;
type CommandConfig = {
name: string,
version: string,
Expand All @@ -18,6 +41,7 @@ type CommandConfig = {
type: NumberConstructor | StringConstructor | BooleanConstructor,
default?: CommandParamValue,
alias?: string[],
description?: string,
}>,
handler: (playground: Playground, options: Record<string, CommandParamValue>, args: Record<string, CommandParamValue>) => unknown,
}>;
Expand Down Expand Up @@ -46,6 +70,7 @@ class JitterConsole {
constructor(config: CommandConfig) {
this.config = config;
JitterConsole.addHelp(config);
JitterConsole.addGenerate(config);
}

private static helpForCommand({ commands }: CommandConfig, command: string) {
Expand All @@ -61,7 +86,7 @@ class JitterConsole {
}

private static addHelp(config: CommandConfig) {
config.commands['help'] = {
config.commands['help'] = {
description: 'Get help for commands.<br/>Pass &lt;command&gt; to get help on specific command',
args: [
{
Expand All @@ -88,6 +113,62 @@ class JitterConsole {
};
}

private static addGenerate(config: CommandConfig) {
config.commands['generate'] = {
description: 'Generate and print a given string to the console with specified grammar type',
args: [
{
name: 'grammar_type',
type: String,
default: '',
},
{
name: 'string',
type: String,
default: '',
}
],
options: {
example: {
type: String,
alias: ['e'],
description: 'Provide example strings for grammar generation'
}
},
async handler(playground, options, args) {
const grammarType = args.grammar_type as string;
const inputString = args.string as string;
const exampleStrings = options.example ? (options.example as string).split(',') : [];

if (!grammarType) {
pushToStream(playground, 'Error', 'Error: Grammar type not specified. Please use "generate <grammar_type> <string>"');
return;
}

if (!['rg', 'cfg', 'tm'].includes(grammarType)) {
pushToStream(playground, 'Error', 'Error: Invalid grammar type. Supported types are rg, cfg, tm, and ai.');
return;
}

if (grammarType === 'rg') {
try {
const generatedString = await generateRightRegularGrammar(inputString, exampleStrings);
const grammar = extractGrammar(generatedString);
addNewPlayground("RG",grammar);
} catch (error: unknown) {
if (error instanceof Error) {
pushToStream(playground, 'Error', `Error generating AI response: ${error.message}`);
} else {
pushToStream(playground, 'Error', 'An unknown error occurred while generating AI response');
}
}
} else {
pushToStream(playground, 'Output', 'This grammar type is not yet implemented.');
}
}
};
}

/**
* Parse input command string and execute appropriate handler for that command
* @param input Command String
Expand All @@ -105,6 +186,21 @@ class JitterConsole {

const command = this.config.commands[commandName];

if (commandName === 'generate') {
const argv = minimist(commandStr.slice(1), {
string: ['example'],
alias: { e: 'example' }
});
const grammarType = argv._[0];
const generatedString = argv._.slice(1).join(' ');
const exampleOption: Record<string, CommandParamValue> = {};
if (argv.example) {
exampleOption.example = argv.example;
}
command.handler(playground, exampleOption, { grammar_type: grammarType, string: generatedString });
return;
}

const argv = minimist(commandStr.slice(1), {
default: Object.fromEntries(
Object.keys(command.options ?? {})
Expand Down Expand Up @@ -157,3 +253,7 @@ class JitterConsole {
}

export { JitterConsole, pushToStream };

function emit(arg0: string) {
throw new Error('Function not implemented.');
}
3 changes: 3 additions & 0 deletions editor/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ export default defineConfig({
allow: ['..'],
},
},
define: {
'process.env': process.env
}
})
Loading

0 comments on commit 03db77d

Please sign in to comment.