|
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 |
|
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: |
|
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) |
|
|
|
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) |
|
print('combined', game_environment) |
|
|
|
return {"game_environment": game_environment} |
|
|
|
|
|
|
|
|
|
|
|
def get_new_chain1(vectorstore) -> Chain: |
|
|
|
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"], |
|
) |
|
|
|
|
|
|
|
|
|
_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) |
|
prompt = FewShotPromptTemplate( |
|
prefix=_prefix, |
|
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) |
|
|
|
|
|
EXAMPLE_PROMPT = PromptTemplate( |
|
template=">AI:\nContent:\n---------\n{page_content}\n----------\n", |
|
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", |
|
prompt=PROMPT, |
|
document_prompt=EXAMPLE_PROMPT, |
|
) |
|
return CustomChain( |
|
chain=doc_chain, vstore=vectorstore, key_word_extractor=key_word_extractor |
|
) |
|
|
|
|
|
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 |
|
|