from langchain.docstore.document import Document from langchain.vectorstores import FAISS from langchain.embeddings.openai import OpenAIEmbeddings from langchain.memory.simple import SimpleMemory from langchain.chains import ConversationChain, LLMChain, SequentialChain from langchain.memory import ConversationBufferMemory from langchain.prompts import ChatPromptTemplate, PromptTemplate from langchain.document_loaders import UnstructuredFileLoader from langchain.chat_models import ChatOpenAI from langchain.llms import OpenAI from langchain.memory import ConversationSummaryMemory from langchain.callbacks import PromptLayerCallbackHandler from langchain.prompts.chat import ( ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate, ) from langchain.schema import AIMessage, HumanMessage, SystemMessage from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler from langchain.callbacks.base import BaseCallbackHandler import gradio as gr from threading import Thread from queue import Queue, Empty from threading import Thread from collections.abc import Generator from langchain.llms import OpenAI from langchain.callbacks.base import BaseCallbackHandler import itertools import time import os import getpass import json import sys from typing import Any, Dict, List, Union import promptlayer import openai import gradio as gr from pydantic import BaseModel, Field, validator from langchain.callbacks import PromptLayerCallbackHandler from langchain.prompts.chat import ( ChatPromptTemplate, SystemMessagePromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate, ) from langchain.memory import ConversationSummaryMemory #API Keys promptlayer.api_key = os.environ["PROMPTLAYER"] openai.api_key = os.environ["OPENAI_API_KEY"] import gradio as gr """# Config the app""" TITLE = "UBD Coach" DESC=""" Using the Understanding By Design (UBD) framework? (/◕ヮ◕)/ \n I can help. Let me be your thinking partner and assistant. \n What subject are you interested in building for? """ APP = """ # UBD Coach Roleplay as an expert in the Understanding by Design curriculum coach. Help the teacher build out their UBD curriculum step by step. Be encouraging. Help the teacher build confidence in the design process. Below is the structure of the design process ( delineated by the triple plus): +++ Stage 1: Identify Desired Results The first stage in the design process calls for clarity about the learning priorities – both long-term outcomes as well as short-term goals. We review established content standards and related outcomes (e.g., 21st-century skills) to consider the big ideas we want students to come to understand and the long-term transfer goals that those ideas enable. We frame companion essential questions around the targeted understandings and transfer goals. Finally, we identify more specific knowledge and skill objectives. The following planning questions guide the work of Stage 1: What do we want students to be able to do with their learning in the long run? What should students come to understand for them to transfer their learning? What essential questions will students explore? What knowledge and skills will students need to acquire? Stage 2: Determine Acceptable Evidence In Stage 2 of backward design, we are encouraged to “think like assessors” before jumping to planning lessons and learning activities (in Stage 3). In other words, we need to think about the assessment that will show the extent to which our students have attained the various learning outcomes outlined in Stage 1. It is one thing to say that students should understand X and be able to do Y; it is another to ask: What evidence will show that they understand X and can effectively apply Y? We have found that considering the needed assessment evidence helps focus and sharpen the teaching-learning plan in Stage 3. The following planning questions guide the work of Stage 2: What evidence will show that learners have achieved the learning goals targeted in Stage 1? How will learners demonstrate their understanding and ability to transfer their learning? How will we assess the specific knowledge and skill proficiency? In UbD, evidence of understanding and transfer is obtained through performance tasks that ask students to explain what they understand and to apply (i.e., transfer) their learning to new situations. We recommend that the performance assessments be set in a meaningful and authentic context whenever possible. Supplementary assessments, such as a test on facts or a skills check, provide additional evidence of students’ knowledge acquisition and skill proficiency. Stage 3: Plan Learning Experiences and Instruction In the third stage of backward design, we plan for our teaching and the associated learning experiences that students will need to reach and demonstrate attainment of goals. With clearly identified learning results (Stage 1) and appropriate assessment evidence in mind (Stage 2), we now plan the most appropriate instructional activities for helping learners acquire targeted knowledge and skills, come to understand important ideas, and apply their learning in meaningful ways. The various types of learning goals identified in Stage 1—acquisition of knowledge and skills, understanding of big ideas, and transfer—inform the selection of instructional strategies and the roles of the teacher, including direct instructor, facilitator, and coach. In other words, our instructional practices need to be aligned to the desired results (Stage 1) and their assessments (Stage 2). The following planning questions guide planning in Stage 3: What activities, experiences, and lessons will lead to the achievement of the desired results and success at the assessments? How will the learning plan help students acquire, make meaning, and transfer? How will the unit be sequenced and differentiated to optimize achievement for all learners? How will we check for understanding along the way? +++ Goal [ Stage_1 Stage_2 Stage_3 ] Input [ input = {input} ] History [ history = {history} ] Understanding_By_Design_Coach [ State [ Goals ] Constraints [ Emulate the speaking style of the world's best curriculum coaches. Keep the responses short and focused and on task towards the goal. Be encouraging. Close with a question that helps the teacher complete the current step. ] /help - provide a summary of the design process /explain - Explain the goals of the ubd process ] very_brief_state_summary() respond(input, history) """ """# Agent Engine""" # Defined a QueueCallback, which takes as a Queue object during initialization. Each new token is pushed to the queue. class QueueCallback(BaseCallbackHandler): """Callback handler for streaming LLM responses to a queue.""" def __init__(self, q): self.q = q def on_llm_new_token(self, token: str, **kwargs: Any) -> None: self.q.put(token) def on_llm_end(self, *args, **kwargs: Any) -> None: return self.q.empty() class DDSAgent: def __init__(self, name, prompt_template='', model_name='gpt-4', verbose=False, temp=0.2): self.verbose = verbose self.llm = ChatOpenAI( model_name="gpt-4", temperature=temp ) #The zero shot prompt provided at creation self.prompt_template = prompt_template #The LLM used for conversation summarization self.summary_llm = ChatOpenAI( model_name=model_name, max_tokens=25, callbacks=[PromptLayerCallbackHandler(pl_tags=["sudo_lang"])], streaming=False, ) #Reviews convesation history and summarizes it to keep the token count down. self.memory = ConversationSummaryMemory(llm=self.summary_llm, max_token_limit=200, memory_key="memory", input_key="input") def chain(self, prompt: PromptTemplate, llm: ChatOpenAI) -> LLMChain: return LLMChain( llm=llm, prompt=prompt, verbose=self.verbose, memory=self.memory ) def stream(self, input) -> Generator: # Create a Queue q = Queue() job_done = object() llm = ChatOpenAI( model_name='gpt-4', callbacks=[QueueCallback(q), PromptLayerCallbackHandler(pl_tags=["sudo_lang"])], streaming=True, ) prompt = PromptTemplate( input_variables=['input','history'], template=self.prompt_template # partial_variables={"format_instructions": self.parser.get_format_instructions()} ) # Create a funciton to call - this will run in a thread def task(): resp = self.chain(prompt,llm).run( {'input':input, 'history':self.memory}) q.put(job_done) # Create a thread and start the function t = Thread(target=task) t.start() content = "" # Get each new token from the queue and yield for our generator while True: try: next_token = q.get(True, timeout=1) if next_token is job_done: break content += next_token yield next_token, content except Empty: continue agent = DDSAgent('agent', prompt_template=APP) def ask_agent(input, history): for next_token, content in agent.stream(input): yield(content) """# Run Gradio App Locally""" gr.ChatInterface(ask_agent, title=TITLE, description=DESC, theme="monochrome", retry_btn=None, undo_btn=None, clear_btn=None ).queue().launch(debug=True)