adding uv and fixing dependencies for hf spaces
Browse files- .gitignore +5 -2
- .python-version +1 -0
- Data/Ekalia/Ekalia.png +0 -3
- Data/Rules/D&D Livro do jogador.pdf +0 -3
- Data/Rules/Guia do Mestre D&D 5E.pdf +0 -3
- README.md +1 -1
- legacy/src/brain.py +0 -230
- legacy/src/db.py +0 -41
- legacy/src/ears/__pycache__/whisper.cpython-312.pyc +0 -0
- legacy/src/ears/whisper.py +0 -5
- legacy/src/front_meta.py +0 -129
- legacy/src/gen/__init__.py +0 -0
- legacy/src/gen/__pycache__/npc_gen.cpython-312.pyc +0 -0
- legacy/src/gen/npc_gen.py +0 -101
- legacy/src/gen/side_quest_gen.py +0 -0
- legacy/src/main.py +0 -134
- legacy/src/pdf_reader/pdf_agent.py +0 -92
- legacy/src/session_resume.py +0 -75
- legacy/src/testes.ipynb +0 -405
- legacy/src/utils/__init__.py +0 -0
- legacy/src/utils/__pycache__/__init__.cpython-312.pyc +0 -0
- legacy/src/utils/__pycache__/get_data.cpython-312.pyc +0 -0
- legacy/src/utils/api_key.py +0 -4
- legacy/src/utils/get_data.py +0 -30
- main.py +6 -0
- pyproject.toml +22 -0
- requirements.txt +0 -1
- src/llm/__pycache__/client.cpython-312.pyc +0 -0
- uv.lock +0 -0
.gitignore
CHANGED
|
@@ -1,6 +1,9 @@
|
|
| 1 |
.venv/
|
| 2 |
.vscode/
|
| 3 |
-
|
| 4 |
/models
|
| 5 |
.env
|
| 6 |
-
/Data/Audios
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
.venv/
|
| 2 |
.vscode/
|
| 3 |
+
__pycache__/
|
| 4 |
/models
|
| 5 |
.env
|
| 6 |
+
/Data/Audios
|
| 7 |
+
*.png
|
| 8 |
+
/Data/Rules
|
| 9 |
+
/legacy
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.12
|
Data/Ekalia/Ekalia.png
DELETED
Git LFS Details
|
Data/Rules/D&D Livro do jogador.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:2f1bd4f41113f5a13f811ea701d64bd5ed5b02cfadd05c43dbbc9665ec43d7d8
|
| 3 |
-
size 23685308
|
|
|
|
|
|
|
|
|
|
|
|
Data/Rules/Guia do Mestre D&D 5E.pdf
DELETED
|
@@ -1,3 +0,0 @@
|
|
| 1 |
-
version https://git-lfs.github.com/spec/v1
|
| 2 |
-
oid sha256:280fd8568d793ae8e6dc6de69c17cc8e30963eb3c5e745e3b414c2a249ff85a6
|
| 3 |
-
size 21246717
|
|
|
|
|
|
|
|
|
|
|
|
README.md
CHANGED
|
@@ -4,7 +4,7 @@ emoji: 🎲
|
|
| 4 |
colorFrom: purple
|
| 5 |
colorTo: blue
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version: "
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
|
|
|
| 4 |
colorFrom: purple
|
| 5 |
colorTo: blue
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: "5.0.0"
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
---
|
legacy/src/brain.py
DELETED
|
@@ -1,230 +0,0 @@
|
|
| 1 |
-
"""
|
| 2 |
-
WorkFlow:
|
| 3 |
-
|
| 4 |
-
Pre. O usuário insere a campanha ativa,
|
| 5 |
-
(a campanha tem todos os jogadores, posição final deles e oque aconteceu)
|
| 6 |
-
|
| 7 |
-
1. O usuario insere um input para o Cerebro
|
| 8 |
-
2. O input é enviado para o Cerebro (Ollama)
|
| 9 |
-
3. O Cerebro entende o input
|
| 10 |
-
|
| 11 |
-
4. Pega os dados em embedding
|
| 12 |
-
4.1 Do mundo (Ekalia)
|
| 13 |
-
4.2 Pega os dados da campanha ativa atual
|
| 14 |
-
4.3 Pega os dados das regras
|
| 15 |
-
|
| 16 |
-
5. O Cerebro cria um output com base no input e nos dados em embedding
|
| 17 |
-
6. O output é enviado para o usuário
|
| 18 |
-
|
| 19 |
-
-Ideias:
|
| 20 |
-
Gerador de NPCs
|
| 21 |
-
Gerador de missões
|
| 22 |
-
Salvar progresso da campanha, junto de logs do jogo, completando com um resumo do que aconteceu
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
"""
|
| 26 |
-
|
| 27 |
-
from utils.api_key import API_KEY
|
| 28 |
-
|
| 29 |
-
from langchain_openai import ChatOpenAI
|
| 30 |
-
from langchain_openai import OpenAIEmbeddings
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
class RAG():
|
| 35 |
-
def __init__(self):
|
| 36 |
-
pass
|
| 37 |
-
|
| 38 |
-
def transcribe_audio_to_text(audio_path: str) -> str:
|
| 39 |
-
"""
|
| 40 |
-
Transcreve um arquivo de áudio para texto usando Whisper.
|
| 41 |
-
|
| 42 |
-
Args:
|
| 43 |
-
audio_path: O caminho para o arquivo de áudio.
|
| 44 |
-
|
| 45 |
-
Returns:
|
| 46 |
-
A transcrição do áudio como uma string.
|
| 47 |
-
"""
|
| 48 |
-
import whisper
|
| 49 |
-
|
| 50 |
-
model = whisper.load_model("large")
|
| 51 |
-
result = model.transcribe(audio_path)
|
| 52 |
-
return result["text"]
|
| 53 |
-
|
| 54 |
-
def summarize_session_text(session_text: str) -> str:
|
| 55 |
-
"""
|
| 56 |
-
Resume o texto da sessão usando um modelo LLM.
|
| 57 |
-
|
| 58 |
-
Args:
|
| 59 |
-
session_text: O texto completo da sessão.
|
| 60 |
-
|
| 61 |
-
Returns:
|
| 62 |
-
Um resumo do texto da sessão.
|
| 63 |
-
"""
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
from openai import OpenAI
|
| 67 |
-
client = OpenAI(api_key = )
|
| 68 |
-
|
| 69 |
-
response = client.responses.create(
|
| 70 |
-
model="gpt-5.2",
|
| 71 |
-
input="Write a one-sentence bedtime story about a unicorn."
|
| 72 |
-
)
|
| 73 |
-
|
| 74 |
-
print(response.output_text)
|
| 75 |
-
return response.output_text
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
def run_openai():
|
| 80 |
-
|
| 81 |
-
# Model
|
| 82 |
-
llm = ChatOpenAI(
|
| 83 |
-
model="gpt-3.5-turbo",
|
| 84 |
-
temperature=1.0, # Aumenta a criatividade e reduz filtros
|
| 85 |
-
top_p=0.95, # Aumenta a diversidade de respostas
|
| 86 |
-
max_tokens=2048,
|
| 87 |
-
api_key=API_KEY,
|
| 88 |
-
)
|
| 89 |
-
|
| 90 |
-
return llm
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
def run_local():
|
| 95 |
-
# WIP: VLLM Local
|
| 96 |
-
###############################################
|
| 97 |
-
|
| 98 |
-
from langchain_openai import ChatOpenAI
|
| 99 |
-
from langchain_openai import OpenAIEmbeddings
|
| 100 |
-
|
| 101 |
-
llm = ChatOpenAI(
|
| 102 |
-
model="model/qwen25-7b-awq",
|
| 103 |
-
base_url="http://localhost:8000/v1", #Aqui usa VLLM local
|
| 104 |
-
api_key="none"
|
| 105 |
-
)
|
| 106 |
-
|
| 107 |
-
#################################################
|
| 108 |
-
|
| 109 |
-
return llm
|
| 110 |
-
|
| 111 |
-
def choose_method(method):
|
| 112 |
-
if method == 1:
|
| 113 |
-
run_openai()
|
| 114 |
-
elif method == 2:
|
| 115 |
-
run_local()
|
| 116 |
-
|
| 117 |
-
return None
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
def load_db():
|
| 125 |
-
# Vector Store Load
|
| 126 |
-
embeddings = OpenAIEmbeddings(
|
| 127 |
-
model="text-embedding-3-large",
|
| 128 |
-
api_key=API_KEY
|
| 129 |
-
)
|
| 130 |
-
from langchain_community.vectorstores import FAISS
|
| 131 |
-
vectorstore = FAISS.load_local(
|
| 132 |
-
"Data/db/ekalia_vector_db",
|
| 133 |
-
embeddings,
|
| 134 |
-
allow_dangerous_deserialization=True
|
| 135 |
-
)
|
| 136 |
-
|
| 137 |
-
retriever = vectorstore.as_retriever(
|
| 138 |
-
search_kwargs={"k": 5}
|
| 139 |
-
)
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
from langchain.agents import create_tool_calling_agent, AgentExecutor
|
| 147 |
-
from langchain.agents import create_agent
|
| 148 |
-
from langchain_core.prompts import ChatPromptTemplate
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
prompt = ChatPromptTemplate.from_messages([
|
| 152 |
-
(
|
| 153 |
-
"system",
|
| 154 |
-
"""
|
| 155 |
-
Você é o Cronista Oficial do mundo de Ekalia.
|
| 156 |
-
Use APENAS informações retornadas pelas ferramentas.
|
| 157 |
-
Se algo não existir no lore, diga que não está registrado.
|
| 158 |
-
"""
|
| 159 |
-
),
|
| 160 |
-
("human", "{input}"),
|
| 161 |
-
("placeholder", "{agent_scratchpad}")
|
| 162 |
-
])
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
from langchain_core.messages import SystemMessage
|
| 168 |
-
from langchain_core.messages import (
|
| 169 |
-
SystemMessage,
|
| 170 |
-
HumanMessage,
|
| 171 |
-
AIMessage
|
| 172 |
-
)
|
| 173 |
-
|
| 174 |
-
chat_history = [
|
| 175 |
-
SystemMessage(
|
| 176 |
-
content="Você é um assistente para jogos de RPG de mesa, expert em Dungeons and Dragons 5ª Edição. "
|
| 177 |
-
)
|
| 178 |
-
]
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
###############
|
| 183 |
-
|
| 184 |
-
def main():
|
| 185 |
-
method = int(input("Escolha o método de execução (1 para OpenAI, 2 para Local): "))
|
| 186 |
-
llm = choose_method(method)
|
| 187 |
-
load_db()
|
| 188 |
-
|
| 189 |
-
chat_history = []
|
| 190 |
-
|
| 191 |
-
agent = create_tool_calling_agent(
|
| 192 |
-
llm=llm,
|
| 193 |
-
tools=[],
|
| 194 |
-
prompt=prompt
|
| 195 |
-
)
|
| 196 |
-
|
| 197 |
-
agent_executor = AgentExecutor(
|
| 198 |
-
agent=agent,
|
| 199 |
-
tools=[],
|
| 200 |
-
verbose=True
|
| 201 |
-
)
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
while True:
|
| 205 |
-
message = input("\nDigite uma mensagem:\n")
|
| 206 |
-
|
| 207 |
-
if message.lower() in ["sair", "exit", "quit"]:
|
| 208 |
-
break
|
| 209 |
-
|
| 210 |
-
message = [*chat_history, HumanMessage(content=message)]
|
| 211 |
-
|
| 212 |
-
result = agent_executor.invoke({"messages": message})
|
| 213 |
-
print(result)
|
| 214 |
-
|
| 215 |
-
|
| 216 |
-
"""start_time = time.time()
|
| 217 |
-
word = ""
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
while word != "quit":
|
| 222 |
-
word = input("Digite uma palavra (ou 'quit' para sair): ")
|
| 223 |
-
if word != "quit":
|
| 224 |
-
resp = llm.invoke(word)
|
| 225 |
-
end_time = time.time()
|
| 226 |
-
elapsed = end_time - start_time
|
| 227 |
-
print(resp)
|
| 228 |
-
print(f"Tempo de resposta: {elapsed:.2f} segundos")
|
| 229 |
-
else:
|
| 230 |
-
print("Quitting")"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/db.py
DELETED
|
@@ -1,41 +0,0 @@
|
|
| 1 |
-
from utils.get_data import get_data
|
| 2 |
-
from utils.api_key import API_KEY
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
from langchain_openai import OpenAIEmbeddings
|
| 6 |
-
from langchain_text_splitters import RecursiveCharacterTextSplitter
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
from langchain_community.docstore.in_memory import InMemoryDocstore
|
| 10 |
-
from langchain_community.vectorstores import FAISS
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
import faiss
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
data = get_data(verbose=False)
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
text_splitter = RecursiveCharacterTextSplitter(
|
| 20 |
-
chunk_size=800,
|
| 21 |
-
chunk_overlap=120,
|
| 22 |
-
separators=["\n\n", "\n", ".", " "]
|
| 23 |
-
)
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
docs_split = text_splitter.split_documents(data)
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
embeddings = OpenAIEmbeddings(
|
| 30 |
-
model="text-embedding-3-large",
|
| 31 |
-
api_key=API_KEY
|
| 32 |
-
)
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
vectorstore = FAISS.from_documents(
|
| 36 |
-
documents=docs_split,
|
| 37 |
-
embedding=embeddings
|
| 38 |
-
)
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
vectorstore.save_local("Data/db/ekalia_vector_db")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/ears/__pycache__/whisper.cpython-312.pyc
DELETED
|
Binary file (1.36 kB)
|
|
|
legacy/src/ears/whisper.py
DELETED
|
@@ -1,5 +0,0 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
LLM_MODEL = "deepseek-r1:latest" # ou "llama3"
|
| 4 |
-
# da pra trocar pelo modelo local usando vllm
|
| 5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/front_meta.py
DELETED
|
@@ -1,129 +0,0 @@
|
|
| 1 |
-
import sys
|
| 2 |
-
|
| 3 |
-
from PyQt6.QtCore import QSize, Qt
|
| 4 |
-
from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QLineEdit, QGridLayout, QWidget, QPushButton
|
| 5 |
-
|
| 6 |
-
"""
|
| 7 |
-
|
| 8 |
-
Menus - Inicial botoes para -> Durante a sessão,
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
"""
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
WINDOW_TITLES = [
|
| 18 |
-
"My App",
|
| 19 |
-
"Generative AI Assistant",
|
| 20 |
-
"Post Session Helper",
|
| 21 |
-
]
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
# Subclass QMainWindow to customize your application's main window
|
| 26 |
-
class MainWindow(QMainWindow):
|
| 27 |
-
def __init__(self):
|
| 28 |
-
super().__init__()
|
| 29 |
-
self.setMinimumSize(QSize(800, 600))
|
| 30 |
-
self.STATES = ["main_menu", "generate", "session_helper"]
|
| 31 |
-
self.cur_state = "main_menu"
|
| 32 |
-
self.MENU_STATE(self.cur_state)
|
| 33 |
-
|
| 34 |
-
def MENU_STATE(self, state):
|
| 35 |
-
self.setWindowTitle(WINDOW_TITLES[self.STATES.index(state)])
|
| 36 |
-
if state == self.STATES[0]:
|
| 37 |
-
self.MAIN_MENU()
|
| 38 |
-
elif state == self.STATES[1]:
|
| 39 |
-
self.GEN_MENU()
|
| 40 |
-
elif state == self.STATES[2]:
|
| 41 |
-
self.SESSION_HELPER_MENU()
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
def MAIN_MENU(self):
|
| 46 |
-
# Clear the screen if needed
|
| 47 |
-
if self.centralWidget():
|
| 48 |
-
for widget in self.centralWidget().children():
|
| 49 |
-
widget.deleteLater()
|
| 50 |
-
|
| 51 |
-
self.GenButton = QPushButton("Generate")
|
| 52 |
-
self.SHButton = QPushButton("Session Helper")
|
| 53 |
-
|
| 54 |
-
self.GenButton.clicked.connect(lambda: self.MENU_STATE("generate"))
|
| 55 |
-
self.SHButton.clicked.connect(lambda: self.MENU_STATE("session_helper"))
|
| 56 |
-
|
| 57 |
-
layout = QGridLayout()
|
| 58 |
-
layout.addWidget(self.GenButton, 0, 0, Qt.AlignmentFlag.AlignCenter)
|
| 59 |
-
layout.addWidget(self.SHButton, 0, 1, Qt.AlignmentFlag.AlignCenter)
|
| 60 |
-
|
| 61 |
-
container = QWidget()
|
| 62 |
-
container.setLayout(layout)
|
| 63 |
-
self.setCentralWidget(container)
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
def GEN_MENU(self):
|
| 69 |
-
# Clear the screen
|
| 70 |
-
if self.centralWidget():
|
| 71 |
-
for widget in self.centralWidget().children():
|
| 72 |
-
widget.deleteLater()
|
| 73 |
-
|
| 74 |
-
layout = QGridLayout()
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
label = QLabel("Generate Menu")
|
| 78 |
-
layout.addWidget(label, 0, 0, Qt.AlignmentFlag.AlignCenter)
|
| 79 |
-
###########################################################
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
############################################################
|
| 85 |
-
|
| 86 |
-
backButton = QPushButton("Back to Main Menu")
|
| 87 |
-
backButton.clicked.connect(lambda: self.MENU_STATE("main_menu"))
|
| 88 |
-
layout.addWidget(backButton, 3, 0, Qt.AlignmentFlag.AlignCenter)
|
| 89 |
-
|
| 90 |
-
container = QWidget()
|
| 91 |
-
container.setLayout(layout)
|
| 92 |
-
self.setCentralWidget(container)
|
| 93 |
-
|
| 94 |
-
def SESSION_HELPER_MENU(self):
|
| 95 |
-
# Clear the screen
|
| 96 |
-
if self.centralWidget():
|
| 97 |
-
for widget in self.centralWidget().children():
|
| 98 |
-
widget.deleteLater()
|
| 99 |
-
|
| 100 |
-
layout = QGridLayout()
|
| 101 |
-
|
| 102 |
-
label = QLabel("Session Helper Menu")
|
| 103 |
-
layout.addWidget(label, 0, 0, Qt.AlignmentFlag.AlignCenter)
|
| 104 |
-
###########################################################
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
###########################################################
|
| 109 |
-
|
| 110 |
-
backButton = QPushButton("Back to Main Menu")
|
| 111 |
-
backButton.clicked.connect(lambda: self.MENU_STATE("main_menu"))
|
| 112 |
-
layout.addWidget(backButton, 3, 0, Qt.AlignmentFlag.AlignCenter)
|
| 113 |
-
|
| 114 |
-
container = QWidget()
|
| 115 |
-
container.setLayout(layout)
|
| 116 |
-
self.setCentralWidget(container)
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
container = QWidget()
|
| 120 |
-
container.setLayout(layout)
|
| 121 |
-
self.setCentralWidget(container)
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
app = QApplication(sys.argv)
|
| 125 |
-
|
| 126 |
-
window = MainWindow()
|
| 127 |
-
window.show()
|
| 128 |
-
|
| 129 |
-
app.exec()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/gen/__init__.py
DELETED
|
File without changes
|
legacy/src/gen/__pycache__/npc_gen.cpython-312.pyc
DELETED
|
Binary file (446 Bytes)
|
|
|
legacy/src/gen/npc_gen.py
DELETED
|
@@ -1,101 +0,0 @@
|
|
| 1 |
-
# Aqui pegaremos o contexto da campanha e local do NPC
|
| 2 |
-
import random
|
| 3 |
-
|
| 4 |
-
races = {
|
| 5 |
-
"human": {"str": 1, "dex": 1, "con": 1, "int": 1, "wis": 1, "cha": 1},
|
| 6 |
-
|
| 7 |
-
"elf": {"str": 0, "dex": 2, "con": 0, "int": 0, "wis": 0, "cha": 0},
|
| 8 |
-
"high_elf": {"str": 0, "dex": 2, "con": 0, "int": 1, "wis": 0, "cha": 0},
|
| 9 |
-
"wood_elf": {"str": 0, "dex": 2, "con": 0, "int": 0, "wis": 1, "cha": 0},
|
| 10 |
-
"dark_elf": {"str": 0, "dex": 2, "con": 0, "int": 0, "wis": 0, "cha": 1},
|
| 11 |
-
|
| 12 |
-
"dwarf": {"str": 0, "dex": 0, "con": 2, "int": 0, "wis": 0, "cha": 0},
|
| 13 |
-
"hill_dwarf": {"str": 0, "dex": 0, "con": 2, "int": 0, "wis": 1, "cha": 0},
|
| 14 |
-
"mountain_dwarf": {"str": 2, "dex": 0, "con": 2, "int": 0, "wis": 0, "cha": 0},
|
| 15 |
-
|
| 16 |
-
"halfling": {"str": 0, "dex": 2, "con": 0, "int": 0, "wis": 0, "cha": 0},
|
| 17 |
-
"lightfoot_halfling": {"str": 0, "dex": 2, "con": 0, "int": 0, "wis": 0, "cha": 1},
|
| 18 |
-
"stout_halfling": {"str": 0, "dex": 2, "con": 1, "int": 0, "wis": 0, "cha": 0},
|
| 19 |
-
|
| 20 |
-
"dragonborn": {"str": 2, "dex": 0, "con": 0, "int": 0, "wis": 0, "cha": 1},
|
| 21 |
-
"gnome": {"str": 0, "dex": 0, "con": 0, "int": 2, "wis": 0, "cha": 0},
|
| 22 |
-
"forest_gnome": {"str": 0, "dex": 1, "con": 0, "int": 2, "wis": 0, "cha": 0},
|
| 23 |
-
"rock_gnome": {"str": 0, "dex": 0, "con": 1, "int": 2, "wis": 0, "cha": 0},
|
| 24 |
-
|
| 25 |
-
"half_elf": {"str": 0, "dex": 0, "con": 0, "int": 0, "wis": 0, "cha": 2},
|
| 26 |
-
"half_orc": {"str": 2, "dex": 0, "con": 1, "int": 0, "wis": 0, "cha": 0},
|
| 27 |
-
|
| 28 |
-
"tiefling": {"str": 0, "dex": 0, "con": 0, "int": 1, "wis": 0, "cha": 2}
|
| 29 |
-
}
|
| 30 |
-
|
| 31 |
-
class Race:
|
| 32 |
-
def __init__(self, name, base_bonus, subraces=None):
|
| 33 |
-
self.name = name
|
| 34 |
-
self.base_bonus = base_bonus
|
| 35 |
-
self.subraces = subraces or {}
|
| 36 |
-
|
| 37 |
-
def get_bonus(self, subrace=None):
|
| 38 |
-
bonus = self.base_bonus.copy()
|
| 39 |
-
if subrace and subrace in self.subraces:
|
| 40 |
-
for stat, value in self.subraces[subrace].items():
|
| 41 |
-
bonus[stat] = bonus.get(stat, 0) + value
|
| 42 |
-
return bonus
|
| 43 |
-
|
| 44 |
-
class NPC():
|
| 45 |
-
def __init__(self):
|
| 46 |
-
self.str
|
| 47 |
-
self.dex
|
| 48 |
-
self.con
|
| 49 |
-
self.int
|
| 50 |
-
self.wis
|
| 51 |
-
self.char
|
| 52 |
-
|
| 53 |
-
self.race
|
| 54 |
-
self.stats = self.roll_stats
|
| 55 |
-
|
| 56 |
-
def roll_stats(self):
|
| 57 |
-
stats = []
|
| 58 |
-
for _ in range(6):
|
| 59 |
-
rolls = []
|
| 60 |
-
for _ in range(4):
|
| 61 |
-
rolls.append(random.randint(1, 6))
|
| 62 |
-
stat = max(sum(rolls) - min(rolls), 8)
|
| 63 |
-
print(stat)
|
| 64 |
-
stats.append(stat)
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
stats.sort(reverse=True)
|
| 68 |
-
|
| 69 |
-
return stats
|
| 70 |
-
|
| 71 |
-
def roll_race(self, context):
|
| 72 |
-
"""
|
| 73 |
-
Ferramar
|
| 74 |
-
- Humanos
|
| 75 |
-
- Draconatos
|
| 76 |
-
- Aasimar (militares)
|
| 77 |
-
Ressamar
|
| 78 |
-
- Humanos
|
| 79 |
-
- Tritões (minorias costeiras)
|
| 80 |
-
- Tabaxi
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
"""
|
| 85 |
-
pass
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
class Combative_NPC(NPC):
|
| 89 |
-
def __init__(self):
|
| 90 |
-
|
| 91 |
-
self.classe
|
| 92 |
-
|
| 93 |
-
def roll_class(self):
|
| 94 |
-
pass
|
| 95 |
-
|
| 96 |
-
def background():
|
| 97 |
-
NotImplemented
|
| 98 |
-
|
| 99 |
-
class Non_Combative_NPC(NPC):
|
| 100 |
-
def __init__(self):
|
| 101 |
-
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/gen/side_quest_gen.py
DELETED
|
File without changes
|
legacy/src/main.py
DELETED
|
@@ -1,134 +0,0 @@
|
|
| 1 |
-
import os
|
| 2 |
-
import json
|
| 3 |
-
import ears.whisper as whisper
|
| 4 |
-
|
| 5 |
-
"""
|
| 6 |
-
# TODO:
|
| 7 |
-
1. Trocar Tkinter por pyside6
|
| 8 |
-
|
| 9 |
-
"""
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
import tkinter as tk
|
| 13 |
-
from tkinter import filedialog, messagebox
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
OUTPUT_IMAGE_DIR = "output_images"
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
class sessionHelper():
|
| 20 |
-
def __init__(self, root ):
|
| 21 |
-
|
| 22 |
-
self.root = root
|
| 23 |
-
|
| 24 |
-
self.root.geometry("600x400")
|
| 25 |
-
self.root.title("RPG Session Helper")
|
| 26 |
-
|
| 27 |
-
self.campaings = self.get_all_campaings()
|
| 28 |
-
self.main_menu()
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
# Pega os dados das campanhas: Jogadores, Numero de sessoes, Logs
|
| 32 |
-
def get_all_campaings(self):
|
| 33 |
-
# Placeholder: Retorna uma lista de campanhas
|
| 34 |
-
with open(os.path.join("Data", "Campaings", "campaings.json"), "r") as file:
|
| 35 |
-
return json.load(file)
|
| 36 |
-
return
|
| 37 |
-
|
| 38 |
-
def add_or_remove_player_to_campaing(self, campaing_id, player_data):
|
| 39 |
-
# Placeholder: Adiciona um jogador a uma campanha específica
|
| 40 |
-
return
|
| 41 |
-
|
| 42 |
-
def main_menu(self):
|
| 43 |
-
|
| 44 |
-
b1 = tk.Button(self.root, text = "Gerar Algo", command=self.GENERATE_MENU)
|
| 45 |
-
b1.pack(pady=10)
|
| 46 |
-
|
| 47 |
-
b2 = tk.Button(self.root, text="Gerenciar Campanhas", command=self.SELECT_CAMPAING_MENU)
|
| 48 |
-
b2.pack(pady=10)
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
def GENERATE_MENU(self):
|
| 54 |
-
pass
|
| 55 |
-
# Menu principal
|
| 56 |
-
def SELECT_CAMPAING_MENU(self):
|
| 57 |
-
|
| 58 |
-
# Clear the screen
|
| 59 |
-
for widget in self.root.winfo_children():
|
| 60 |
-
widget.destroy()
|
| 61 |
-
|
| 62 |
-
title = tk.Label(self.root, text="Campanhas Ativas", font=("Arial", 16, "bold"))
|
| 63 |
-
title.pack(pady=10)
|
| 64 |
-
|
| 65 |
-
# Lista de campanhas
|
| 66 |
-
self.campaign_list = tk.Listbox(self.root, height=8, width=50)
|
| 67 |
-
self.campaign_list.pack(pady=10)
|
| 68 |
-
for c in self.campaings:
|
| 69 |
-
self.campaign_list.insert(tk.END, f"{c['id']} - {c['name']}")
|
| 70 |
-
|
| 71 |
-
select_btn = tk.Button(self.root, text="Selecionar Campanha", command=self.select_campaign)
|
| 72 |
-
select_btn.pack(pady=5)
|
| 73 |
-
|
| 74 |
-
self.players_label = tk.Label(self.root, text="", font=("Arial", 12))
|
| 75 |
-
self.players_label.pack(pady=10)
|
| 76 |
-
|
| 77 |
-
self.transcribe_btn = tk.Button(self.root, text="Transcrever e Resumir Sessão", command=self.transcribe_and_summarize)
|
| 78 |
-
self.transcribe_btn.pack(pady=10)
|
| 79 |
-
self.transcribe_btn.config(state=tk.DISABLED)
|
| 80 |
-
|
| 81 |
-
def select_campaign(self):
|
| 82 |
-
selection = self.campaign_list.curselection()
|
| 83 |
-
if not selection:
|
| 84 |
-
messagebox.showwarning("Aviso", "Selecione uma campanha primeiro.")
|
| 85 |
-
return
|
| 86 |
-
|
| 87 |
-
index = selection[0]
|
| 88 |
-
self.selected_campaign = self.campaings[index]
|
| 89 |
-
players_text = "Jogadores:\n" + "\n".join(
|
| 90 |
-
[f"- {p['Nome']} ({p['Raça']} {p['Classe']})" for p in self.selected_campaign.get("players", [])]
|
| 91 |
-
)
|
| 92 |
-
self.players_label.config(text=players_text)
|
| 93 |
-
self.transcribe_btn.config(state=tk.NORMAL)
|
| 94 |
-
|
| 95 |
-
def log_session(self, campaing_id, session_number, session_data):
|
| 96 |
-
# Placeholder: Loga os dados de uma sessão para uma campanha específica
|
| 97 |
-
return
|
| 98 |
-
|
| 99 |
-
def transcribe_and_summarize(self):
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
audio_path = filedialog.askopenfilename(title="Selecione o arquivo de áudio da sessão")
|
| 103 |
-
if not audio_path:
|
| 104 |
-
return
|
| 105 |
-
|
| 106 |
-
try:
|
| 107 |
-
session_text = whisper.transcribe_audio_to_text(audio_path)
|
| 108 |
-
summary = whisper.summarize_session_text(session_text)
|
| 109 |
-
messagebox.showinfo("Resumo da Sessão", summary)
|
| 110 |
-
except Exception as e:
|
| 111 |
-
messagebox.showerror("Erro", f"Ocorreu um erro: {str(e)}")
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
if __name__ == "__main__":
|
| 116 |
-
import tkinter as tk
|
| 117 |
-
from tkinter import simpledialog
|
| 118 |
-
|
| 119 |
-
# Adicionar Menu principal interativo com TKinter
|
| 120 |
-
# - Listar campanhas
|
| 121 |
-
# - Adicionar/Remover jogadores da campanha
|
| 122 |
-
# - Selecionar campanha -> Logar sessão
|
| 123 |
-
#
|
| 124 |
-
# - Ver resumo da campanha
|
| 125 |
-
|
| 126 |
-
root = tk.Tk()
|
| 127 |
-
sh = sessionHelper(root)
|
| 128 |
-
root.mainloop()
|
| 129 |
-
# Listar campanhas disponíveis
|
| 130 |
-
for campaing in sh.campaings:
|
| 131 |
-
print(f"ID: {campaing['id']}, Nome: {campaing['name']}")
|
| 132 |
-
# Selecionar campanha
|
| 133 |
-
|
| 134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/pdf_reader/pdf_agent.py
DELETED
|
@@ -1,92 +0,0 @@
|
|
| 1 |
-
import fitz # PyMuPDF
|
| 2 |
-
import io
|
| 3 |
-
from PIL import Image
|
| 4 |
-
import os
|
| 5 |
-
|
| 6 |
-
# --- Configuração ---
|
| 7 |
-
# Crie uma pasta para salvar as imagens extraídas
|
| 8 |
-
OUTPUT_IMAGE_DIR = "extracted_images"
|
| 9 |
-
if not os.path.exists(OUTPUT_IMAGE_DIR):
|
| 10 |
-
os.makedirs(OUTPUT_IMAGE_DIR)
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
def get_image_description(image_bytes: bytes) -> str:
|
| 14 |
-
"""
|
| 15 |
-
Esta é a função que se comunicará com um modelo de visão.
|
| 16 |
-
Por enquanto, ela apenas retorna um placeholder.
|
| 17 |
-
"""
|
| 18 |
-
# TODO: Implementar a chamada para a API de visão (ex: OpenAI GPT-4o)
|
| 19 |
-
# from openai import OpenAI
|
| 20 |
-
# client = OpenAI(api_key="SUA_CHAVE_API")
|
| 21 |
-
# ... chamada da API ...
|
| 22 |
-
return "[Descrição da imagem pendente]"
|
| 23 |
-
|
| 24 |
-
def process_pdf(pdf_path: str) -> str:
|
| 25 |
-
"""
|
| 26 |
-
Processa um único arquivo PDF, extraindo texto e descrevendo imagens.
|
| 27 |
-
|
| 28 |
-
Args:
|
| 29 |
-
pdf_path: O caminho para o arquivo PDF.
|
| 30 |
-
|
| 31 |
-
Returns:
|
| 32 |
-
Uma string contendo todo o texto consolidado do PDF.
|
| 33 |
-
"""
|
| 34 |
-
print(f"Processando PDF: {pdf_path}...")
|
| 35 |
-
doc = fitz.open(pdf_path)
|
| 36 |
-
consolidated_text = ""
|
| 37 |
-
|
| 38 |
-
for page_num, page in enumerate(doc):
|
| 39 |
-
# 1. Extrair texto da página
|
| 40 |
-
consolidated_text += f"--- Página {page_num + 1} ---\n"
|
| 41 |
-
consolidated_text += page.get_text()
|
| 42 |
-
consolidated_text += "\n"
|
| 43 |
-
|
| 44 |
-
# 2. Extrair imagens da página
|
| 45 |
-
image_list = page.get_images(full=True)
|
| 46 |
-
if image_list:
|
| 47 |
-
consolidated_text += f"\n[IMAGENS ENCONTRADAS NA PÁGINA {page_num + 1}]\n"
|
| 48 |
-
|
| 49 |
-
for img_index, img in enumerate(image_list):
|
| 50 |
-
xref = img[0]
|
| 51 |
-
base_image = doc.extract_image(xref)
|
| 52 |
-
image_bytes = base_image["image"]
|
| 53 |
-
|
| 54 |
-
# Obter descrição da imagem (atualmente um placeholder)
|
| 55 |
-
description = get_image_description(image_bytes)
|
| 56 |
-
|
| 57 |
-
consolidated_text += f"- Imagem {img_index + 1}: {description}\n"
|
| 58 |
-
|
| 59 |
-
# Opcional: Salvar a imagem em disco para verificação
|
| 60 |
-
image_ext = base_image["ext"]
|
| 61 |
-
image_filename = f"{os.path.basename(pdf_path)}_p{page_num+1}_img{img_index+1}.{image_ext}"
|
| 62 |
-
image_path = os.path.join(OUTPUT_IMAGE_DIR, image_filename)
|
| 63 |
-
with open(image_path, "wb") as img_file:
|
| 64 |
-
img_file.write(image_bytes)
|
| 65 |
-
# print(f" - Imagem salva em: {image_path}")
|
| 66 |
-
|
| 67 |
-
doc.close()
|
| 68 |
-
print("Processamento concluído.")
|
| 69 |
-
return consolidated_text
|
| 70 |
-
|
| 71 |
-
# --- Exemplo de Uso ---
|
| 72 |
-
if __name__ == "__main__":
|
| 73 |
-
# Encontre um PDF no seu workspace para testar
|
| 74 |
-
# Vou usar um que vi na sua estrutura de arquivos.
|
| 75 |
-
# Adapte o caminho se necessário.
|
| 76 |
-
test_pdf_path = "DH.pdf"
|
| 77 |
-
|
| 78 |
-
if os.path.exists(test_pdf_path):
|
| 79 |
-
full_text_content = process_pdf(test_pdf_path)
|
| 80 |
-
|
| 81 |
-
# Salva o resultado em um arquivo de texto para análise
|
| 82 |
-
output_txt_filename = f"{os.path.basename(test_pdf_path)}.txt"
|
| 83 |
-
with open(output_txt_filename, "w", encoding="utf-8") as f:
|
| 84 |
-
f.write(full_text_content)
|
| 85 |
-
|
| 86 |
-
print(f"\nConteúdo extraído e salvo em '{output_txt_filename}'")
|
| 87 |
-
# print("\n--- CONTEÚDO EXTRAÍDO ---")
|
| 88 |
-
# print(full_text_content)
|
| 89 |
-
else:
|
| 90 |
-
print(f"Arquivo de teste não encontrado em: {test_pdf_path}")
|
| 91 |
-
print("Por favor, ajuste a variável 'test_pdf_path' no final do script para um PDF existente.")
|
| 92 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/session_resume.py
DELETED
|
@@ -1,75 +0,0 @@
|
|
| 1 |
-
import whisper
|
| 2 |
-
import openai
|
| 3 |
-
from utils.api_key import PYANNOTE_API_KEY
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
LLM_MODEL = "deepseek-r1:latest" # ou "llama3"
|
| 7 |
-
# da pra trocar pelo modelo local usando vllm
|
| 8 |
-
|
| 9 |
-
def assign_speaker(segment, diarization):
|
| 10 |
-
for turn, _, speaker in diarization.itertracks(yield_label=True):
|
| 11 |
-
if turn.start <= segment["start"] <= turn.end:
|
| 12 |
-
return speaker
|
| 13 |
-
return "Unknown"
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
def transcribe_audio_to_text(audio_path: str) -> str:
|
| 17 |
-
"""
|
| 18 |
-
Transcreve um arquivo de áudio para texto usando Whisper.
|
| 19 |
-
|
| 20 |
-
Args:
|
| 21 |
-
audio_path: O caminho para o arquivo de áudio.
|
| 22 |
-
|
| 23 |
-
Returns:
|
| 24 |
-
A transcrição do áudio como uma string.
|
| 25 |
-
"""
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
model = whisper.load_model("large", device="cuda")
|
| 29 |
-
result = model.transcribe(audio_path,verbose=True)
|
| 30 |
-
|
| 31 |
-
segments = result["segments"]
|
| 32 |
-
|
| 33 |
-
from pyannote.audio import Pipeline
|
| 34 |
-
|
| 35 |
-
pipeline = Pipeline.from_pretrained(
|
| 36 |
-
"pyannote/speaker-diarization",
|
| 37 |
-
use_auth_token=PYANNOTE_API_KEY
|
| 38 |
-
)
|
| 39 |
-
|
| 40 |
-
diarization = pipeline(audio_path)
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
for seg in segments:
|
| 44 |
-
speaker = assign_speaker(seg, diarization)
|
| 45 |
-
print(f"{speaker}: {seg['text']}")
|
| 46 |
-
|
| 47 |
-
print(result)
|
| 48 |
-
return segments
|
| 49 |
-
|
| 50 |
-
def summarize_session_text(session_text: str) -> str:
|
| 51 |
-
"""
|
| 52 |
-
Resume o texto da sessão usando um modelo LLM.
|
| 53 |
-
|
| 54 |
-
Args:
|
| 55 |
-
session_text: O texto completo da sessão.
|
| 56 |
-
|
| 57 |
-
Returns:
|
| 58 |
-
Um resumo do texto da sessão.
|
| 59 |
-
"""
|
| 60 |
-
from langchain_ollama import OllamaLLM
|
| 61 |
-
|
| 62 |
-
llm = OllamaLLM(
|
| 63 |
-
model=LLM_MODEL, # ou "llama3"
|
| 64 |
-
temperature=1.0, # Aumenta a criatividade e reduz filtros
|
| 65 |
-
top_p=0.95, # Aumenta a diversidade de respostas
|
| 66 |
-
top_k=40, # Permite mais tokens candidatos
|
| 67 |
-
num_ctx=4096 # Contexto maior
|
| 68 |
-
)
|
| 69 |
-
prompt = f"Resuma oque aconteceu na seguinte sessão de RPG:\n\n{session_text}\n\nResumo:"
|
| 70 |
-
summary = llm.invoke(prompt)
|
| 71 |
-
return summary
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
transcribe_audio_to_text("Data/Audios/c4e1.mp4")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/testes.ipynb
DELETED
|
@@ -1,405 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"cells": [
|
| 3 |
-
{
|
| 4 |
-
"cell_type": "code",
|
| 5 |
-
"execution_count": 26,
|
| 6 |
-
"id": "cfad16e7",
|
| 7 |
-
"metadata": {},
|
| 8 |
-
"outputs": [
|
| 9 |
-
{
|
| 10 |
-
"name": "stdout",
|
| 11 |
-
"output_type": "stream",
|
| 12 |
-
"text": [
|
| 13 |
-
"Read file: Lore/Guilds/Formulario de Inscrição.txt with content length: 816\n",
|
| 14 |
-
"Read file: Lore/Historia/As cores.txt with content length: 170\n",
|
| 15 |
-
"Read file: Lore/Historia/Deuses.txt with content length: 1288\n",
|
| 16 |
-
"Read file: Lore/Livros/A traição de Aghamina, por Lord Gamon.txt with content length: 1952\n",
|
| 17 |
-
"Read file: Lore/Livros/A lenda dos 7.txt with content length: 2385\n",
|
| 18 |
-
"Read file: Lore/Livros/A Heroina Aghamina.txt with content length: 2240\n",
|
| 19 |
-
"Read file: Cristais/Cristais.txt with content length: 1150\n",
|
| 20 |
-
"Read file: Cristais/Cristais/Afixos.txt with content length: 1264\n",
|
| 21 |
-
"Read file: Cristais/Cristais/Cristal de Gelo I/Bolinha de Neve.txt with content length: 1468\n",
|
| 22 |
-
"Read file: Cristais/Cristais/Cristal de Gelo I/Coruja.txt with content length: 110\n",
|
| 23 |
-
"Read file: Cristais/Cristais/Cristal de Gelo I/Urso polar elemental.txt with content length: 0\n",
|
| 24 |
-
"Read file: Cristais/Cristais/Cristal de Gelo I/Baguera, O tigre gelido.txt with content length: 1152\n",
|
| 25 |
-
"Read file: Cristais/Cristais/Cristal de Água I/Giff.txt with content length: 47\n",
|
| 26 |
-
"Read file: Cristais/Cristais/Cristal de Água I/Jaré.txt with content length: 0\n",
|
| 27 |
-
"Read file: Cristais/Cristais/Cristal de Água I/O Patorro.txt with content length: 0\n",
|
| 28 |
-
"Read file: Cristais/Cristais/Cristal de Fogo I/Aranha Infernal.txt with content length: 62\n",
|
| 29 |
-
"Read file: Cristais/Cristais/Cristal de Fogo I/Filhote de Anjarex.txt with content length: 0\n",
|
| 30 |
-
"Read file: Cristais/Cristais/Cristal de Fogo I/Kobold Escudragão.txt with content length: 81\n",
|
| 31 |
-
"Read file: Mundo/Linguas.txt with content length: 1404\n",
|
| 32 |
-
"Read file: Mundo/Ekalia.txt with content length: 115\n",
|
| 33 |
-
"Read file: Mundo/Continentes/Ploya.txt with content length: 272\n",
|
| 34 |
-
"Read file: Mundo/Continentes/Amaril.txt with content length: 47\n",
|
| 35 |
-
"Read file: Mundo/Continentes/Soléternel.txt with content length: 39\n",
|
| 36 |
-
"Read file: Mundo/Continentes/Paises_Ploya/TerraMijada.txt with content length: 0\n",
|
| 37 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Costas Piratas/Ressamar.txt with content length: 214\n",
|
| 38 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Costas Piratas/Farragemar.txt with content length: 196\n",
|
| 39 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terras Vivas/SilvanVale.txt with content length: 439\n",
|
| 40 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terras Vivas/Furtunasue.txt with content length: 309\n",
|
| 41 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terras Vivas/Steinberg.txt with content length: 587\n",
|
| 42 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terras Vivas/Maraven.txt with content length: 506\n",
|
| 43 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terras Vivas/Matareal.txt with content length: 455\n",
|
| 44 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glückslott.txt with content length: 579\n",
|
| 45 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Andarilhos.txt with content length: 252\n",
|
| 46 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Fauna.txt with content length: 458\n",
|
| 47 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/As minas de Glüsckssot.txt with content length: 50\n",
|
| 48 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/Tavernas/Helle Oase.txt with content length: 2031\n",
|
| 49 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/Tavernas/Helle Oase (Oasis brilhante).txt with content length: 2037\n",
|
| 50 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/Tavernas/Wüstenwinde (Ventos do deserto).txt with content length: 1679\n",
|
| 51 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/Lojas/Mercado principal/Emporio do Solstício (Itens Magicos).txt with content length: 1176\n",
|
| 52 |
-
"Read file: Mundo/Continentes/Paises_Ploya/Terra Mijada/Glusckslott/Lojas/Mercado principal/Antiguidades do Deserto(Relíquias).txt with content length: 61\n",
|
| 53 |
-
"Read file: Mundo/Guildas/Gelb Skarabäus.txt with content length: 179\n",
|
| 54 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/Escaravelho amarelo.txt with content length: 0\n",
|
| 55 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCs.txt with content length: 0\n",
|
| 56 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Taverneira (Krea).txt with content length: 728\n",
|
| 57 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Krea Hammerhemd.txt with content length: 728\n",
|
| 58 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Guild Master (Atur).txt with content length: 812\n",
|
| 59 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Askad Edelmetall.txt with content length: 758\n",
|
| 60 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Atur Hammerhemd.txt with content length: 0\n",
|
| 61 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Quest G (Askad).txt with content length: 758\n",
|
| 62 |
-
"Read file: Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Cozinheira (Thrinan).txt with content length: 900\n",
|
| 63 |
-
"Read file: Campanhas/A Cidade Dourada/Sessão 01.txt with content length: 1468\n",
|
| 64 |
-
"Read file: Campanhas/A Cidade Dourada/Sessão 02.txt with content length: 144\n",
|
| 65 |
-
"Read file: Campanhas/A Cidade Dourada/Sessão 03.txt with content length: 0\n",
|
| 66 |
-
"Read file: Campanhas/A Cidade Dourada/NPCs/Zackrias Bluff.txt with content length: 0\n",
|
| 67 |
-
"Read file: Campanhas/A Cidade Dourada/Inimigos/Os Meninos.txt with content length: 1296\n",
|
| 68 |
-
"Read file: Campanhas/A Cidade Dourada/Inimigos/Ignacio.txt with content length: 86\n"
|
| 69 |
-
]
|
| 70 |
-
},
|
| 71 |
-
{
|
| 72 |
-
"data": {
|
| 73 |
-
"text/html": [
|
| 74 |
-
"<div>\n",
|
| 75 |
-
"<style scoped>\n",
|
| 76 |
-
" .dataframe tbody tr th:only-of-type {\n",
|
| 77 |
-
" vertical-align: middle;\n",
|
| 78 |
-
" }\n",
|
| 79 |
-
"\n",
|
| 80 |
-
" .dataframe tbody tr th {\n",
|
| 81 |
-
" vertical-align: top;\n",
|
| 82 |
-
" }\n",
|
| 83 |
-
"\n",
|
| 84 |
-
" .dataframe thead th {\n",
|
| 85 |
-
" text-align: right;\n",
|
| 86 |
-
" }\n",
|
| 87 |
-
"</style>\n",
|
| 88 |
-
"<table border=\"1\" class=\"dataframe\">\n",
|
| 89 |
-
" <thead>\n",
|
| 90 |
-
" <tr style=\"text-align: right;\">\n",
|
| 91 |
-
" <th></th>\n",
|
| 92 |
-
" <th>Lore/Guilds/Formulario de Inscrição.txt</th>\n",
|
| 93 |
-
" <th>Lore/Historia/As cores.txt</th>\n",
|
| 94 |
-
" <th>Lore/Historia/Deuses.txt</th>\n",
|
| 95 |
-
" <th>Lore/Livros/A traição de Aghamina, por Lord Gamon.txt</th>\n",
|
| 96 |
-
" <th>Lore/Livros/A lenda dos 7.txt</th>\n",
|
| 97 |
-
" <th>Lore/Livros/A Heroina Aghamina.txt</th>\n",
|
| 98 |
-
" <th>Cristais/Cristais.txt</th>\n",
|
| 99 |
-
" <th>Cristais/Cristais/Afixos.txt</th>\n",
|
| 100 |
-
" <th>Cristais/Cristais/Cristal de Gelo I/Bolinha de Neve.txt</th>\n",
|
| 101 |
-
" <th>Cristais/Cristais/Cristal de Gelo I/Coruja.txt</th>\n",
|
| 102 |
-
" <th>...</th>\n",
|
| 103 |
-
" <th>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Askad Edelmetall.txt</th>\n",
|
| 104 |
-
" <th>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Atur Hammerhemd.txt</th>\n",
|
| 105 |
-
" <th>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Quest G (Askad).txt</th>\n",
|
| 106 |
-
" <th>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Cozinheira (Thrinan).txt</th>\n",
|
| 107 |
-
" <th>Campanhas/A Cidade Dourada/Sessão 01.txt</th>\n",
|
| 108 |
-
" <th>Campanhas/A Cidade Dourada/Sessão 02.txt</th>\n",
|
| 109 |
-
" <th>Campanhas/A Cidade Dourada/Sessão 03.txt</th>\n",
|
| 110 |
-
" <th>Campanhas/A Cidade Dourada/NPCs/Zackrias Bluff.txt</th>\n",
|
| 111 |
-
" <th>Campanhas/A Cidade Dourada/Inimigos/Os Meninos.txt</th>\n",
|
| 112 |
-
" <th>Campanhas/A Cidade Dourada/Inimigos/Ignacio.txt</th>\n",
|
| 113 |
-
" </tr>\n",
|
| 114 |
-
" </thead>\n",
|
| 115 |
-
" <tbody>\n",
|
| 116 |
-
" <tr>\n",
|
| 117 |
-
" <th>file name</th>\n",
|
| 118 |
-
" <td>Lore/Guilds/Formulario de Inscrição.txt</td>\n",
|
| 119 |
-
" <td>Lore/Historia/As cores.txt</td>\n",
|
| 120 |
-
" <td>Lore/Historia/Deuses.txt</td>\n",
|
| 121 |
-
" <td>Lore/Livros/A traição de Aghamina, por Lord Ga...</td>\n",
|
| 122 |
-
" <td>Lore/Livros/A lenda dos 7.txt</td>\n",
|
| 123 |
-
" <td>Lore/Livros/A Heroina Aghamina.txt</td>\n",
|
| 124 |
-
" <td>Cristais/Cristais.txt</td>\n",
|
| 125 |
-
" <td>Cristais/Cristais/Afixos.txt</td>\n",
|
| 126 |
-
" <td>Cristais/Cristais/Cristal de Gelo I/Bolinha de...</td>\n",
|
| 127 |
-
" <td>Cristais/Cristais/Cristal de Gelo I/Coruja.txt</td>\n",
|
| 128 |
-
" <td>...</td>\n",
|
| 129 |
-
" <td>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Ask...</td>\n",
|
| 130 |
-
" <td>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Atu...</td>\n",
|
| 131 |
-
" <td>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Que...</td>\n",
|
| 132 |
-
" <td>Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Coz...</td>\n",
|
| 133 |
-
" <td>Campanhas/A Cidade Dourada/Sessão 01.txt</td>\n",
|
| 134 |
-
" <td>Campanhas/A Cidade Dourada/Sessão 02.txt</td>\n",
|
| 135 |
-
" <td>Campanhas/A Cidade Dourada/Sessão 03.txt</td>\n",
|
| 136 |
-
" <td>Campanhas/A Cidade Dourada/NPCs/Zackrias Bluff...</td>\n",
|
| 137 |
-
" <td>Campanhas/A Cidade Dourada/Inimigos/Os Meninos...</td>\n",
|
| 138 |
-
" <td>Campanhas/A Cidade Dourada/Inimigos/Ignacio.txt</td>\n",
|
| 139 |
-
" </tr>\n",
|
| 140 |
-
" <tr>\n",
|
| 141 |
-
" <th>content</th>\n",
|
| 142 |
-
" <td>Nome Completo:\\nIncluir um campo para o nome c...</td>\n",
|
| 143 |
-
" <td>Vermelho\\tVida\\t\\tIvo\\nLaranja \\tEnergia\\t\\tEl...</td>\n",
|
| 144 |
-
" <td>Janus Brightspark, Rato Guardião, Deus da Enge...</td>\n",
|
| 145 |
-
" <td>Anos depois da grande vitória sobre Zeref, Eka...</td>\n",
|
| 146 |
-
" <td>Em um mundo distante, no reino de Ekalia, as t...</td>\n",
|
| 147 |
-
" <td>Anos após a vitória sobre Zeref, Ekalia vivia ...</td>\n",
|
| 148 |
-
" <td># Oque são Cristais?\\n\\nOs Cristais são pedras...</td>\n",
|
| 149 |
-
" <td>Afixos\\n\\n\\tMisericordioso\\nEsse inimigo ignor...</td>\n",
|
| 150 |
-
" <td>Bolinha de neve (80HP AC 12)\\n\\nAfixos: Miseri...</td>\n",
|
| 151 |
-
" <td>Frostaluna (40HP 13AC)\\n\\n\\nAfixos: Misericord...</td>\n",
|
| 152 |
-
" <td>...</td>\n",
|
| 153 |
-
" <td>Askad Edelmetall\\né uma feiticeira nível 10, a...</td>\n",
|
| 154 |
-
" <td></td>\n",
|
| 155 |
-
" <td>Askad Edelmetall\\né uma feiticeira nível 10, a...</td>\n",
|
| 156 |
-
" <td>Thrinan Kieselstein\\n\\né uma cozinheira anã da...</td>\n",
|
| 157 |
-
" <td>Retcon: \\nA viagem dos 4 foi conduzida por um ...</td>\n",
|
| 158 |
-
" <td>Recap:\\nNa sessão passada, nossos heróis(?) fo...</td>\n",
|
| 159 |
-
" <td></td>\n",
|
| 160 |
-
" <td></td>\n",
|
| 161 |
-
" <td>Primeiros Boss caso seja no armazem\\n\\n\\nOs Me...</td>\n",
|
| 162 |
-
" <td>Primeiro boss caso batalhem na caravana\\n\\n\\n\\...</td>\n",
|
| 163 |
-
" </tr>\n",
|
| 164 |
-
" </tbody>\n",
|
| 165 |
-
"</table>\n",
|
| 166 |
-
"<p>2 rows × 56 columns</p>\n",
|
| 167 |
-
"</div>"
|
| 168 |
-
],
|
| 169 |
-
"text/plain": [
|
| 170 |
-
" Lore/Guilds/Formulario de Inscrição.txt \\\n",
|
| 171 |
-
"file name Lore/Guilds/Formulario de Inscrição.txt \n",
|
| 172 |
-
"content Nome Completo:\\nIncluir um campo para o nome c... \n",
|
| 173 |
-
"\n",
|
| 174 |
-
" Lore/Historia/As cores.txt \\\n",
|
| 175 |
-
"file name Lore/Historia/As cores.txt \n",
|
| 176 |
-
"content Vermelho\\tVida\\t\\tIvo\\nLaranja \\tEnergia\\t\\tEl... \n",
|
| 177 |
-
"\n",
|
| 178 |
-
" Lore/Historia/Deuses.txt \\\n",
|
| 179 |
-
"file name Lore/Historia/Deuses.txt \n",
|
| 180 |
-
"content Janus Brightspark, Rato Guardião, Deus da Enge... \n",
|
| 181 |
-
"\n",
|
| 182 |
-
" Lore/Livros/A traição de Aghamina, por Lord Gamon.txt \\\n",
|
| 183 |
-
"file name Lore/Livros/A traição de Aghamina, por Lord Ga... \n",
|
| 184 |
-
"content Anos depois da grande vitória sobre Zeref, Eka... \n",
|
| 185 |
-
"\n",
|
| 186 |
-
" Lore/Livros/A lenda dos 7.txt \\\n",
|
| 187 |
-
"file name Lore/Livros/A lenda dos 7.txt \n",
|
| 188 |
-
"content Em um mundo distante, no reino de Ekalia, as t... \n",
|
| 189 |
-
"\n",
|
| 190 |
-
" Lore/Livros/A Heroina Aghamina.txt \\\n",
|
| 191 |
-
"file name Lore/Livros/A Heroina Aghamina.txt \n",
|
| 192 |
-
"content Anos após a vitória sobre Zeref, Ekalia vivia ... \n",
|
| 193 |
-
"\n",
|
| 194 |
-
" Cristais/Cristais.txt \\\n",
|
| 195 |
-
"file name Cristais/Cristais.txt \n",
|
| 196 |
-
"content # Oque são Cristais?\\n\\nOs Cristais são pedras... \n",
|
| 197 |
-
"\n",
|
| 198 |
-
" Cristais/Cristais/Afixos.txt \\\n",
|
| 199 |
-
"file name Cristais/Cristais/Afixos.txt \n",
|
| 200 |
-
"content Afixos\\n\\n\\tMisericordioso\\nEsse inimigo ignor... \n",
|
| 201 |
-
"\n",
|
| 202 |
-
" Cristais/Cristais/Cristal de Gelo I/Bolinha de Neve.txt \\\n",
|
| 203 |
-
"file name Cristais/Cristais/Cristal de Gelo I/Bolinha de... \n",
|
| 204 |
-
"content Bolinha de neve (80HP AC 12)\\n\\nAfixos: Miseri... \n",
|
| 205 |
-
"\n",
|
| 206 |
-
" Cristais/Cristais/Cristal de Gelo I/Coruja.txt ... \\\n",
|
| 207 |
-
"file name Cristais/Cristais/Cristal de Gelo I/Coruja.txt ... \n",
|
| 208 |
-
"content Frostaluna (40HP 13AC)\\n\\n\\nAfixos: Misericord... ... \n",
|
| 209 |
-
"\n",
|
| 210 |
-
" Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Askad Edelmetall.txt \\\n",
|
| 211 |
-
"file name Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Ask... \n",
|
| 212 |
-
"content Askad Edelmetall\\né uma feiticeira nível 10, a... \n",
|
| 213 |
-
"\n",
|
| 214 |
-
" Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Atur Hammerhemd.txt \\\n",
|
| 215 |
-
"file name Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Atu... \n",
|
| 216 |
-
"content \n",
|
| 217 |
-
"\n",
|
| 218 |
-
" Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Quest G (Askad).txt \\\n",
|
| 219 |
-
"file name Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Que... \n",
|
| 220 |
-
"content Askad Edelmetall\\né uma feiticeira nível 10, a... \n",
|
| 221 |
-
"\n",
|
| 222 |
-
" Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Cozinheira (Thrinan).txt \\\n",
|
| 223 |
-
"file name Mundo/Guildas/Guilda (Gelb Skarabäus)/NPCS/Coz... \n",
|
| 224 |
-
"content Thrinan Kieselstein\\n\\né uma cozinheira anã da... \n",
|
| 225 |
-
"\n",
|
| 226 |
-
" Campanhas/A Cidade Dourada/Sessão 01.txt \\\n",
|
| 227 |
-
"file name Campanhas/A Cidade Dourada/Sessão 01.txt \n",
|
| 228 |
-
"content Retcon: \\nA viagem dos 4 foi conduzida por um ... \n",
|
| 229 |
-
"\n",
|
| 230 |
-
" Campanhas/A Cidade Dourada/Sessão 02.txt \\\n",
|
| 231 |
-
"file name Campanhas/A Cidade Dourada/Sessão 02.txt \n",
|
| 232 |
-
"content Recap:\\nNa sessão passada, nossos heróis(?) fo... \n",
|
| 233 |
-
"\n",
|
| 234 |
-
" Campanhas/A Cidade Dourada/Sessão 03.txt \\\n",
|
| 235 |
-
"file name Campanhas/A Cidade Dourada/Sessão 03.txt \n",
|
| 236 |
-
"content \n",
|
| 237 |
-
"\n",
|
| 238 |
-
" Campanhas/A Cidade Dourada/NPCs/Zackrias Bluff.txt \\\n",
|
| 239 |
-
"file name Campanhas/A Cidade Dourada/NPCs/Zackrias Bluff... \n",
|
| 240 |
-
"content \n",
|
| 241 |
-
"\n",
|
| 242 |
-
" Campanhas/A Cidade Dourada/Inimigos/Os Meninos.txt \\\n",
|
| 243 |
-
"file name Campanhas/A Cidade Dourada/Inimigos/Os Meninos... \n",
|
| 244 |
-
"content Primeiros Boss caso seja no armazem\\n\\n\\nOs Me... \n",
|
| 245 |
-
"\n",
|
| 246 |
-
" Campanhas/A Cidade Dourada/Inimigos/Ignacio.txt \n",
|
| 247 |
-
"file name Campanhas/A Cidade Dourada/Inimigos/Ignacio.txt \n",
|
| 248 |
-
"content Primeiro boss caso batalhem na caravana\\n\\n\\n\\... \n",
|
| 249 |
-
"\n",
|
| 250 |
-
"[2 rows x 56 columns]"
|
| 251 |
-
]
|
| 252 |
-
},
|
| 253 |
-
"execution_count": 26,
|
| 254 |
-
"metadata": {},
|
| 255 |
-
"output_type": "execute_result"
|
| 256 |
-
}
|
| 257 |
-
],
|
| 258 |
-
"source": [
|
| 259 |
-
"from src.utils.get_data import get_data\n",
|
| 260 |
-
"\n",
|
| 261 |
-
"\n",
|
| 262 |
-
"\n",
|
| 263 |
-
"data = get_data()\n",
|
| 264 |
-
"\n",
|
| 265 |
-
"import pandas as pd\n",
|
| 266 |
-
"df = pd.DataFrame.from_dict(data)\n",
|
| 267 |
-
"df"
|
| 268 |
-
]
|
| 269 |
-
},
|
| 270 |
-
{
|
| 271 |
-
"cell_type": "code",
|
| 272 |
-
"execution_count": 9,
|
| 273 |
-
"id": "f073a9c9",
|
| 274 |
-
"metadata": {},
|
| 275 |
-
"outputs": [
|
| 276 |
-
{
|
| 277 |
-
"data": {
|
| 278 |
-
"text/html": [
|
| 279 |
-
"<div>\n",
|
| 280 |
-
"<style scoped>\n",
|
| 281 |
-
" .dataframe tbody tr th:only-of-type {\n",
|
| 282 |
-
" vertical-align: middle;\n",
|
| 283 |
-
" }\n",
|
| 284 |
-
"\n",
|
| 285 |
-
" .dataframe tbody tr th {\n",
|
| 286 |
-
" vertical-align: top;\n",
|
| 287 |
-
" }\n",
|
| 288 |
-
"\n",
|
| 289 |
-
" .dataframe thead th {\n",
|
| 290 |
-
" text-align: right;\n",
|
| 291 |
-
" }\n",
|
| 292 |
-
"</style>\n",
|
| 293 |
-
"<table border=\"1\" class=\"dataframe\">\n",
|
| 294 |
-
" <thead>\n",
|
| 295 |
-
" <tr style=\"text-align: right;\">\n",
|
| 296 |
-
" <th></th>\n",
|
| 297 |
-
" <th>File Name</th>\n",
|
| 298 |
-
" <th>Content</th>\n",
|
| 299 |
-
" <th>Context</th>\n",
|
| 300 |
-
" </tr>\n",
|
| 301 |
-
" </thead>\n",
|
| 302 |
-
" <tbody>\n",
|
| 303 |
-
" <tr>\n",
|
| 304 |
-
" <th>0</th>\n",
|
| 305 |
-
" <td>asdasd</td>\n",
|
| 306 |
-
" <td>asdasdasd</td>\n",
|
| 307 |
-
" <td>asdasdasd</td>\n",
|
| 308 |
-
" </tr>\n",
|
| 309 |
-
" </tbody>\n",
|
| 310 |
-
"</table>\n",
|
| 311 |
-
"</div>"
|
| 312 |
-
],
|
| 313 |
-
"text/plain": [
|
| 314 |
-
" File Name Content Context\n",
|
| 315 |
-
"0 asdasd asdasdasd asdasdasd"
|
| 316 |
-
]
|
| 317 |
-
},
|
| 318 |
-
"execution_count": 9,
|
| 319 |
-
"metadata": {},
|
| 320 |
-
"output_type": "execute_result"
|
| 321 |
-
}
|
| 322 |
-
],
|
| 323 |
-
"source": [
|
| 324 |
-
"test = {'File Name': [], 'Content': [], 'Context': []}\n",
|
| 325 |
-
"\n",
|
| 326 |
-
"\n",
|
| 327 |
-
"test['File Name'].append('asdasd')\n",
|
| 328 |
-
"test['Content'].append('asdasdasd')\n",
|
| 329 |
-
"test['Context'].append('asdasdasd')\n",
|
| 330 |
-
"\n",
|
| 331 |
-
"df2 = pd.DataFrame.from_dict(test)\n",
|
| 332 |
-
"df2.head()"
|
| 333 |
-
]
|
| 334 |
-
},
|
| 335 |
-
{
|
| 336 |
-
"cell_type": "code",
|
| 337 |
-
"execution_count": 17,
|
| 338 |
-
"id": "1d8236f5",
|
| 339 |
-
"metadata": {},
|
| 340 |
-
"outputs": [
|
| 341 |
-
{
|
| 342 |
-
"name": "stdout",
|
| 343 |
-
"output_type": "stream",
|
| 344 |
-
"text": [
|
| 345 |
-
"O erro é: 0.03530823858545563\n"
|
| 346 |
-
]
|
| 347 |
-
}
|
| 348 |
-
],
|
| 349 |
-
"source": [
|
| 350 |
-
"import math \n",
|
| 351 |
-
"\n",
|
| 352 |
-
"e = math.e\n",
|
| 353 |
-
"k = 0.05\n",
|
| 354 |
-
"\n",
|
| 355 |
-
"\n",
|
| 356 |
-
"def calculate_p(m):\n",
|
| 357 |
-
" d = (10)\n",
|
| 358 |
-
" d0 = 200\n",
|
| 359 |
-
"\n",
|
| 360 |
-
" I = (0.55)\n",
|
| 361 |
-
" I = min(1, max(I,0))\n",
|
| 362 |
-
"\n",
|
| 363 |
-
" C = len(m.split(\" \"))/len(m)\n",
|
| 364 |
-
" C = min(1, max(C, 0))\n",
|
| 365 |
-
" d_critico = d0*((1-I)*(1-C))\n",
|
| 366 |
-
" p_erro = 1/(1 + e**(-k*(d - d_critico)))\n",
|
| 367 |
-
" print(f\"O erro é: {p_erro}\")\n",
|
| 368 |
-
" return p_erro\n",
|
| 369 |
-
"\n",
|
| 370 |
-
"\n",
|
| 371 |
-
"msg = \"sexo selvagem\"\n",
|
| 372 |
-
"p_erro = calculate_p(msg)"
|
| 373 |
-
]
|
| 374 |
-
},
|
| 375 |
-
{
|
| 376 |
-
"cell_type": "code",
|
| 377 |
-
"execution_count": null,
|
| 378 |
-
"id": "32b611de",
|
| 379 |
-
"metadata": {},
|
| 380 |
-
"outputs": [],
|
| 381 |
-
"source": []
|
| 382 |
-
}
|
| 383 |
-
],
|
| 384 |
-
"metadata": {
|
| 385 |
-
"kernelspec": {
|
| 386 |
-
"display_name": "RPG-RAG",
|
| 387 |
-
"language": "python",
|
| 388 |
-
"name": "python3"
|
| 389 |
-
},
|
| 390 |
-
"language_info": {
|
| 391 |
-
"codemirror_mode": {
|
| 392 |
-
"name": "ipython",
|
| 393 |
-
"version": 3
|
| 394 |
-
},
|
| 395 |
-
"file_extension": ".py",
|
| 396 |
-
"mimetype": "text/x-python",
|
| 397 |
-
"name": "python",
|
| 398 |
-
"nbconvert_exporter": "python",
|
| 399 |
-
"pygments_lexer": "ipython3",
|
| 400 |
-
"version": "3.12.0"
|
| 401 |
-
}
|
| 402 |
-
},
|
| 403 |
-
"nbformat": 4,
|
| 404 |
-
"nbformat_minor": 5
|
| 405 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/utils/__init__.py
DELETED
|
File without changes
|
legacy/src/utils/__pycache__/__init__.cpython-312.pyc
DELETED
|
Binary file (148 Bytes)
|
|
|
legacy/src/utils/__pycache__/get_data.cpython-312.pyc
DELETED
|
Binary file (1.29 kB)
|
|
|
legacy/src/utils/api_key.py
DELETED
|
@@ -1,4 +0,0 @@
|
|
| 1 |
-
import os
|
| 2 |
-
|
| 3 |
-
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
|
| 4 |
-
PYANNOTE_API_KEY = os.getenv("PYANNOTE_API_KEY")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
legacy/src/utils/get_data.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
| 1 |
-
from pathlib import Path
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
# project root (RPG-RAG/)
|
| 5 |
-
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
| 6 |
-
|
| 7 |
-
# Data/Ekalia
|
| 8 |
-
DATA_DIR = PROJECT_ROOT / "Data" / "Ekalia"
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
def get_data():
|
| 12 |
-
data = {
|
| 13 |
-
"File Name": [],
|
| 14 |
-
"Context": [],
|
| 15 |
-
"Content": [],
|
| 16 |
-
}
|
| 17 |
-
|
| 18 |
-
for file_path in DATA_DIR.rglob("*.txt"):
|
| 19 |
-
content = file_path.read_text(encoding="utf-8")
|
| 20 |
-
|
| 21 |
-
data["File Name"].append(file_path.name)
|
| 22 |
-
data["Content"].append(content)
|
| 23 |
-
|
| 24 |
-
# Context = relative path inside Ekalia
|
| 25 |
-
context = file_path.parent.relative_to(DATA_DIR)
|
| 26 |
-
data["Context"].append(str(context))
|
| 27 |
-
|
| 28 |
-
print(f"Read file: {context}/{file_path.name} ({len(content)})")
|
| 29 |
-
|
| 30 |
-
return data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
main.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def main():
|
| 2 |
+
print("Hello from rpg-rag!")
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
if __name__ == "__main__":
|
| 6 |
+
main()
|
pyproject.toml
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "rpg-rag"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Add your description here"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
requires-python = ">=3.12"
|
| 7 |
+
dependencies = [
|
| 8 |
+
"gradio>=6.9.0",
|
| 9 |
+
"groq>=1.1.1",
|
| 10 |
+
"langchain>=1.2.12",
|
| 11 |
+
"langchain-ollama>=1.0.1",
|
| 12 |
+
"langchain-openai>=1.1.11",
|
| 13 |
+
"openai>=2.28.0",
|
| 14 |
+
"openai-whisper>=20250625",
|
| 15 |
+
"pandas>=3.0.1",
|
| 16 |
+
"pillow>=12.1.1",
|
| 17 |
+
"pyannote-audio>=4.0.4",
|
| 18 |
+
"pymupdf>=1.23.0",
|
| 19 |
+
"torch>=2.10.0",
|
| 20 |
+
"torchaudio>=2.10.0",
|
| 21 |
+
"torchvision>=0.25.0",
|
| 22 |
+
]
|
requirements.txt
CHANGED
|
@@ -20,5 +20,4 @@ PyMuPDF>=1.23.0
|
|
| 20 |
Pillow>=10.0.0
|
| 21 |
|
| 22 |
# HF Spaces
|
| 23 |
-
audioop-lts
|
| 24 |
gradio>=5.0.0
|
|
|
|
| 20 |
Pillow>=10.0.0
|
| 21 |
|
| 22 |
# HF Spaces
|
|
|
|
| 23 |
gradio>=5.0.0
|
src/llm/__pycache__/client.cpython-312.pyc
CHANGED
|
Binary files a/src/llm/__pycache__/client.cpython-312.pyc and b/src/llm/__pycache__/client.cpython-312.pyc differ
|
|
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|