Skip to content

Commit

Permalink
uploaded from p5.js
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielWarfield1 authored May 2, 2024
1 parent c0618c7 commit 48db52c
Show file tree
Hide file tree
Showing 24 changed files with 123,556 additions and 0 deletions.
136 changes: 136 additions & 0 deletions AutoTA/Agent/agent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
class Agent{
constructor(apikey, iBlock, userContext, isTranscript){
this.apiKey = apikey;
this.iBlock = iBlock;
this.working_context = composePrompt(userContext, isTranscript)
this.promptFromWorkingContext()
}

//////////// triggers the agent (input) ////////////
promptFromWorkingContext(recursion = 0){

console.log('prompting model')

if (recursion > 3){
this.pushMessage('AutoTA got messed up, probably from failing to parse correctly. Try restarting the conversation or finding a new topic.', false)
return
}

console.log('---Working Context Slice---')
console.log(this.working_context.slice(-200))
console.log('---------------------------')

let modelResponsePromise = geminiQuery(this.working_context, this.apiKey)

modelResponsePromise.then((modelResponse) => {
let parsedComponents = this.parseResponse(modelResponse);
if (typeof parsedComponents === 'string') {
console.log('some issue on previous iteration')
let new_context = [parsedComponents].join('\n') + '\n';
this.working_context += new_context
this.promptFromWorkingContext(recursion+1)
return
}
let errorObservation = this.handleParsedComponents(parsedComponents)
if (!typeof errorObservation === "undefined"){
console.log('some issue on previous iteration')
let new_context = [model_response, result].join('\n') + '\n';
this.working_context += new_context
this.promptFromWorkingContext(recursion+1)
return
}
})

}


addObservation(userStr){
let new_context
if (!userStr.trim().length) {
new_context = `\nObservation: The student responded with an empty response.`;
}else{
new_context = `\nObservation: The student responded with "${userStr}"`;
}
this.working_context += new_context
}

//////////// request feedback (output) ////////////
pushMessage(message, isThought){
this.iBlock.addMessage(message, isThought)
}

requestPrompt(args){
try{
this.iBlock.addPrompt(args['prompt'])
}catch{
return 'Observation: The previous action resulted in an unknown error. Please try again, beginning with a Thought.'
}
}

requestChoice(args){
try{
this.iBlock.addChoice(args['prompt'], args['options'])
}catch{
return 'Observation: The previous action resulted in an unknown error. Please try again, beginning with a Thought.'
}
}

//////////// Parsing ///////////////
parseResponse(inputText) {
this.working_context += inputText
// const pattern = /(Thought|Action|Action Input): (.*?)(?=\n(?:Thought|Action|Action Input): |$)/gs;
const pattern = /(Thought|Action|Action Input): (.*?)(?=\n*(?:Thought|Action|Action Input): |$)/gs;
const matches = [...inputText.matchAll(pattern)];

const parsedComponents = [];

for (const match of matches) {
const component_name = match[1];
const component_content = match[2].trim();

if (component_name === 'Action Input') {
try {
const parsed_component = JSON.parse(component_content);
parsedComponents.push([component_name, parsed_component]);
} catch (e) {
console.log(`failed to parse: "${component_content}"`);
return 'Observation: The previous action input was not able to be parsed correctly due to the following error:\n\n{e}\n\n. Be sure to use correct and parsable JSON formatting. Please try again. Restate the Action you wish to run, and the Action Input';
}
} else {
parsedComponents.push([component_name, component_content]);
}
}

return parsedComponents;
}

//////////// Triggering Actions ///////////////
handleParsedComponents(parsedComponents) {
for (let i = 0; i < parsedComponents.length; i++) {
const component = parsedComponents[i];

if (component[0] === 'Thought') {
let message = `AutoTA is thinking...\n${component[1]}`
console.log(message);
this.pushMessage(message, true)
}

if (component[0] === 'Action') {
// Handling errors
if (i === parsedComponents.length - 1) {
return 'Observation: The previous action was malformed. No inputs were provided. Please try again, beginning with a Thought.';
} else if (parsedComponents[i + 1][0] !== 'Action Input') {
return 'Observation: The previous action was malformed. No inputs were provided. Please try again, beginning with a Thought.';
}

if (component[1].includes('requestInput')){
return this.requestPrompt(parsedComponents[i + 1][1])
}else if (component[1].includes('multipleChoice')){
return this.requestChoice(parsedComponents[i + 1][1])
}else{
return `Observation: The specified tool "${component[1]}" does not exist. The tool was not executed.`;
}
}
}
}
}
98 changes: 98 additions & 0 deletions AutoTA/Agent/prompting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Constructing Tool Descriptions
let TOOL_DESC = '';
let toolNames = '[';
TOOLS.forEach((tool, i) => {
const tooltip = `**Tool ${i}**\ntool name: ${tool.name}\ndescription: ${tool.description}\nexample: \`\`\`\n${tool.example}\n\`\`\`\nArguments: ${JSON.stringify(tool.arguments)}`;
TOOL_DESC += tooltip + '\n';
toolNames += `${tool.name}, `;
});
toolNames = toolNames.slice(0, -2) + ']';

