File size: 8,223 Bytes
bb84260 c2eb605 bb84260 c2eb605 bb84260 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
import json
import os
import pathlib
from typing import Dict, List, Tuple
import weaviate
from langchain import OpenAI, PromptTemplate
from langchain.chains import LLMChain
from langchain.chains.base import Chain
from langchain.chains.combine_documents.base import BaseCombineDocumentsChain
from langchain.chains.conversation.memory import ConversationBufferMemory
from langchain.chains.question_answering import load_qa_chain #BaseCombineDocumentsChain
from langchain.embeddings import OpenAIEmbeddings
from langchain.prompts import FewShotPromptTemplate, PromptTemplate
from langchain.prompts.example_selector import \
SemanticSimilarityExampleSelector
from langchain.vectorstores import FAISS, Weaviate
from pydantic import BaseModel
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import FAISS, Weaviate
os.environ["WEAVIATE_URL"] = "https://tro.weaviate.network/"
os.environ["OPENAI_API_KEY"] = "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"
KEY ="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"
class CustomChain(Chain, BaseModel):
vstore: Weaviate
chain: BaseCombineDocumentsChain
key_word_extractor: Chain
@property
def input_keys(self) -> List[str]:
return ["game_description"]
@property
def output_keys(self) -> List[str]:
return ["game_environment"]
def _call(self, inputs: Dict[str, str]) -> Dict[str, str]:
game_description = inputs["game_description"]
chat_history_str = _get_chat_history(inputs["chat_history"])
if chat_history_str: # Takes in user input
print('running key_word_extractor')
new_game_description= self.key_word_extractor.run(
game_description=game_description, chat_history=chat_history_str
)
print('new_game_description',new_game_description)
else:
new_game_description = game_description
print('_new_game_description', new_game_description) # sendig objects , not showing up on screen ?
docs = self.vstore.similarity_search(new_game_description, k=4)
new_inputs = inputs.copy()
new_inputs["game_description"] = new_game_description
new_inputs["chat_history"] = chat_history_str
game_environment, _ = self.chain.combine_docs(docs, **new_inputs) # StuffDocumentsChain
print('combined', game_environment) # doc combo of game descripton and chat history,
return {"game_environment": game_environment}
# 1. Given the chat history and new user input,
# Generate game environment, objects, npcs, enemies, and quest narrative.
def get_new_chain1(vectorstore) -> Chain:
# Calls Vector DB
WEAVIATE_URL = os.environ["WEAVIATE_URL"]
client = weaviate.Client(
url=WEAVIATE_URL,
additional_headers={"X-OpenAI-Api-Key": os.environ["OPENAI_API_KEY"]},
)
_eg_template = """## AI:
Chat History:
{chat_history}
Follow Up Input: {game_description}
standalone detail: {game_description} {game_environment}"""
_eg_prompt = PromptTemplate(
template=_eg_template,
input_variables=["chat_history","game_description", "game_environment"], # question aka game detail ################ showing up in Terminal? ##############
)
# _prefix = """Given the following conversation and a follow up game detail, summarize the follow up game detail
#in a way that is coherent with the conversation.\
# You should assume that the detail is related to Game Design. Never change the game Title unless the human asks you to."""
_prefix = """ If the input and the follow up input are closely related, and are both related to the game suggested by
the previous conversation and if you are completely confident if it the same game from the original converation, then proceed. Otherwise, clarify the game title and proceed.
To proceed, retrieve the game Title and share again in quotes to the human, and summarize the follow up input in a way that is coherent with the conversation.
If the input detail is related to Game Design, proceed, otherwise clarify.
"""
_suffix = """## AI:
Chat History:
{chat_history}
Follow Up Input: {game_description}
standalone detail:"""
eg_store = Weaviate(
client,
"Rephrase",
"content",
attributes=["game_description", "game_environment", "chat_history"],
)
example_selector = SemanticSimilarityExampleSelector(vectorstore=eg_store, k=4) # looks for similar examples in vector db
prompt = FewShotPromptTemplate(
prefix=_prefix, # prompt
suffix=_suffix,
example_selector=example_selector,
example_prompt=_eg_prompt,
input_variables=["game_description", "chat_history"],
)
llm = OpenAI(temperature=0.7, model_name="text-davinci-003", max_tokens=1000)
key_word_extractor = LLMChain(llm=llm, prompt=prompt) # this could be game word extractor
# Gives an example and relevant documents # from Vector DB ##################################################### showing up in UI ##############
EXAMPLE_PROMPT = PromptTemplate(
template=">AI:\nContent:\n---------\n{page_content}\n----------\n", # not working right now ?
input_variables=["page_content"],
)
template = """
You are an AI assistant for generating a single game, the central narrative and its game quests inside the same game,
conversing in a succinct, coherent and interactive manner. Assume the entire conversation is about a single game only.
You are given the game description. You are also given the chat history, which is a conversation between a human and
another AI assistant about the same game. Do not answer any questions from the other AI assistant.
If you don't know the answer, just say "I'm not sure, how this is related?" and ask the human to clarify.
If asked about a quest, assume it is within the same game,
and provide a quest motivation, participants, rewards, character dialogue relevant to the game.
From the input, introduce a short back story of the game's plot points or character motivations and character dialogue.
Plot points may include an inciting incidient, a rising action composed of a series of conflicts, complications, dilemmas, obstacles.
From the input, generate game objects (collectibles, NPCs, enemies) related to the plot points, limit to 1-2 objects.
Ask a short question to clarify details if you are unsure but you are an expert so offer a suggestion and only ask once.
If the human asks for or adds game objects, provide only 1 detail such as physical description and possible player interactions with the object.
If the human asks for or adds an enemy, describe its behaviors and personality, as related to the game plot points, limit to a few words.
If the human asks for or adds a collectible, describe its physical appearance and possible player interactions with the object.
If the human asks for or adds a noun or NPC, describe its behaviors and personality, as related to the game plot points, limit to a few words.
If the huamn asks for character dialogue, provide a short dialogue snippet, with 1-2 sentences, as related to the game plot points.
Limit your reponses to 3-6 sentences.
Game Description: {game_description}
{context}
Answer in Markdown:"""
PROMPT = PromptTemplate(template=template, input_variables=["game_description", "context"])
doc_chain = load_qa_chain(
OpenAI(temperature=0.7, model_name="text-davinci-003", max_tokens=1000),
chain_type="stuff", # all related data is stuffed into prompt as context
prompt=PROMPT,
document_prompt=EXAMPLE_PROMPT,
)
return CustomChain(
chain=doc_chain, vstore=vectorstore, key_word_extractor=key_word_extractor
)
# doc + input -> game environment
def _get_chat_history(chat_history: List[Tuple[str, str]]):
buffer = ""
for human_s, ai_s in chat_history:
human = f"Human: " + human_s
ai = f"Assistant: " + ai_s
buffer += "\n" + "\n".join([human, ai])
return buffer
|