// Constructing header
const SYSTEM_HEADER = `# Instructions
Your name is AutoTA. You are a teachers assistant designed to help students learn by providing summaries, answering questions, and performing quizzes. The student will provide context which will inform you what they would like to learn. At the beginning of the conversation you will ask the student what they need help with, then you will maintain a continual dialogue with the student in order to assist them.
## Communication Style
When conversing with a student:
- Attempt to recover and resume the conversation when there is an error. If there is an error, let the student know there was an error and try to pick up where you left off.
- If the user requests to be tested or quizzed, you can assume they want to be quizzed based on the student provided context to test their knowledge.
- If the user requests something comprehensive, it's advised to plan through a comprehensive list of steps within Thoughts.
- Assume the student wants to continue unless told otherwise.
- Don't assume the lesson is over unless the student asks for it to be over.
- If appropriate, try to use examples when providing students information. Especially with STEM topics.
- Do not ask the student to wait.
- When beginning a conversation, let the student know what you understand about the provided context
- If the student asked to be quizzed, don't ask if they want to continue. Assume they do unless you're told otherwise.
- Try to make quizzes as diverse as possible. Mix it up, don't just ask the same type of question.
- When asking a multiple choice question, one of the options should be correct.
- Thoughts should be long.
- If the student asks about open ended or broad topics, Provide them a list of more specific sub-topics that they might like to learn about.
- Only quiz the student if they want to be quizzed.
- Try to answer questions immediately and directly when possible. Be sure to include interesting and relvent additional information.
## Tools
You have access to a wide variety of tools. You are responsible for using the tools in any sequence you deem appropriate to complete the task at hand.
This may require breaking the task into subtasks and using different tools to complete each subtask.
You have access to the following tools:
---
${TOOL_DESC}
---
## Output Format
Please answer in the same language as the question and use the following format:
\`\`\`
Thought: The current language of the user is: (user's language). I need to use a tool to help me answer the question.
Action: tool name (one of [${toolNames}]) if using a tool.
Action Input: the input to the tool, in a JSON format representing the kwargs (e.g. {"input": "hello world", "num_beams": 5})
\`\`\`
Please ALWAYS start with a Thought.
Please NEVER create output that is not a Thought, Action, or Action Input.
Please use a valid JSON format for the Action Input. Do NOT do this {{"input": "hello world", "num_beams": 5}}.
Please always use escape quotations when outputting a value as a string. For example do this {"prompt": "the word is \\"Hello\\""}, NOT this {"prompt": "the word is "Hello""}
If this format is used, the user will respond in the following format:
\`\`\`
Observation: tool response
\`\`\`
You should keep repeating the above format indefinitely.`;

// Function for constructing prompt
function composePrompt(userInput, isTranscript = true, systemHeader = SYSTEM_HEADER) {
let tprompt;
if (isTranscript) {
tprompt = 'They provided a transcript of a lecture they attended, and want you to help them with the transcripts contents. This is the transcript:';
} else {
tprompt = 'This was their response:';
}

const prompt = `${systemHeader}
## Student Provided Context
The student was asked what they wanted to learn about. ${tprompt}
---
${userInput}
---
# Current Conversation
Below is the current conversation consisting of interleaving human and assistant messages.
Thought: I should introduce myself as AutoTA, and ask the student what they want to learn about based on the context they provided. I'll tell them the topic of the context, then I'll ask them an open ended question about what they would like to learn.`;
return prompt;
}

// const systemPrompt = composePrompt('I want help learning about python', false);
// console.log(systemPrompt);
19 changes: 19 additions & 0 deletions AutoTA/Agent/tools.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 53 additions & 0 deletions AutoTA/Elements/choiceelement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
class ChoiceElement extends PromptElement{
constructor(xmargin, prompt, choices, hook) {
for(let i=0; i<choices.length; i++) {
prompt += `\n\n${i+1}: ${choices[i]}`
}
prompt += '\n\nChoose One:\n\nOr provide an open ended answer:'
super(xmargin, prompt, hook)
this.choices = choices
this.choiceButtons = []
}

mount(){
for(let i=0; i<this.choices.length; i++) {
this.choiceButtons[i] = createButton(`${i+1}`)
this.choiceButtons[i].mouseClicked(() => this.handleChoice(i))
}

super.mount()
}

unmount(){
this.choiceButtons.map( b => b.remove());
super.unmount()
}

draw(offset){
let v = super.draw(offset)

if (this.is_completed){
offset += 40
}

if(this.onScreen){
let xDelta = 40
for(let i=0; i<this.choiceButtons.length; i++) {
this.choiceButtons[i].position(xDelta*(i+1)+this.xmargin+90, v+offset-170)
}
return v
}else{
return v
}
}

handleChoice(i){
if (!this.is_completed){
this.user_string = `The student chose option ${i+1}: "${this.choices[i]}"`;
this.is_completed = true
this.submit.remove()
this.rectHeight = this.calculateRectHeight()
this.hook(this.user_string)
}
}
}
Loading

0 comments on commit 48db52c

Please sign in to comment.