Spaces:
Sleeping
Sleeping
EMMA commited on
Commit ·
367e76b
0
Parent(s):
Initial lightweight commit
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .dockerignore +9 -0
- .env +1 -0
- .gitattributes +5 -0
- .github/workflows/docker-publish.yml +27 -0
- .gitignore +6 -0
- Backup code/app_V1.py +727 -0
- Backup code/app_V11.py +944 -0
- Backup code/app_V12.py +964 -0
- Backup code/app_V13.py +973 -0
- Backup code/app_V14.py +1032 -0
- Backup code/app_V15.py +1031 -0
- Backup code/app_V2.py +751 -0
- Backup code/app_V3.py +751 -0
- Backup code/app_V4.py +855 -0
- Backup code/app_V5.py +881 -0
- Backup code/app_V6.py +854 -0
- Backup code/app_V7.py +901 -0
- Backup code/app_V8.py +907 -0
- Backup code/app_V9.py +934 -0
- Backup code/app_v10.py +848 -0
- Backup code/app_v17.py +1031 -0
- Backup code/memory_utils copy 2.py +276 -0
- Backup code/memory_utils copy.py +276 -0
- Backup code/memory_utils.py +246 -0
- Backup code/prompt_utils.py +215 -0
- Backup code/summarize_memory_v4.py +373 -0
- Backup code/summarize_memory_v5.py +381 -0
- Dockerfile +18 -0
- Emma/.gradio/certificate.pem +31 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/default__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/docstore.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/graph_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/image__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/index_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/default__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/docstore.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/graph_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/image__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/index_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/default__vector_store.json +0 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/docstore.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/graph_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/image__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/index_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/default__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/docstore.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/graph_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/image__vector_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/index_store.json +1 -0
- Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/semantic_memory/default__vector_store.json +1 -0
.dockerignore
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# .dockerignore
|
| 2 |
+
Classification_Model/xlm_r_router_results/
|
| 3 |
+
**/xlm_r_router_results
|
| 4 |
+
Classification_Model/final_xlm_r_model_router/
|
| 5 |
+
**/final_xlm_r_model_router
|
| 6 |
+
|
| 7 |
+
.git/
|
| 8 |
+
__pycache__/
|
| 9 |
+
|
.env
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
GAPGPT_API_KEY="sk-7kRI3ooFa8cd3Lwn7oQBjU1l7DgCp7UmlchaEWNt6d6utDKt"
|
.gitattributes
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.jpg filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.png filter=lfs diff=lfs merge=lfs -text
|
.github/workflows/docker-publish.yml
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Build and Push Docker Image
|
| 2 |
+
|
| 3 |
+
on:
|
| 4 |
+
push:
|
| 5 |
+
branches:
|
| 6 |
+
- main # اگر نام برنچ اصلی شما چیز دیگری مثل master است، آن را تغییر دهید
|
| 7 |
+
|
| 8 |
+
jobs:
|
| 9 |
+
build:
|
| 10 |
+
runs-on: ubuntu-latest
|
| 11 |
+
|
| 12 |
+
steps:
|
| 13 |
+
- name: Check out the repo
|
| 14 |
+
uses: actions/checkout@v3
|
| 15 |
+
|
| 16 |
+
- name: Log in to Docker Hub
|
| 17 |
+
uses: docker/login-action@v2
|
| 18 |
+
with:
|
| 19 |
+
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
| 20 |
+
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
| 21 |
+
|
| 22 |
+
- name: Build and push Docker image
|
| 23 |
+
uses: docker/build-push-action@v4
|
| 24 |
+
with:
|
| 25 |
+
context: .
|
| 26 |
+
push: true
|
| 27 |
+
tags: ${{ secrets.DOCKERHUB_USERNAME }}/emma-assistant:latest
|
.gitignore
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
*.pyc
|
| 3 |
+
.vscode/
|
| 4 |
+
.ipynb_checkpoints
|
| 5 |
+
Classification_Model/
|
| 6 |
+
wheels/
|
Backup code/app_V1.py
ADDED
|
@@ -0,0 +1,727 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
|
| 13 |
+
import gradio as gr
|
| 14 |
+
import nltk
|
| 15 |
+
import torch
|
| 16 |
+
import tiktoken
|
| 17 |
+
|
| 18 |
+
from openai import OpenAI as OpenAIClient
|
| 19 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 20 |
+
|
| 21 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 22 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 23 |
+
from llama_index.core import Settings
|
| 24 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 25 |
+
|
| 26 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 27 |
+
sys.path.append(prompt_path)
|
| 28 |
+
|
| 29 |
+
# Assuming these imports exist in your local environment
|
| 30 |
+
from utils.sys_args import data_args, model_args
|
| 31 |
+
from utils.app_modules.utils import *
|
| 32 |
+
from utils.app_modules.presets import *
|
| 33 |
+
from utils.app_modules.overwrites import *
|
| 34 |
+
from utils.prompt_utils import *
|
| 35 |
+
from utils.memory_utils import (
|
| 36 |
+
enter_name_llamaindex,
|
| 37 |
+
summarize_memory_event_personality,
|
| 38 |
+
save_local_memory,
|
| 39 |
+
extract_session_summary,
|
| 40 |
+
extract_semantic_memory,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# Ensure NLTK data path
|
| 44 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 45 |
+
|
| 46 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 47 |
+
|
| 48 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 49 |
+
openai_client_cache = {}
|
| 50 |
+
|
| 51 |
+
import torch
|
| 52 |
+
import torch.nn.functional as F
|
| 53 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 57 |
+
|
| 58 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 59 |
+
|
| 60 |
+
try:
|
| 61 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 62 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model.eval()
|
| 64 |
+
print("Local classifier loaded successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Error loading local classifier: {e}")
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 70 |
+
if not api_key:
|
| 71 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 72 |
+
if api_key not in openai_client_cache:
|
| 73 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 74 |
+
return openai_client_cache[api_key]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
os_name = platform.system()
|
| 78 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 79 |
+
stop_stream = False
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def signal_handler(signal_number, frame):
|
| 83 |
+
global stop_stream
|
| 84 |
+
stop_stream = True
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 88 |
+
|
| 89 |
+
# Update this path to your actual file location
|
| 90 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def read_apis(path):
|
| 94 |
+
api_keys_local = []
|
| 95 |
+
if os.path.exists(path):
|
| 96 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 97 |
+
for line in f:
|
| 98 |
+
line = line.strip()
|
| 99 |
+
if line:
|
| 100 |
+
api_keys_local.append(line)
|
| 101 |
+
return api_keys_local
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 105 |
+
|
| 106 |
+
# Ensure directory exists
|
| 107 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 108 |
+
|
| 109 |
+
if not os.path.exists(memory_dir):
|
| 110 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 111 |
+
|
| 112 |
+
global memory
|
| 113 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 114 |
+
language = 'en'
|
| 115 |
+
user_keyword = generate_user_keyword()[language]
|
| 116 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 117 |
+
boot_name = boot_name_dict[language]
|
| 118 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 119 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 120 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 122 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 123 |
+
|
| 124 |
+
api_keys = read_apis(api_path)
|
| 125 |
+
# Fallback if file is empty or missing for testing purposes
|
| 126 |
+
if not api_keys:
|
| 127 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 128 |
+
|
| 129 |
+
new_conversation = False
|
| 130 |
+
chatgpt_config = {
|
| 131 |
+
"model": "gpt-4o",
|
| 132 |
+
"temperature": 1,
|
| 133 |
+
"max_tokens": 1024,
|
| 134 |
+
"top_p": 0.95,
|
| 135 |
+
"frequency_penalty": 0.4,
|
| 136 |
+
"presence_penalty": 0.2,
|
| 137 |
+
"n": 1,
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
deactivated_keys = []
|
| 141 |
+
logging.basicConfig(
|
| 142 |
+
level=logging.DEBUG,
|
| 143 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 148 |
+
"""
|
| 149 |
+
Handles the chat request to OpenAI.
|
| 150 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 151 |
+
"""
|
| 152 |
+
retry_times, count = 5, 0
|
| 153 |
+
response = None
|
| 154 |
+
|
| 155 |
+
while response is None and count < retry_times:
|
| 156 |
+
try:
|
| 157 |
+
request = copy.deepcopy(gpt_config)
|
| 158 |
+
|
| 159 |
+
# Initial system and greeting messages
|
| 160 |
+
if data_args.language == 'en':
|
| 161 |
+
message = [
|
| 162 |
+
{"role": "system", "content": system.strip()},
|
| 163 |
+
{"role": "user", "content": "Hi!"},
|
| 164 |
+
{"role": "assistant",
|
| 165 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 166 |
+
]
|
| 167 |
+
else:
|
| 168 |
+
message = [
|
| 169 |
+
{"role": "system", "content": system.strip()},
|
| 170 |
+
{"role": "user", "content": "Hi"},
|
| 171 |
+
{"role": "assistant",
|
| 172 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 173 |
+
]
|
| 174 |
+
|
| 175 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 176 |
+
if history:
|
| 177 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 178 |
+
if isinstance(history[0], list):
|
| 179 |
+
# Convert old format temporarily if encountered
|
| 180 |
+
for q, a in history:
|
| 181 |
+
message.append({"role": "user", "content": str(q)})
|
| 182 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 183 |
+
elif isinstance(history[0], dict):
|
| 184 |
+
# New format
|
| 185 |
+
for msg in history:
|
| 186 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 187 |
+
message.append(msg)
|
| 188 |
+
|
| 189 |
+
# Add the current prompt
|
| 190 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 191 |
+
|
| 192 |
+
if not api_keys:
|
| 193 |
+
return "Error: No API Keys available."
|
| 194 |
+
|
| 195 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 196 |
+
|
| 197 |
+
# New OpenAI 1.x Syntax
|
| 198 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 199 |
+
|
| 200 |
+
except Exception as e:
|
| 201 |
+
print(f"Chat Error: {e}")
|
| 202 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 203 |
+
deactivated_keys.append(api_keys[api_index])
|
| 204 |
+
|
| 205 |
+
if api_keys:
|
| 206 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 207 |
+
loop_check = 0
|
| 208 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 209 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 210 |
+
loop_check += 1
|
| 211 |
+
count += 1
|
| 212 |
+
|
| 213 |
+
if response:
|
| 214 |
+
response = response.choices[0].message.content
|
| 215 |
+
else:
|
| 216 |
+
response = ''
|
| 217 |
+
return response
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def classify_query_local(text):
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 224 |
+
id2label_map = {
|
| 225 |
+
0: "episodic_memory",
|
| 226 |
+
1: "semantic_memory",
|
| 227 |
+
2: "semantic-episodic",
|
| 228 |
+
3: "unknown"
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
try:
|
| 232 |
+
|
| 233 |
+
inputs = _tokenizer(
|
| 234 |
+
text,
|
| 235 |
+
return_tensors="pt",
|
| 236 |
+
truncation=True,
|
| 237 |
+
padding=True,
|
| 238 |
+
max_length=512
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
with torch.no_grad():
|
| 244 |
+
outputs = _classifier_model(**inputs)
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
logits = outputs.logits
|
| 248 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 249 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 253 |
+
|
| 254 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 255 |
+
return category
|
| 256 |
+
|
| 257 |
+
except Exception as e:
|
| 258 |
+
print(f"Error in local classification: {e}")
|
| 259 |
+
return "unknown"
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 264 |
+
response = None
|
| 265 |
+
count = 0
|
| 266 |
+
local_deactivated = []
|
| 267 |
+
print("text********:", text)
|
| 268 |
+
|
| 269 |
+
system_prompt = """
|
| 270 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 271 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 272 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 273 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 274 |
+
|
| 275 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 276 |
+
""".strip()
|
| 277 |
+
|
| 278 |
+
if not api_keys:
|
| 279 |
+
return "unknown"
|
| 280 |
+
|
| 281 |
+
while response is None and count < retry_times:
|
| 282 |
+
try:
|
| 283 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 284 |
+
|
| 285 |
+
# New OpenAI 1.x Syntax
|
| 286 |
+
response = client.chat.completions.create(
|
| 287 |
+
messages=[
|
| 288 |
+
{"role": "system", "content": system_prompt},
|
| 289 |
+
{"role": "user", "content": text.strip()},
|
| 290 |
+
],
|
| 291 |
+
**copy.deepcopy(gpt_config),
|
| 292 |
+
)
|
| 293 |
+
except Exception as e:
|
| 294 |
+
print(f"Classify Error: {e}")
|
| 295 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 296 |
+
local_deactivated.append(api_keys[api_index])
|
| 297 |
+
|
| 298 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 299 |
+
while api_keys[api_index] in local_deactivated:
|
| 300 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 301 |
+
count += 1
|
| 302 |
+
|
| 303 |
+
if response:
|
| 304 |
+
category = response.choices[0].message.content.strip().lower()
|
| 305 |
+
# Basic cleanup
|
| 306 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 307 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 308 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 309 |
+
else: category = "unknown"
|
| 310 |
+
else:
|
| 311 |
+
category = "unknown"
|
| 312 |
+
|
| 313 |
+
return category
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def predict_new(
|
| 317 |
+
text,
|
| 318 |
+
history,
|
| 319 |
+
top_p,
|
| 320 |
+
temperature,
|
| 321 |
+
max_length_tokens,
|
| 322 |
+
max_context_length_tokens,
|
| 323 |
+
user_name,
|
| 324 |
+
user_memory,
|
| 325 |
+
user_memory_index,
|
| 326 |
+
service_context,
|
| 327 |
+
api_index,
|
| 328 |
+
semantic_memory_text,
|
| 329 |
+
query_category,
|
| 330 |
+
):
|
| 331 |
+
chatgpt_cfg = {
|
| 332 |
+
"model": "gpt-4o",
|
| 333 |
+
"temperature": temperature,
|
| 334 |
+
"max_tokens": max_length_tokens,
|
| 335 |
+
"top_p": top_p,
|
| 336 |
+
"frequency_penalty": 0.4,
|
| 337 |
+
"presence_penalty": 0.2,
|
| 338 |
+
"n": 1,
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
if text == "":
|
| 342 |
+
# Return same history if empty input
|
| 343 |
+
return history, history, "Empty context."
|
| 344 |
+
|
| 345 |
+
# Ensure history is initialized
|
| 346 |
+
if history is None:
|
| 347 |
+
history = []
|
| 348 |
+
|
| 349 |
+
system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
|
| 350 |
+
history=history,
|
| 351 |
+
query=text, # Changed name to match prompt_utils
|
| 352 |
+
user_memory=user_memory,
|
| 353 |
+
user_name=user_name,
|
| 354 |
+
user_memory_index=user_memory_index,
|
| 355 |
+
service_context=service_context,
|
| 356 |
+
api_keys=api_keys,
|
| 357 |
+
api_index=api_index,
|
| 358 |
+
meta_prompt=meta_prompt,
|
| 359 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 360 |
+
data_args=data_args,
|
| 361 |
+
boot_actual_name=boot_actual_name,
|
| 362 |
+
semantic_memory_text=semantic_memory_text,
|
| 363 |
+
query_category=query_category,
|
| 364 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 365 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# Handle context window slicing manually if needed,
|
| 369 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 370 |
+
current_history_for_llm = history
|
| 371 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 372 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 373 |
+
|
| 374 |
+
response = chatgpt_chat(
|
| 375 |
+
prompt=text,
|
| 376 |
+
system=system_prompt,
|
| 377 |
+
history=current_history_for_llm,
|
| 378 |
+
gpt_config=chatgpt_cfg,
|
| 379 |
+
api_index=api_index,
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
torch.cuda.empty_cache()
|
| 383 |
+
|
| 384 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 385 |
+
new_history = history + [
|
| 386 |
+
{"role": "user", "content": text},
|
| 387 |
+
{"role": "assistant", "content": response}
|
| 388 |
+
]
|
| 389 |
+
|
| 390 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 391 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 392 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 393 |
+
if user_name:
|
| 394 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 395 |
+
# or pass a converted version. Let's try passing the new format.
|
| 396 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 397 |
+
|
| 398 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 399 |
+
return new_history, new_history, "Generating..."
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
import gradio as gr
|
| 403 |
+
import time
|
| 404 |
+
|
| 405 |
+
def create_gradio_interface(service_context, api_keys):
|
| 406 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 407 |
+
|
| 408 |
+
gr.HTML("""
|
| 409 |
+
<style>
|
| 410 |
+
.center-content {
|
| 411 |
+
display: flex;
|
| 412 |
+
flex-direction: column;
|
| 413 |
+
align-items: center;
|
| 414 |
+
justify-content: center;
|
| 415 |
+
}
|
| 416 |
+
/* -- استایلهای فرم ورود -- */
|
| 417 |
+
.login-box {
|
| 418 |
+
max-width: 400px !important;
|
| 419 |
+
margin: 0 auto !important;
|
| 420 |
+
width: 100% !important;
|
| 421 |
+
}
|
| 422 |
+
.login-btn, .login-btn:hover {
|
| 423 |
+
background-color: #3498db !important;
|
| 424 |
+
background-image: none !important;
|
| 425 |
+
color: white !important;
|
| 426 |
+
border: none !important;
|
| 427 |
+
}
|
| 428 |
+
/* -- استایلهای محیط چت -- */
|
| 429 |
+
.chat-box {
|
| 430 |
+
max-width: 800px !important;
|
| 431 |
+
margin: 0 auto !important;
|
| 432 |
+
width: 100% !important;
|
| 433 |
+
}
|
| 434 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 435 |
+
.mobile-button, .mobile-button:hover {
|
| 436 |
+
background-color: #3498db !important;
|
| 437 |
+
background-image: none !important;
|
| 438 |
+
color: white !important;
|
| 439 |
+
border: none !important;
|
| 440 |
+
}
|
| 441 |
+
.gr-textbox textarea {
|
| 442 |
+
font-size: 16px;
|
| 443 |
+
}
|
| 444 |
+
.gr-chatbot {
|
| 445 |
+
font-size: 15px;
|
| 446 |
+
}
|
| 447 |
+
</style>
|
| 448 |
+
""")
|
| 449 |
+
|
| 450 |
+
state = gr.State({
|
| 451 |
+
"history": [],
|
| 452 |
+
"user_name": None,
|
| 453 |
+
"memory": memory,
|
| 454 |
+
"data_args": data_args,
|
| 455 |
+
"service_context": service_context,
|
| 456 |
+
"api_keys": api_keys,
|
| 457 |
+
"api_index": 0,
|
| 458 |
+
"semantic_memory_text": "",
|
| 459 |
+
"new_conversation": True,
|
| 460 |
+
"initialized": False
|
| 461 |
+
})
|
| 462 |
+
|
| 463 |
+
# ==========================================
|
| 464 |
+
# 1. LOGIN PAGE
|
| 465 |
+
# ==========================================
|
| 466 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 467 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 468 |
+
|
| 469 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 470 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 471 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 472 |
+
|
| 473 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 474 |
+
|
| 475 |
+
with gr.Column(visible=False) as registration_fields:
|
| 476 |
+
gr.Markdown("### ✨ New User Registration")
|
| 477 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 478 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 479 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 480 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 481 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 482 |
+
|
| 483 |
+
# ==========================================
|
| 484 |
+
# 2. CHAT PAGE
|
| 485 |
+
# ==========================================
|
| 486 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 487 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 488 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 489 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 490 |
+
|
| 491 |
+
with gr.Group():
|
| 492 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 493 |
+
|
| 494 |
+
with gr.Row():
|
| 495 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 496 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 497 |
+
|
| 498 |
+
with gr.Row(equal_height=True):
|
| 499 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 500 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 501 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 502 |
+
|
| 503 |
+
# -------------------------------------------------------
|
| 504 |
+
# Internal Functions (کامل شده)
|
| 505 |
+
# -------------------------------------------------------
|
| 506 |
+
def handle_login_check(name, state):
|
| 507 |
+
if not name.strip():
|
| 508 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 509 |
+
|
| 510 |
+
if name in memory:
|
| 511 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 512 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 513 |
+
|
| 514 |
+
new_state = state.copy()
|
| 515 |
+
new_state["user_name"] = name
|
| 516 |
+
new_state["memory"] = memory
|
| 517 |
+
new_state["initialized"] = True
|
| 518 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 519 |
+
new_state["history"] = []
|
| 520 |
+
|
| 521 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 522 |
+
|
| 523 |
+
return (
|
| 524 |
+
gr.update(visible=False),
|
| 525 |
+
gr.update(visible=False),
|
| 526 |
+
gr.update(visible=True),
|
| 527 |
+
gr.update(visible=False, value=""),
|
| 528 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 529 |
+
gr.update(value=welcome_msg),
|
| 530 |
+
new_state
|
| 531 |
+
)
|
| 532 |
+
else:
|
| 533 |
+
return (
|
| 534 |
+
gr.update(visible=True),
|
| 535 |
+
gr.update(visible=True),
|
| 536 |
+
gr.update(visible=False),
|
| 537 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 538 |
+
gr.update(),
|
| 539 |
+
gr.update(),
|
| 540 |
+
state
|
| 541 |
+
)
|
| 542 |
+
|
| 543 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 544 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 545 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 546 |
+
|
| 547 |
+
new_state = state.copy()
|
| 548 |
+
new_state["user_name"] = name
|
| 549 |
+
new_state["memory"] = memory
|
| 550 |
+
new_state["initialized"] = True
|
| 551 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 552 |
+
new_state["history"] = []
|
| 553 |
+
|
| 554 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 555 |
+
|
| 556 |
+
return (
|
| 557 |
+
gr.update(visible=False),
|
| 558 |
+
gr.update(visible=False),
|
| 559 |
+
gr.update(visible=True),
|
| 560 |
+
gr.update(visible=False, value=""),
|
| 561 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 562 |
+
gr.update(value=welcome_msg),
|
| 563 |
+
new_state
|
| 564 |
+
)
|
| 565 |
+
|
| 566 |
+
def switch_user(state):
|
| 567 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 568 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 569 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 570 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 571 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 572 |
+
|
| 573 |
+
new_state = state.copy()
|
| 574 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 575 |
+
|
| 576 |
+
return (
|
| 577 |
+
gr.update(visible=True),
|
| 578 |
+
gr.update(visible=False),
|
| 579 |
+
gr.update(visible=False),
|
| 580 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 581 |
+
gr.update(value=""),
|
| 582 |
+
new_state,
|
| 583 |
+
gr.update(value=[])
|
| 584 |
+
)
|
| 585 |
+
|
| 586 |
+
def handle_chat(user_message, state):
|
| 587 |
+
if not user_message.strip():
|
| 588 |
+
return gr.update(), state.get("history", []), state
|
| 589 |
+
|
| 590 |
+
user_name = state.get("user_name")
|
| 591 |
+
user_memory = state.get("memory")
|
| 592 |
+
service_context = state.get("service_context")
|
| 593 |
+
api_index = state.get("api_index", 0)
|
| 594 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 595 |
+
|
| 596 |
+
# دستهبندی پرامپت با تابعی که در کدهای شما وجود دارد
|
| 597 |
+
query_category = classify_query_local(user_message)
|
| 598 |
+
|
| 599 |
+
# ارسال به تابع predict_new شما
|
| 600 |
+
new_history, _, status_msg = predict_new(
|
| 601 |
+
text=user_message,
|
| 602 |
+
history=state.get("history", []),
|
| 603 |
+
top_p=0.95,
|
| 604 |
+
temperature=1.0,
|
| 605 |
+
max_length_tokens=1024,
|
| 606 |
+
max_context_length_tokens=4096,
|
| 607 |
+
user_name=user_name,
|
| 608 |
+
user_memory=user_memory,
|
| 609 |
+
user_memory_index=None,
|
| 610 |
+
service_context=service_context,
|
| 611 |
+
api_index=api_index,
|
| 612 |
+
semantic_memory_text=semantic_memory_text,
|
| 613 |
+
query_category=query_category
|
| 614 |
+
)
|
| 615 |
+
|
| 616 |
+
state["history"] = new_history
|
| 617 |
+
return "", new_history, state
|
| 618 |
+
|
| 619 |
+
def clear_history(state):
|
| 620 |
+
state["history"] = []
|
| 621 |
+
return [], state
|
| 622 |
+
|
| 623 |
+
# -------------------------------------------------------
|
| 624 |
+
# Event Bindings (اتصال دکمهها به توابع)
|
| 625 |
+
# -------------------------------------------------------
|
| 626 |
+
check_user_btn.click(
|
| 627 |
+
handle_login_check,
|
| 628 |
+
inputs=[username_input, state],
|
| 629 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 630 |
+
)
|
| 631 |
+
|
| 632 |
+
register_btn.click(
|
| 633 |
+
handle_register,
|
| 634 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 635 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 636 |
+
)
|
| 637 |
+
|
| 638 |
+
switch_user_btn.click(
|
| 639 |
+
switch_user,
|
| 640 |
+
inputs=[state],
|
| 641 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 642 |
+
)
|
| 643 |
+
|
| 644 |
+
submit_btn.click(
|
| 645 |
+
handle_chat,
|
| 646 |
+
inputs=[user_input, state],
|
| 647 |
+
outputs=[user_input, chatbot, state]
|
| 648 |
+
)
|
| 649 |
+
|
| 650 |
+
user_input.submit(
|
| 651 |
+
handle_chat,
|
| 652 |
+
inputs=[user_input, state],
|
| 653 |
+
outputs=[user_input, chatbot, state]
|
| 654 |
+
)
|
| 655 |
+
|
| 656 |
+
clear_btn.click(
|
| 657 |
+
clear_history,
|
| 658 |
+
inputs=[state],
|
| 659 |
+
outputs=[chatbot, state]
|
| 660 |
+
)
|
| 661 |
+
|
| 662 |
+
new_session_btn.click(
|
| 663 |
+
clear_history,
|
| 664 |
+
inputs=[state],
|
| 665 |
+
outputs=[chatbot, state]
|
| 666 |
+
)
|
| 667 |
+
|
| 668 |
+
return demo
|
| 669 |
+
|
| 670 |
+
def main():
|
| 671 |
+
"""Main function to initialize and launch the interface."""
|
| 672 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 673 |
+
|
| 674 |
+
if not gapgpt_api_key:
|
| 675 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 676 |
+
else:
|
| 677 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 678 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 679 |
+
|
| 680 |
+
# تنظیم LLM (مدل زبانی)
|
| 681 |
+
llm = LlamaIndexOpenAI(
|
| 682 |
+
model="gpt-4o",
|
| 683 |
+
temperature=1,
|
| 684 |
+
max_tokens=1024,
|
| 685 |
+
top_p=0.95,
|
| 686 |
+
frequency_penalty=0.4,
|
| 687 |
+
presence_penalty=0.2,
|
| 688 |
+
api_key=gapgpt_api_key,
|
| 689 |
+
api_base=GAPGPT_BASE_URL,
|
| 690 |
+
)
|
| 691 |
+
|
| 692 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 693 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 694 |
+
embed_model = OpenAIEmbedding(
|
| 695 |
+
api_key=gapgpt_api_key,
|
| 696 |
+
api_base=GAPGPT_BASE_URL,
|
| 697 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 698 |
+
)
|
| 699 |
+
|
| 700 |
+
# اعمال تنظیمات سراسری
|
| 701 |
+
Settings.llm = llm
|
| 702 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 703 |
+
|
| 704 |
+
Settings.prompt_helper = PromptHelper(
|
| 705 |
+
context_window=4096,
|
| 706 |
+
num_output=256,
|
| 707 |
+
chunk_overlap_ratio=20 / 4096,
|
| 708 |
+
tokenizer=tokenizer,
|
| 709 |
+
)
|
| 710 |
+
|
| 711 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 712 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 713 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 714 |
+
if 'api_keys' not in locals():
|
| 715 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 716 |
+
|
| 717 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 718 |
+
demo.launch(
|
| 719 |
+
server_name="127.0.0.1",
|
| 720 |
+
server_port=7860,
|
| 721 |
+
share=True
|
| 722 |
+
)
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
if __name__ == "__main__":
|
| 726 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 727 |
+
main()
|
Backup code/app_V11.py
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
):
|
| 334 |
+
chatgpt_cfg = {
|
| 335 |
+
"model": "gpt-4o",
|
| 336 |
+
"temperature": temperature,
|
| 337 |
+
"max_tokens": max_length_tokens,
|
| 338 |
+
"top_p": top_p,
|
| 339 |
+
"frequency_penalty": 0.4,
|
| 340 |
+
"presence_penalty": 0.2,
|
| 341 |
+
"n": 1,
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
if text == "":
|
| 345 |
+
# Return same history if empty input
|
| 346 |
+
return history, history, "Empty context."
|
| 347 |
+
|
| 348 |
+
# Ensure history is initialized
|
| 349 |
+
if history is None:
|
| 350 |
+
history = []
|
| 351 |
+
|
| 352 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 353 |
+
history=history,
|
| 354 |
+
query=text, # Changed name to match prompt_utils
|
| 355 |
+
user_memory=user_memory,
|
| 356 |
+
user_name=user_name,
|
| 357 |
+
user_memory_index=user_memory_index,
|
| 358 |
+
service_context=service_context,
|
| 359 |
+
api_keys=api_keys,
|
| 360 |
+
api_index=api_index,
|
| 361 |
+
meta_prompt=meta_prompt,
|
| 362 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 363 |
+
data_args=data_args,
|
| 364 |
+
boot_actual_name=boot_actual_name,
|
| 365 |
+
semantic_memory_text=semantic_memory_text,
|
| 366 |
+
query_category=query_category,
|
| 367 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 368 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
# Handle context window slicing manually if needed,
|
| 372 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 373 |
+
current_history_for_llm = history
|
| 374 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 375 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 376 |
+
|
| 377 |
+
response = chatgpt_chat(
|
| 378 |
+
prompt=text,
|
| 379 |
+
system=system_prompt,
|
| 380 |
+
history=current_history_for_llm,
|
| 381 |
+
gpt_config=chatgpt_cfg,
|
| 382 |
+
api_index=api_index,
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
torch.cuda.empty_cache()
|
| 386 |
+
|
| 387 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 388 |
+
new_history = history + [
|
| 389 |
+
{"role": "user", "content": text},
|
| 390 |
+
{"role": "assistant", "content": response}
|
| 391 |
+
]
|
| 392 |
+
|
| 393 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 394 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 395 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 396 |
+
if user_name:
|
| 397 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 398 |
+
# or pass a converted version. Let's try passing the new format.
|
| 399 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 400 |
+
|
| 401 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 402 |
+
return new_history, new_history, "Generating..."
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
def create_gradio_interface(service_context, api_keys):
|
| 407 |
+
|
| 408 |
+
|
| 409 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 410 |
+
custom_css = """
|
| 411 |
+
/* استایل دکمه ارسال (Send) */
|
| 412 |
+
.send-btn {
|
| 413 |
+
border: 3px solid #0066cc !important;
|
| 414 |
+
border-radius: 12px !important;
|
| 415 |
+
background-color: white !important;
|
| 416 |
+
color: black !important;
|
| 417 |
+
font-weight: bold !important;
|
| 418 |
+
font-size: 16px !important;
|
| 419 |
+
transition: all 0.3s ease !important;
|
| 420 |
+
}
|
| 421 |
+
.send-btn:hover {
|
| 422 |
+
background-color: #0066cc !important;
|
| 423 |
+
color: white !important;
|
| 424 |
+
}
|
| 425 |
+
|
| 426 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 427 |
+
.bottom-actions-row {
|
| 428 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 429 |
+
border-radius: 8px !important;
|
| 430 |
+
padding: 5px !important;
|
| 431 |
+
margin-top: 10px !important;
|
| 432 |
+
}
|
| 433 |
+
|
| 434 |
+
.action-btn {
|
| 435 |
+
border: none !important;
|
| 436 |
+
background: transparent !important;
|
| 437 |
+
color: black !important;
|
| 438 |
+
font-weight: bold !important;
|
| 439 |
+
box-shadow: none !important;
|
| 440 |
+
transition: all 0.3s ease !important;
|
| 441 |
+
}
|
| 442 |
+
|
| 443 |
+
.action-btn:hover {
|
| 444 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
}
|
| 447 |
+
/* مخفی کردن آیکون/مربع نارنجی پیشفرض Gradio */
|
| 448 |
+
.progress-level svg, .progress-level img {
|
| 449 |
+
display: none !important;
|
| 450 |
+
}
|
| 451 |
+
|
| 452 |
+
/* ایجاد یک دایره چرخان (Spinner) استاندارد */
|
| 453 |
+
.progress-level::before {
|
| 454 |
+
content: "";
|
| 455 |
+
display: inline-block;
|
| 456 |
+
width: 20px;
|
| 457 |
+
height: 20px;
|
| 458 |
+
border: 3px solid #e5e7eb; /* رنگ پسزمینه دایره */
|
| 459 |
+
border-radius: 50%;
|
| 460 |
+
border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
|
| 461 |
+
animation: spin 1s linear infinite;
|
| 462 |
+
margin-right: 8px;
|
| 463 |
+
vertical-align: middle;
|
| 464 |
+
}
|
| 465 |
+
|
| 466 |
+
/* انیمیشن چرخش */
|
| 467 |
+
@keyframes spin {
|
| 468 |
+
0% { transform: rotate(0deg); }
|
| 469 |
+
100% { transform: rotate(360deg); }
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 473 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 474 |
+
/*
|
| 475 |
+
.progress-text {
|
| 476 |
+
display: none !important;
|
| 477 |
+
}
|
| 478 |
+
*/
|
| 479 |
+
|
| 480 |
+
"""
|
| 481 |
+
|
| 482 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 483 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 484 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 485 |
+
|
| 486 |
+
# بقیه کدهای شما...
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
state = gr.State({
|
| 490 |
+
"history": [],
|
| 491 |
+
"user_name": None,
|
| 492 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 493 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 494 |
+
"service_context": service_context,
|
| 495 |
+
"api_keys": api_keys,
|
| 496 |
+
"api_index": 0,
|
| 497 |
+
"semantic_memory_text": "",
|
| 498 |
+
"new_conversation": True,
|
| 499 |
+
"initialized": False
|
| 500 |
+
})
|
| 501 |
+
|
| 502 |
+
|
| 503 |
+
|
| 504 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 505 |
+
with gr.Row():
|
| 506 |
+
|
| 507 |
+
# ==========================================
|
| 508 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 509 |
+
# ==========================================
|
| 510 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 511 |
+
with gr.Sidebar(open=True) as login_page:
|
| 512 |
+
|
| 513 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 514 |
+
|
| 515 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 516 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 517 |
+
|
| 518 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 519 |
+
|
| 520 |
+
with gr.Column(visible=False) as registration_fields:
|
| 521 |
+
gr.Markdown("### ✨ New User Registration")
|
| 522 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 523 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 524 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 525 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 526 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 527 |
+
|
| 528 |
+
|
| 529 |
+
# ==========================================
|
| 530 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 531 |
+
# ==========================================
|
| 532 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 533 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 534 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 535 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 536 |
+
|
| 537 |
+
with gr.Group():
|
| 538 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 539 |
+
|
| 540 |
+
with gr.Row():
|
| 541 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 542 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 543 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 544 |
+
|
| 545 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 546 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 547 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 548 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 549 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 550 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 551 |
+
|
| 552 |
+
# -------------------------------------------------------
|
| 553 |
+
# Internal Functions
|
| 554 |
+
# -------------------------------------------------------
|
| 555 |
+
def handle_login_check(name, state):
|
| 556 |
+
if not name.strip():
|
| 557 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 558 |
+
|
| 559 |
+
if name in memory:
|
| 560 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 561 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 562 |
+
|
| 563 |
+
new_state = state.copy()
|
| 564 |
+
new_state["user_name"] = name
|
| 565 |
+
new_state["memory"] = memory
|
| 566 |
+
new_state["initialized"] = True
|
| 567 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 568 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 569 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 570 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 571 |
+
new_state["history"] = []
|
| 572 |
+
|
| 573 |
+
|
| 574 |
+
|
| 575 |
+
|
| 576 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 577 |
+
|
| 578 |
+
return (
|
| 579 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 580 |
+
gr.update(visible=False),
|
| 581 |
+
gr.update(visible=True),
|
| 582 |
+
gr.update(visible=False, value=""),
|
| 583 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 584 |
+
gr.update(value=welcome_msg),
|
| 585 |
+
new_state
|
| 586 |
+
)
|
| 587 |
+
else:
|
| 588 |
+
return (
|
| 589 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 590 |
+
gr.update(visible=True),
|
| 591 |
+
gr.update(visible=False),
|
| 592 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 593 |
+
gr.update(),
|
| 594 |
+
gr.update(),
|
| 595 |
+
state
|
| 596 |
+
)
|
| 597 |
+
|
| 598 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 599 |
+
name = str(name).strip()
|
| 600 |
+
|
| 601 |
+
if not name:
|
| 602 |
+
raise gr.Error("Please enter a valid user name.")
|
| 603 |
+
|
| 604 |
+
# Registration is only for new users.
|
| 605 |
+
if name in memory:
|
| 606 |
+
raise gr.Error(
|
| 607 |
+
f"User '{name}' already exists. Please use the login form."
|
| 608 |
+
)
|
| 609 |
+
|
| 610 |
+
# Create the user before trying to build or load their indices.
|
| 611 |
+
memory[name] = {
|
| 612 |
+
"profile": {
|
| 613 |
+
"age": age,
|
| 614 |
+
"gender": gender,
|
| 615 |
+
"occupation": occupation,
|
| 616 |
+
"residence": residence,
|
| 617 |
+
},
|
| 618 |
+
"sessions": [],
|
| 619 |
+
"episodic_memory": [],
|
| 620 |
+
"semantic_memory": {},
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
try:
|
| 624 |
+
(
|
| 625 |
+
_,
|
| 626 |
+
user_memory,
|
| 627 |
+
sessions_memory,
|
| 628 |
+
episodic_memory,
|
| 629 |
+
semantic_memory,
|
| 630 |
+
) = enter_name_llamaindex(
|
| 631 |
+
name=name,
|
| 632 |
+
memory=memory,
|
| 633 |
+
data_args=data_args,
|
| 634 |
+
update_memory_index=True,
|
| 635 |
+
)
|
| 636 |
+
except Exception:
|
| 637 |
+
# Avoid leaving a partially registered user in memory.
|
| 638 |
+
memory.pop(name, None)
|
| 639 |
+
raise
|
| 640 |
+
|
| 641 |
+
new_state = dict(state or {})
|
| 642 |
+
new_state.update(
|
| 643 |
+
{
|
| 644 |
+
"user_name": name,
|
| 645 |
+
"memory": memory,
|
| 646 |
+
"initialized": True,
|
| 647 |
+
"history": [],
|
| 648 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 649 |
+
"user_memory_index": sessions_memory,
|
| 650 |
+
"episodic_memory_index": episodic_memory,
|
| 651 |
+
"semantic_memory_index": semantic_memory,
|
| 652 |
+
}
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 656 |
+
|
| 657 |
+
return (
|
| 658 |
+
gr.update(open=False),
|
| 659 |
+
gr.update(visible=False),
|
| 660 |
+
gr.update(visible=True),
|
| 661 |
+
gr.update(visible=False, value=""),
|
| 662 |
+
gr.update(
|
| 663 |
+
value=(
|
| 664 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 665 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 666 |
+
)
|
| 667 |
+
),
|
| 668 |
+
gr.update(value=welcome_msg),
|
| 669 |
+
new_state,
|
| 670 |
+
)
|
| 671 |
+
|
| 672 |
+
def switch_user(state):
|
| 673 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 674 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 675 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 676 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 677 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 678 |
+
# ==========================================
|
| 679 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 680 |
+
# ==========================================
|
| 681 |
+
try:
|
| 682 |
+
user_mem = state["memory"][state["user_name"]]
|
| 683 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 684 |
+
|
| 685 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 686 |
+
|
| 687 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 688 |
+
except Exception as e:
|
| 689 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 690 |
+
# ==========================================
|
| 691 |
+
|
| 692 |
+
new_state = state.copy()
|
| 693 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 694 |
+
|
| 695 |
+
|
| 696 |
+
return (
|
| 697 |
+
gr.update(open=True), # 1. باز شدن سایدبار (login_page)
|
| 698 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام (registration_fields)
|
| 699 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 700 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 701 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 702 |
+
new_state, # 6. استیت جدید
|
| 703 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 704 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 705 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 706 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 707 |
+
gr.update(value="") # 11. پاک کردن residence_input
|
| 708 |
+
)
|
| 709 |
+
|
| 710 |
+
def handle_chat(user_message, state):
|
| 711 |
+
if not user_message.strip():
|
| 712 |
+
print("[handle_chat] empty message")
|
| 713 |
+
print("[handle_chat] state =", state)
|
| 714 |
+
return gr.update(), state.get("history", []), state
|
| 715 |
+
|
| 716 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 717 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 718 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 719 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 720 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 721 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 722 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 723 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 724 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 725 |
+
|
| 726 |
+
user_name = state.get("user_name")
|
| 727 |
+
user_memory_index = state.get("user_memory_index")
|
| 728 |
+
user_memory = state.get("user_memory", {})
|
| 729 |
+
user_memory_index = state.get("user_memory_index")
|
| 730 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 731 |
+
service_context = state.get("service_context")
|
| 732 |
+
api_index = state.get("api_index", 0)
|
| 733 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 734 |
+
|
| 735 |
+
query_category = classify_query_local(user_message)
|
| 736 |
+
print("[handle_chat] query_category =", query_category)
|
| 737 |
+
|
| 738 |
+
new_history, _, status_msg = predict_new(
|
| 739 |
+
text=user_message,
|
| 740 |
+
history=state.get("history", []),
|
| 741 |
+
top_p=0.95,
|
| 742 |
+
temperature=1.0,
|
| 743 |
+
max_length_tokens=1024,
|
| 744 |
+
max_context_length_tokens=4096,
|
| 745 |
+
user_name=user_name,
|
| 746 |
+
user_memory=user_memory,
|
| 747 |
+
user_memory_index=user_memory_index,
|
| 748 |
+
service_context=service_context,
|
| 749 |
+
api_index=api_index,
|
| 750 |
+
semantic_memory_text=semantic_memory_text,
|
| 751 |
+
query_category=query_category,
|
| 752 |
+
|
| 753 |
+
)
|
| 754 |
+
|
| 755 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 756 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 757 |
+
|
| 758 |
+
state["history"] = new_history
|
| 759 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 760 |
+
|
| 761 |
+
return "", new_history, state
|
| 762 |
+
|
| 763 |
+
def clear_history(state):
|
| 764 |
+
state["history"] = []
|
| 765 |
+
return [], state
|
| 766 |
+
|
| 767 |
+
def handle_new_session(state):
|
| 768 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 769 |
+
user_name = state.get("user_name")
|
| 770 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 771 |
+
print("Error: User not logged in or memory missing.")
|
| 772 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 773 |
+
return [], state
|
| 774 |
+
|
| 775 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 776 |
+
user_data = state["memory"][user_name]
|
| 777 |
+
|
| 778 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 779 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 780 |
+
last_session = user_data["sessions"][-1]
|
| 781 |
+
|
| 782 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 783 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 784 |
+
session_date = last_session.get("date", "")
|
| 785 |
+
session_id = last_session.get("session_id", 0)
|
| 786 |
+
|
| 787 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 788 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 789 |
+
|
| 790 |
+
if "episodic_memory" not in user_data:
|
| 791 |
+
user_data["episodic_memory"] = []
|
| 792 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 793 |
+
|
| 794 |
+
# ==========================================
|
| 795 |
+
# بهروزرسانی حافظه سمانتیک
|
| 796 |
+
# ==========================================
|
| 797 |
+
try:
|
| 798 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 799 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 800 |
+
|
| 801 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 802 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 803 |
+
|
| 804 |
+
# ذخیره دیتای جدید
|
| 805 |
+
user_data["semantic_memory"] = updated_semantic
|
| 806 |
+
except Exception as e:
|
| 807 |
+
print(f"Error updating semantic memory: {e}")
|
| 808 |
+
# ==========================================
|
| 809 |
+
|
| 810 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 811 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 812 |
+
|
| 813 |
+
new_session = {
|
| 814 |
+
"session_id": new_session_id,
|
| 815 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 816 |
+
"conversation": []
|
| 817 |
+
}
|
| 818 |
+
|
| 819 |
+
if "sessions" not in user_data:
|
| 820 |
+
user_data["sessions"] = []
|
| 821 |
+
|
| 822 |
+
user_data["sessions"].append(new_session)
|
| 823 |
+
|
| 824 |
+
# پاک کردن تاریخچه چت در state
|
| 825 |
+
state["history"] = []
|
| 826 |
+
|
| 827 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 828 |
+
return [], state
|
| 829 |
+
|
| 830 |
+
check_user_btn.click(
|
| 831 |
+
handle_login_check,
|
| 832 |
+
inputs=[username_input, state],
|
| 833 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 834 |
+
show_progress="hidden"
|
| 835 |
+
)
|
| 836 |
+
|
| 837 |
+
register_btn.click(
|
| 838 |
+
handle_register,
|
| 839 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 840 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 841 |
+
show_progress="hidden"
|
| 842 |
+
)
|
| 843 |
+
|
| 844 |
+
switch_user_btn.click(
|
| 845 |
+
switch_user,
|
| 846 |
+
inputs=[state],
|
| 847 |
+
# اضافه کردن فیلدهای ثبتنام به خروجیها
|
| 848 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input],
|
| 849 |
+
show_progress="hidden"
|
| 850 |
+
)
|
| 851 |
+
|
| 852 |
+
|
| 853 |
+
submit_btn.click(
|
| 854 |
+
handle_chat,
|
| 855 |
+
inputs=[user_input, state],
|
| 856 |
+
outputs=[user_input, chatbot, state],
|
| 857 |
+
show_progress="hidden"
|
| 858 |
+
)
|
| 859 |
+
|
| 860 |
+
user_input.submit(
|
| 861 |
+
handle_chat,
|
| 862 |
+
inputs=[user_input, state],
|
| 863 |
+
outputs=[user_input, chatbot, state],
|
| 864 |
+
show_progress="hidden"
|
| 865 |
+
)
|
| 866 |
+
|
| 867 |
+
clear_btn.click(
|
| 868 |
+
clear_history,
|
| 869 |
+
inputs=[state],
|
| 870 |
+
outputs=[chatbot, state],
|
| 871 |
+
show_progress="hidden"
|
| 872 |
+
)
|
| 873 |
+
|
| 874 |
+
# تغییر از clear_history به handle_new_session
|
| 875 |
+
new_session_btn.click(
|
| 876 |
+
handle_new_session,
|
| 877 |
+
inputs=[state],
|
| 878 |
+
outputs=[chatbot, state],
|
| 879 |
+
show_progress="hidden"
|
| 880 |
+
|
| 881 |
+
|
| 882 |
+
)
|
| 883 |
+
|
| 884 |
+
return demo
|
| 885 |
+
|
| 886 |
+
|
| 887 |
+
def main():
|
| 888 |
+
"""Main function to initialize and launch the interface."""
|
| 889 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 890 |
+
|
| 891 |
+
if not gapgpt_api_key:
|
| 892 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 893 |
+
else:
|
| 894 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 895 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 896 |
+
|
| 897 |
+
# تنظیم LLM (مدل زبانی)
|
| 898 |
+
llm = LlamaIndexOpenAI(
|
| 899 |
+
model="gpt-4o",
|
| 900 |
+
temperature=1,
|
| 901 |
+
max_tokens=1024,
|
| 902 |
+
top_p=0.95,
|
| 903 |
+
frequency_penalty=0.4,
|
| 904 |
+
presence_penalty=0.2,
|
| 905 |
+
api_key=gapgpt_api_key,
|
| 906 |
+
api_base=GAPGPT_BASE_URL,
|
| 907 |
+
)
|
| 908 |
+
|
| 909 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 910 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 911 |
+
embed_model = OpenAIEmbedding(
|
| 912 |
+
api_key=gapgpt_api_key,
|
| 913 |
+
api_base=GAPGPT_BASE_URL,
|
| 914 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 915 |
+
)
|
| 916 |
+
|
| 917 |
+
# اعمال تنظیمات سراسری
|
| 918 |
+
Settings.llm = llm
|
| 919 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 920 |
+
|
| 921 |
+
Settings.prompt_helper = PromptHelper(
|
| 922 |
+
context_window=4096,
|
| 923 |
+
num_output=256,
|
| 924 |
+
chunk_overlap_ratio=20 / 4096,
|
| 925 |
+
tokenizer=tokenizer,
|
| 926 |
+
)
|
| 927 |
+
|
| 928 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 929 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 930 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 931 |
+
if 'api_keys' not in locals():
|
| 932 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 933 |
+
|
| 934 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 935 |
+
demo.launch(
|
| 936 |
+
server_name="127.0.0.1",
|
| 937 |
+
server_port=7860,
|
| 938 |
+
share=True
|
| 939 |
+
)
|
| 940 |
+
|
| 941 |
+
|
| 942 |
+
if __name__ == "__main__":
|
| 943 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 944 |
+
main()
|
Backup code/app_V12.py
ADDED
|
@@ -0,0 +1,964 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
user_profile=None
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
):
|
| 335 |
+
chatgpt_cfg = {
|
| 336 |
+
"model": "gpt-4o",
|
| 337 |
+
"temperature": temperature,
|
| 338 |
+
"max_tokens": max_length_tokens,
|
| 339 |
+
"top_p": top_p,
|
| 340 |
+
"frequency_penalty": 0.4,
|
| 341 |
+
"presence_penalty": 0.2,
|
| 342 |
+
"n": 1,
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
if text == "":
|
| 346 |
+
# Return same history if empty input
|
| 347 |
+
return history, history, "Empty context."
|
| 348 |
+
|
| 349 |
+
# Ensure history is initialized
|
| 350 |
+
if history is None:
|
| 351 |
+
history = []
|
| 352 |
+
|
| 353 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 354 |
+
history=history,
|
| 355 |
+
query=text, # Changed name to match prompt_utils
|
| 356 |
+
user_memory=user_memory,
|
| 357 |
+
user_name=user_name,
|
| 358 |
+
user_memory_index=user_memory_index,
|
| 359 |
+
service_context=service_context,
|
| 360 |
+
api_keys=api_keys,
|
| 361 |
+
api_index=api_index,
|
| 362 |
+
meta_prompt=meta_prompt,
|
| 363 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 364 |
+
data_args=data_args,
|
| 365 |
+
boot_actual_name=boot_actual_name,
|
| 366 |
+
semantic_memory_text=semantic_memory_text,
|
| 367 |
+
query_category=query_category,
|
| 368 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 369 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ==========================================
|
| 373 |
+
# اضافه کردن پروفایل به System Prompt
|
| 374 |
+
# ==========================================
|
| 375 |
+
if user_profile:
|
| 376 |
+
profile_str = (
|
| 377 |
+
f"\n\n[User Profile Information]:\n"
|
| 378 |
+
f"- Age: {user_profile.get('age', 'Unknown')}\n"
|
| 379 |
+
f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
|
| 380 |
+
f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
|
| 381 |
+
f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
|
| 382 |
+
f"Use this context subtly when talking to the user."
|
| 383 |
+
)
|
| 384 |
+
system_prompt += profile_str
|
| 385 |
+
# ==========================================
|
| 386 |
+
|
| 387 |
+
# Handle context window slicing manually if needed,
|
| 388 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 389 |
+
current_history_for_llm = history
|
| 390 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 391 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 392 |
+
|
| 393 |
+
response = chatgpt_chat(
|
| 394 |
+
prompt=text,
|
| 395 |
+
system=system_prompt,
|
| 396 |
+
history=current_history_for_llm,
|
| 397 |
+
gpt_config=chatgpt_cfg,
|
| 398 |
+
api_index=api_index,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
torch.cuda.empty_cache()
|
| 402 |
+
|
| 403 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 404 |
+
new_history = history + [
|
| 405 |
+
{"role": "user", "content": text},
|
| 406 |
+
{"role": "assistant", "content": response}
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 410 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 411 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 412 |
+
if user_name:
|
| 413 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 414 |
+
# or pass a converted version. Let's try passing the new format.
|
| 415 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 416 |
+
|
| 417 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 418 |
+
return new_history, new_history, "Generating..."
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
def create_gradio_interface(service_context, api_keys):
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 426 |
+
custom_css = """
|
| 427 |
+
/* استایل دکمه ارسال (Send) */
|
| 428 |
+
.send-btn {
|
| 429 |
+
border: 3px solid #0066cc !important;
|
| 430 |
+
border-radius: 12px !important;
|
| 431 |
+
background-color: white !important;
|
| 432 |
+
color: black !important;
|
| 433 |
+
font-weight: bold !important;
|
| 434 |
+
font-size: 16px !important;
|
| 435 |
+
transition: all 0.3s ease !important;
|
| 436 |
+
}
|
| 437 |
+
.send-btn:hover {
|
| 438 |
+
background-color: #0066cc !important;
|
| 439 |
+
color: white !important;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 443 |
+
.bottom-actions-row {
|
| 444 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
padding: 5px !important;
|
| 447 |
+
margin-top: 10px !important;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
.action-btn {
|
| 451 |
+
border: none !important;
|
| 452 |
+
background: transparent !important;
|
| 453 |
+
color: black !important;
|
| 454 |
+
font-weight: bold !important;
|
| 455 |
+
box-shadow: none !important;
|
| 456 |
+
transition: all 0.3s ease !important;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.action-btn:hover {
|
| 460 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 461 |
+
border-radius: 8px !important;
|
| 462 |
+
}
|
| 463 |
+
/* مخفی کردن آیکون/مربع نارنجی پیشفرض Gradio */
|
| 464 |
+
.progress-level svg, .progress-level img {
|
| 465 |
+
display: none !important;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
/* ایجاد یک دایره چرخان (Spinner) استاندارد */
|
| 469 |
+
.progress-level::before {
|
| 470 |
+
content: "";
|
| 471 |
+
display: inline-block;
|
| 472 |
+
width: 20px;
|
| 473 |
+
height: 20px;
|
| 474 |
+
border: 3px solid #e5e7eb; /* رنگ پسزمینه دایره */
|
| 475 |
+
border-radius: 50%;
|
| 476 |
+
border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
|
| 477 |
+
animation: spin 1s linear infinite;
|
| 478 |
+
margin-right: 8px;
|
| 479 |
+
vertical-align: middle;
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
/* انیمیشن چرخش */
|
| 483 |
+
@keyframes spin {
|
| 484 |
+
0% { transform: rotate(0deg); }
|
| 485 |
+
100% { transform: rotate(360deg); }
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 489 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 490 |
+
/*
|
| 491 |
+
.progress-text {
|
| 492 |
+
display: none !important;
|
| 493 |
+
}
|
| 494 |
+
*/
|
| 495 |
+
|
| 496 |
+
"""
|
| 497 |
+
|
| 498 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 499 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 500 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 501 |
+
|
| 502 |
+
# بقیه کدهای شما...
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
state = gr.State({
|
| 506 |
+
"history": [],
|
| 507 |
+
"user_name": None,
|
| 508 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 509 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 510 |
+
"service_context": service_context,
|
| 511 |
+
"api_keys": api_keys,
|
| 512 |
+
"api_index": 0,
|
| 513 |
+
"semantic_memory_text": "",
|
| 514 |
+
"new_conversation": True,
|
| 515 |
+
"initialized": False
|
| 516 |
+
})
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
|
| 520 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 521 |
+
with gr.Row():
|
| 522 |
+
|
| 523 |
+
# ==========================================
|
| 524 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 525 |
+
# ==========================================
|
| 526 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 527 |
+
with gr.Sidebar(open=True) as login_page:
|
| 528 |
+
|
| 529 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 530 |
+
|
| 531 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 532 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 533 |
+
|
| 534 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 535 |
+
|
| 536 |
+
with gr.Column(visible=False) as registration_fields:
|
| 537 |
+
gr.Markdown("### ✨ New User Registration")
|
| 538 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 539 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 540 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 541 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 542 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
# ==========================================
|
| 546 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 547 |
+
# ==========================================
|
| 548 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 549 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 550 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 551 |
+
#system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 552 |
+
|
| 553 |
+
with gr.Group():
|
| 554 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
|
| 555 |
+
|
| 556 |
+
with gr.Row():
|
| 557 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 558 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 559 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 560 |
+
|
| 561 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 562 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 563 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 564 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 565 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 566 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 567 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 568 |
+
|
| 569 |
+
# -------------------------------------------------------
|
| 570 |
+
# Internal Functions
|
| 571 |
+
# -------------------------------------------------------
|
| 572 |
+
def handle_login_check(name, state):
|
| 573 |
+
if not name.strip():
|
| 574 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 575 |
+
|
| 576 |
+
if name in memory:
|
| 577 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 578 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 579 |
+
|
| 580 |
+
new_state = state.copy()
|
| 581 |
+
new_state["user_name"] = name
|
| 582 |
+
new_state["memory"] = memory
|
| 583 |
+
new_state["initialized"] = True
|
| 584 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 585 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 586 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 587 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 588 |
+
new_state["history"] = []
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
|
| 593 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 594 |
+
|
| 595 |
+
return (
|
| 596 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 597 |
+
gr.update(visible=False),
|
| 598 |
+
gr.update(visible=True),
|
| 599 |
+
gr.update(visible=False, value=""),
|
| 600 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 601 |
+
gr.update(value=welcome_msg),
|
| 602 |
+
new_state
|
| 603 |
+
)
|
| 604 |
+
else:
|
| 605 |
+
return (
|
| 606 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 607 |
+
gr.update(visible=True),
|
| 608 |
+
gr.update(visible=False),
|
| 609 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 610 |
+
gr.update(),
|
| 611 |
+
gr.update(),
|
| 612 |
+
state
|
| 613 |
+
)
|
| 614 |
+
|
| 615 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 616 |
+
name = str(name).strip()
|
| 617 |
+
|
| 618 |
+
if not name:
|
| 619 |
+
raise gr.Error("Please enter a valid user name.")
|
| 620 |
+
|
| 621 |
+
# Registration is only for new users.
|
| 622 |
+
if name in memory:
|
| 623 |
+
raise gr.Error(
|
| 624 |
+
f"User '{name}' already exists. Please use the login form."
|
| 625 |
+
)
|
| 626 |
+
|
| 627 |
+
# Create the user before trying to build or load their indices.
|
| 628 |
+
memory[name] = {
|
| 629 |
+
"profile": {
|
| 630 |
+
"age": age,
|
| 631 |
+
"gender": gender,
|
| 632 |
+
"occupation": occupation,
|
| 633 |
+
"residence": residence,
|
| 634 |
+
},
|
| 635 |
+
"sessions": [],
|
| 636 |
+
"episodic_memory": [],
|
| 637 |
+
"semantic_memory": {},
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
try:
|
| 641 |
+
(
|
| 642 |
+
_,
|
| 643 |
+
user_memory,
|
| 644 |
+
sessions_memory,
|
| 645 |
+
episodic_memory,
|
| 646 |
+
semantic_memory,
|
| 647 |
+
) = enter_name_llamaindex(
|
| 648 |
+
name=name,
|
| 649 |
+
memory=memory,
|
| 650 |
+
data_args=data_args,
|
| 651 |
+
update_memory_index=True,
|
| 652 |
+
)
|
| 653 |
+
except Exception:
|
| 654 |
+
# Avoid leaving a partially registered user in memory.
|
| 655 |
+
memory.pop(name, None)
|
| 656 |
+
raise
|
| 657 |
+
|
| 658 |
+
new_state = dict(state or {})
|
| 659 |
+
new_state.update(
|
| 660 |
+
{
|
| 661 |
+
"user_name": name,
|
| 662 |
+
"memory": memory,
|
| 663 |
+
"initialized": True,
|
| 664 |
+
"history": [],
|
| 665 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 666 |
+
"user_memory_index": sessions_memory,
|
| 667 |
+
"episodic_memory_index": episodic_memory,
|
| 668 |
+
"semantic_memory_index": semantic_memory,
|
| 669 |
+
}
|
| 670 |
+
)
|
| 671 |
+
|
| 672 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 673 |
+
|
| 674 |
+
return (
|
| 675 |
+
gr.update(open=False),
|
| 676 |
+
gr.update(visible=False),
|
| 677 |
+
gr.update(visible=True),
|
| 678 |
+
gr.update(visible=False, value=""),
|
| 679 |
+
gr.update(
|
| 680 |
+
value=(
|
| 681 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 682 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 683 |
+
)
|
| 684 |
+
),
|
| 685 |
+
gr.update(value=welcome_msg),
|
| 686 |
+
new_state,
|
| 687 |
+
)
|
| 688 |
+
|
| 689 |
+
def switch_user(state):
|
| 690 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 691 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 692 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 693 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 694 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 695 |
+
# ==========================================
|
| 696 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 697 |
+
# ==========================================
|
| 698 |
+
try:
|
| 699 |
+
user_mem = state["memory"][state["user_name"]]
|
| 700 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 701 |
+
|
| 702 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 703 |
+
|
| 704 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 705 |
+
except Exception as e:
|
| 706 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 707 |
+
# ==========================================
|
| 708 |
+
|
| 709 |
+
new_state = state.copy()
|
| 710 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 711 |
+
|
| 712 |
+
return (
|
| 713 |
+
gr.update(open=True), # 1. باز شدن سایدبار
|
| 714 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام
|
| 715 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 716 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 717 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 718 |
+
new_state, # 6. استیت جدید
|
| 719 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 720 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 721 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 722 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 723 |
+
gr.update(value=""), # 11. پاک کردن residence_input
|
| 724 |
+
gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
|
| 725 |
+
)
|
| 726 |
+
|
| 727 |
+
|
| 728 |
+
def handle_chat(user_message, state):
|
| 729 |
+
if not user_message.strip():
|
| 730 |
+
print("[handle_chat] empty message")
|
| 731 |
+
print("[handle_chat] state =", state)
|
| 732 |
+
return gr.update(), state.get("history", []), state
|
| 733 |
+
|
| 734 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 735 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 736 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 737 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 738 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 739 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 740 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 741 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 742 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 743 |
+
|
| 744 |
+
user_name = state.get("user_name")
|
| 745 |
+
user_memory_index = state.get("user_memory_index")
|
| 746 |
+
user_memory = state.get("user_memory", {})
|
| 747 |
+
user_memory_index = state.get("user_memory_index")
|
| 748 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 749 |
+
service_context = state.get("service_context")
|
| 750 |
+
api_index = state.get("api_index", 0)
|
| 751 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 752 |
+
|
| 753 |
+
query_category = classify_query_local(user_message)
|
| 754 |
+
print("[handle_chat] query_category =", query_category)
|
| 755 |
+
|
| 756 |
+
new_history, _, status_msg = predict_new(
|
| 757 |
+
text=user_message,
|
| 758 |
+
history=state.get("history", []),
|
| 759 |
+
top_p=0.95,
|
| 760 |
+
temperature=1.0,
|
| 761 |
+
max_length_tokens=1024,
|
| 762 |
+
max_context_length_tokens=4096,
|
| 763 |
+
user_name=user_name,
|
| 764 |
+
user_memory=user_memory,
|
| 765 |
+
user_memory_index=user_memory_index,
|
| 766 |
+
service_context=service_context,
|
| 767 |
+
api_index=api_index,
|
| 768 |
+
semantic_memory_text=semantic_memory_text,
|
| 769 |
+
query_category=query_category,
|
| 770 |
+
|
| 771 |
+
)
|
| 772 |
+
|
| 773 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 774 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 775 |
+
|
| 776 |
+
state["history"] = new_history
|
| 777 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 778 |
+
|
| 779 |
+
return "", new_history, state
|
| 780 |
+
|
| 781 |
+
def clear_history(state):
|
| 782 |
+
state["history"] = []
|
| 783 |
+
return [], state
|
| 784 |
+
|
| 785 |
+
def handle_new_session(state):
|
| 786 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 787 |
+
user_name = state.get("user_name")
|
| 788 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 789 |
+
print("Error: User not logged in or memory missing.")
|
| 790 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 791 |
+
return [], state, gr.update() # خروجی سوم اضافه شد
|
| 792 |
+
|
| 793 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 794 |
+
user_data = state["memory"][user_name]
|
| 795 |
+
|
| 796 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 797 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 798 |
+
last_session = user_data["sessions"][-1]
|
| 799 |
+
|
| 800 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 801 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 802 |
+
session_date = last_session.get("date", "")
|
| 803 |
+
session_id = last_session.get("session_id", 0)
|
| 804 |
+
|
| 805 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 806 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 807 |
+
|
| 808 |
+
if "episodic_memory" not in user_data:
|
| 809 |
+
user_data["episodic_memory"] = []
|
| 810 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 811 |
+
|
| 812 |
+
# ==========================================
|
| 813 |
+
# بهروزرسانی حافظه سمانتیک
|
| 814 |
+
# ==========================================
|
| 815 |
+
try:
|
| 816 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 817 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 818 |
+
|
| 819 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 820 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 821 |
+
|
| 822 |
+
# ذخیره دیتای جدید
|
| 823 |
+
user_data["semantic_memory"] = updated_semantic
|
| 824 |
+
except Exception as e:
|
| 825 |
+
print(f"Error updating semantic memory: {e}")
|
| 826 |
+
# ==========================================
|
| 827 |
+
|
| 828 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 829 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 830 |
+
|
| 831 |
+
new_session = {
|
| 832 |
+
"session_id": new_session_id,
|
| 833 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 834 |
+
"conversation": []
|
| 835 |
+
}
|
| 836 |
+
|
| 837 |
+
if "sessions" not in user_data:
|
| 838 |
+
user_data["sessions"] = []
|
| 839 |
+
|
| 840 |
+
user_data["sessions"].append(new_session)
|
| 841 |
+
|
| 842 |
+
# پاک کردن تاریخچه چت در state
|
| 843 |
+
state["history"] = []
|
| 844 |
+
|
| 845 |
+
# محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
|
| 846 |
+
session_number = len(user_data["sessions"])
|
| 847 |
+
new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
|
| 848 |
+
|
| 849 |
+
# بازگرداندن خروجی جدید برای active_header
|
| 850 |
+
return [], state, gr.update(value=new_header_text)
|
| 851 |
+
|
| 852 |
+
check_user_btn.click(
|
| 853 |
+
handle_login_check,
|
| 854 |
+
inputs=[username_input, state],
|
| 855 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 856 |
+
show_progress="hidden"
|
| 857 |
+
)
|
| 858 |
+
|
| 859 |
+
register_btn.click(
|
| 860 |
+
handle_register,
|
| 861 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 862 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 863 |
+
show_progress="hidden"
|
| 864 |
+
)
|
| 865 |
+
|
| 866 |
+
switch_user_btn.click(
|
| 867 |
+
switch_user,
|
| 868 |
+
inputs=[state],
|
| 869 |
+
# system_msg به انتهای لیست خروجیها اضافه شد
|
| 870 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
|
| 871 |
+
show_progress="hidden"
|
| 872 |
+
)
|
| 873 |
+
|
| 874 |
+
|
| 875 |
+
submit_btn.click(
|
| 876 |
+
handle_chat,
|
| 877 |
+
inputs=[user_input, state],
|
| 878 |
+
outputs=[user_input, chatbot, state],
|
| 879 |
+
show_progress="hidden"
|
| 880 |
+
)
|
| 881 |
+
|
| 882 |
+
user_input.submit(
|
| 883 |
+
handle_chat,
|
| 884 |
+
inputs=[user_input, state],
|
| 885 |
+
outputs=[user_input, chatbot, state],
|
| 886 |
+
show_progress="hidden"
|
| 887 |
+
)
|
| 888 |
+
|
| 889 |
+
clear_btn.click(
|
| 890 |
+
clear_history,
|
| 891 |
+
inputs=[state],
|
| 892 |
+
outputs=[chatbot, state],
|
| 893 |
+
show_progress="hidden"
|
| 894 |
+
)
|
| 895 |
+
|
| 896 |
+
# تغییر از clear_history به handle_new_session
|
| 897 |
+
new_session_btn.click(
|
| 898 |
+
handle_new_session,
|
| 899 |
+
inputs=[state],
|
| 900 |
+
outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
|
| 901 |
+
show_progress="hidden"
|
| 902 |
+
)
|
| 903 |
+
|
| 904 |
+
return demo
|
| 905 |
+
|
| 906 |
+
|
| 907 |
+
def main():
|
| 908 |
+
"""Main function to initialize and launch the interface."""
|
| 909 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 910 |
+
|
| 911 |
+
if not gapgpt_api_key:
|
| 912 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 913 |
+
else:
|
| 914 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 915 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 916 |
+
|
| 917 |
+
# تنظیم LLM (مدل زبانی)
|
| 918 |
+
llm = LlamaIndexOpenAI(
|
| 919 |
+
model="gpt-4o",
|
| 920 |
+
temperature=1,
|
| 921 |
+
max_tokens=1024,
|
| 922 |
+
top_p=0.95,
|
| 923 |
+
frequency_penalty=0.4,
|
| 924 |
+
presence_penalty=0.2,
|
| 925 |
+
api_key=gapgpt_api_key,
|
| 926 |
+
api_base=GAPGPT_BASE_URL,
|
| 927 |
+
)
|
| 928 |
+
|
| 929 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 930 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 931 |
+
embed_model = OpenAIEmbedding(
|
| 932 |
+
api_key=gapgpt_api_key,
|
| 933 |
+
api_base=GAPGPT_BASE_URL,
|
| 934 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 935 |
+
)
|
| 936 |
+
|
| 937 |
+
# اعمال تنظیمات سراسری
|
| 938 |
+
Settings.llm = llm
|
| 939 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 940 |
+
|
| 941 |
+
Settings.prompt_helper = PromptHelper(
|
| 942 |
+
context_window=4096,
|
| 943 |
+
num_output=256,
|
| 944 |
+
chunk_overlap_ratio=20 / 4096,
|
| 945 |
+
tokenizer=tokenizer,
|
| 946 |
+
)
|
| 947 |
+
|
| 948 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 949 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 950 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 951 |
+
if 'api_keys' not in locals():
|
| 952 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 953 |
+
|
| 954 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 955 |
+
demo.launch(
|
| 956 |
+
server_name="127.0.0.1",
|
| 957 |
+
server_port=7860,
|
| 958 |
+
share=True
|
| 959 |
+
)
|
| 960 |
+
|
| 961 |
+
|
| 962 |
+
if __name__ == "__main__":
|
| 963 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 964 |
+
main()
|
Backup code/app_V13.py
ADDED
|
@@ -0,0 +1,973 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
user_profile=None
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
):
|
| 335 |
+
chatgpt_cfg = {
|
| 336 |
+
"model": "gpt-4o",
|
| 337 |
+
"temperature": temperature,
|
| 338 |
+
"max_tokens": max_length_tokens,
|
| 339 |
+
"top_p": top_p,
|
| 340 |
+
"frequency_penalty": 0.4,
|
| 341 |
+
"presence_penalty": 0.2,
|
| 342 |
+
"n": 1,
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
if text == "":
|
| 346 |
+
# Return same history if empty input
|
| 347 |
+
return history, history, "Empty context."
|
| 348 |
+
|
| 349 |
+
# Ensure history is initialized
|
| 350 |
+
if history is None:
|
| 351 |
+
history = []
|
| 352 |
+
|
| 353 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 354 |
+
history=history,
|
| 355 |
+
query=text, # Changed name to match prompt_utils
|
| 356 |
+
user_memory=user_memory,
|
| 357 |
+
user_name=user_name,
|
| 358 |
+
user_memory_index=user_memory_index,
|
| 359 |
+
service_context=service_context,
|
| 360 |
+
api_keys=api_keys,
|
| 361 |
+
api_index=api_index,
|
| 362 |
+
meta_prompt=meta_prompt,
|
| 363 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 364 |
+
data_args=data_args,
|
| 365 |
+
boot_actual_name=boot_actual_name,
|
| 366 |
+
semantic_memory_text=semantic_memory_text,
|
| 367 |
+
query_category=query_category,
|
| 368 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 369 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ==========================================
|
| 373 |
+
# اضافه کردن پروفایل به System Prompt
|
| 374 |
+
# ==========================================
|
| 375 |
+
if user_profile:
|
| 376 |
+
profile_str = (
|
| 377 |
+
f"\n\n[User Profile Information]:\n"
|
| 378 |
+
f"- Age: {user_profile.get('age', 'Unknown')}\n"
|
| 379 |
+
f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
|
| 380 |
+
f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
|
| 381 |
+
f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
|
| 382 |
+
f"Use this context subtly when talking to the user."
|
| 383 |
+
)
|
| 384 |
+
system_prompt += profile_str
|
| 385 |
+
# ==========================================
|
| 386 |
+
|
| 387 |
+
# Handle context window slicing manually if needed,
|
| 388 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 389 |
+
current_history_for_llm = history
|
| 390 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 391 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 392 |
+
|
| 393 |
+
response = chatgpt_chat(
|
| 394 |
+
prompt=text,
|
| 395 |
+
system=system_prompt,
|
| 396 |
+
history=current_history_for_llm,
|
| 397 |
+
gpt_config=chatgpt_cfg,
|
| 398 |
+
api_index=api_index,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
torch.cuda.empty_cache()
|
| 402 |
+
|
| 403 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 404 |
+
new_history = history + [
|
| 405 |
+
{"role": "user", "content": text},
|
| 406 |
+
{"role": "assistant", "content": response}
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 410 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 411 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 412 |
+
if user_name:
|
| 413 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 414 |
+
# or pass a converted version. Let's try passing the new format.
|
| 415 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 416 |
+
|
| 417 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 418 |
+
return new_history, new_history, "Generating..."
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
def create_gradio_interface(service_context, api_keys):
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 426 |
+
custom_css = """
|
| 427 |
+
/* استایل دکمه ارسال (Send) */
|
| 428 |
+
.send-btn {
|
| 429 |
+
border: 3px solid #0066cc !important;
|
| 430 |
+
border-radius: 12px !important;
|
| 431 |
+
background-color: white !important;
|
| 432 |
+
color: black !important;
|
| 433 |
+
font-weight: bold !important;
|
| 434 |
+
font-size: 16px !important;
|
| 435 |
+
transition: all 0.3s ease !important;
|
| 436 |
+
}
|
| 437 |
+
.send-btn:hover {
|
| 438 |
+
background-color: #0066cc !important;
|
| 439 |
+
color: white !important;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 443 |
+
.bottom-actions-row {
|
| 444 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
padding: 5px !important;
|
| 447 |
+
margin-top: 10px !important;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
.action-btn {
|
| 451 |
+
border: none !important;
|
| 452 |
+
background: transparent !important;
|
| 453 |
+
color: black !important;
|
| 454 |
+
font-weight: bold !important;
|
| 455 |
+
box-shadow: none !important;
|
| 456 |
+
transition: all 0.3s ease !important;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.action-btn:hover {
|
| 460 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 461 |
+
border-radius: 8px !important;
|
| 462 |
+
}
|
| 463 |
+
/* مخفی کردن آیکون/مربع نارنجی پیشفرض Gradio */
|
| 464 |
+
.progress-level svg, .progress-level img {
|
| 465 |
+
display: none !important;
|
| 466 |
+
}
|
| 467 |
+
|
| 468 |
+
/* ایجاد یک دایره چرخان (Spinner) استاندارد */
|
| 469 |
+
.progress-level::before {
|
| 470 |
+
content: "";
|
| 471 |
+
display: inline-block;
|
| 472 |
+
width: 20px;
|
| 473 |
+
height: 20px;
|
| 474 |
+
border: 3px solid #e5e7eb; /* رنگ پسزمینه دایره */
|
| 475 |
+
border-radius: 50%;
|
| 476 |
+
border-top-color: #0066cc; /* رنگ قسمت چرخنده دایره (آبی) */
|
| 477 |
+
animation: spin 1s linear infinite;
|
| 478 |
+
margin-right: 8px;
|
| 479 |
+
vertical-align: middle;
|
| 480 |
+
}
|
| 481 |
+
|
| 482 |
+
/* انیمیشن چرخش */
|
| 483 |
+
@keyframes spin {
|
| 484 |
+
0% { transform: rotate(0deg); }
|
| 485 |
+
100% { transform: rotate(360deg); }
|
| 486 |
+
}
|
| 487 |
+
|
| 488 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 489 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 490 |
+
/*
|
| 491 |
+
.progress-text {
|
| 492 |
+
display: none !important;
|
| 493 |
+
}
|
| 494 |
+
*/
|
| 495 |
+
|
| 496 |
+
"""
|
| 497 |
+
|
| 498 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 499 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 500 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 501 |
+
|
| 502 |
+
# بقیه کدهای شما...
|
| 503 |
+
|
| 504 |
+
|
| 505 |
+
state = gr.State({
|
| 506 |
+
"history": [],
|
| 507 |
+
"user_name": None,
|
| 508 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 509 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 510 |
+
"service_context": service_context,
|
| 511 |
+
"api_keys": api_keys,
|
| 512 |
+
"api_index": 0,
|
| 513 |
+
"semantic_memory_text": "",
|
| 514 |
+
"new_conversation": True,
|
| 515 |
+
"initialized": False
|
| 516 |
+
})
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
|
| 520 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 521 |
+
with gr.Row():
|
| 522 |
+
|
| 523 |
+
# ==========================================
|
| 524 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 525 |
+
# ==========================================
|
| 526 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 527 |
+
with gr.Sidebar(open=True) as login_page:
|
| 528 |
+
|
| 529 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 530 |
+
|
| 531 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 532 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 533 |
+
|
| 534 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 535 |
+
|
| 536 |
+
with gr.Column(visible=False) as registration_fields:
|
| 537 |
+
gr.Markdown("### ✨ New User Registration")
|
| 538 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 539 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 540 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 541 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 542 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
# ==========================================
|
| 546 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 547 |
+
# ==========================================
|
| 548 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 549 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 550 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 551 |
+
#system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 552 |
+
|
| 553 |
+
with gr.Group():
|
| 554 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
|
| 555 |
+
|
| 556 |
+
with gr.Row():
|
| 557 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 558 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 559 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 560 |
+
|
| 561 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 562 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 563 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 564 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 565 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 566 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 567 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 568 |
+
|
| 569 |
+
# -------------------------------------------------------
|
| 570 |
+
# Internal Functions
|
| 571 |
+
# -------------------------------------------------------
|
| 572 |
+
def handle_login_check(name, state):
|
| 573 |
+
if not name.strip():
|
| 574 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 575 |
+
|
| 576 |
+
if name in memory:
|
| 577 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 578 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 579 |
+
|
| 580 |
+
new_state = state.copy()
|
| 581 |
+
new_state["user_name"] = name
|
| 582 |
+
new_state["memory"] = memory
|
| 583 |
+
new_state["initialized"] = True
|
| 584 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 585 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 586 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 587 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 588 |
+
new_state["history"] = []
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
|
| 592 |
+
|
| 593 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 594 |
+
|
| 595 |
+
return (
|
| 596 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 597 |
+
gr.update(visible=False),
|
| 598 |
+
gr.update(visible=True),
|
| 599 |
+
gr.update(visible=False, value=""),
|
| 600 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 601 |
+
gr.update(value=welcome_msg),
|
| 602 |
+
new_state
|
| 603 |
+
)
|
| 604 |
+
else:
|
| 605 |
+
return (
|
| 606 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 607 |
+
gr.update(visible=True),
|
| 608 |
+
gr.update(visible=False),
|
| 609 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 610 |
+
gr.update(),
|
| 611 |
+
gr.update(),
|
| 612 |
+
state
|
| 613 |
+
)
|
| 614 |
+
|
| 615 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 616 |
+
name = str(name).strip()
|
| 617 |
+
|
| 618 |
+
if not name:
|
| 619 |
+
raise gr.Error("Please enter a valid user name.")
|
| 620 |
+
|
| 621 |
+
# Registration is only for new users.
|
| 622 |
+
if name in memory:
|
| 623 |
+
raise gr.Error(
|
| 624 |
+
f"User '{name}' already exists. Please use the login form."
|
| 625 |
+
)
|
| 626 |
+
|
| 627 |
+
# Create the user before trying to build or load their indices.
|
| 628 |
+
memory[name] = {
|
| 629 |
+
"profile": {
|
| 630 |
+
"age": age,
|
| 631 |
+
"gender": gender,
|
| 632 |
+
"occupation": occupation,
|
| 633 |
+
"residence": residence,
|
| 634 |
+
},
|
| 635 |
+
"sessions": [],
|
| 636 |
+
"episodic_memory": [],
|
| 637 |
+
"semantic_memory": {},
|
| 638 |
+
}
|
| 639 |
+
|
| 640 |
+
try:
|
| 641 |
+
(
|
| 642 |
+
_,
|
| 643 |
+
user_memory,
|
| 644 |
+
sessions_memory,
|
| 645 |
+
episodic_memory,
|
| 646 |
+
semantic_memory,
|
| 647 |
+
) = enter_name_llamaindex(
|
| 648 |
+
name=name,
|
| 649 |
+
memory=memory,
|
| 650 |
+
data_args=data_args,
|
| 651 |
+
update_memory_index=True,
|
| 652 |
+
)
|
| 653 |
+
except Exception:
|
| 654 |
+
# Avoid leaving a partially registered user in memory.
|
| 655 |
+
memory.pop(name, None)
|
| 656 |
+
raise
|
| 657 |
+
|
| 658 |
+
new_state = dict(state or {})
|
| 659 |
+
new_state.update(
|
| 660 |
+
{
|
| 661 |
+
"user_name": name,
|
| 662 |
+
"memory": memory,
|
| 663 |
+
"initialized": True,
|
| 664 |
+
"history": [],
|
| 665 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 666 |
+
"user_memory_index": sessions_memory,
|
| 667 |
+
"episodic_memory_index": episodic_memory,
|
| 668 |
+
"semantic_memory_index": semantic_memory,
|
| 669 |
+
}
|
| 670 |
+
)
|
| 671 |
+
|
| 672 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 673 |
+
|
| 674 |
+
return (
|
| 675 |
+
gr.update(open=False),
|
| 676 |
+
gr.update(visible=False),
|
| 677 |
+
gr.update(visible=True),
|
| 678 |
+
gr.update(visible=False, value=""),
|
| 679 |
+
gr.update(
|
| 680 |
+
value=(
|
| 681 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 682 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 683 |
+
)
|
| 684 |
+
),
|
| 685 |
+
gr.update(value=welcome_msg),
|
| 686 |
+
new_state,
|
| 687 |
+
)
|
| 688 |
+
|
| 689 |
+
def switch_user(state):
|
| 690 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 691 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 692 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 693 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 694 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 695 |
+
# ==========================================
|
| 696 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 697 |
+
# ==========================================
|
| 698 |
+
try:
|
| 699 |
+
user_mem = state["memory"][state["user_name"]]
|
| 700 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 701 |
+
|
| 702 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 703 |
+
|
| 704 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 705 |
+
except Exception as e:
|
| 706 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 707 |
+
# ==========================================
|
| 708 |
+
|
| 709 |
+
new_state = state.copy()
|
| 710 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 711 |
+
|
| 712 |
+
return (
|
| 713 |
+
gr.update(open=True), # 1. باز شدن سایدبار
|
| 714 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام
|
| 715 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 716 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 717 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 718 |
+
new_state, # 6. استیت جدید
|
| 719 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 720 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 721 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 722 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 723 |
+
gr.update(value=""), # 11. پاک کردن residence_input
|
| 724 |
+
gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
|
| 725 |
+
)
|
| 726 |
+
|
| 727 |
+
|
| 728 |
+
def handle_chat(user_message, state):
|
| 729 |
+
if not user_message.strip():
|
| 730 |
+
print("[handle_chat] empty message")
|
| 731 |
+
print("[handle_chat] state =", state)
|
| 732 |
+
return gr.update(), state.get("history", []), state
|
| 733 |
+
|
| 734 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 735 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 736 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 737 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 738 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 739 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 740 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 741 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 742 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 743 |
+
|
| 744 |
+
user_name = state.get("user_name")
|
| 745 |
+
user_memory_index = state.get("user_memory_index")
|
| 746 |
+
user_memory = state.get("user_memory", {})
|
| 747 |
+
user_memory_index = state.get("user_memory_index")
|
| 748 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 749 |
+
service_context = state.get("service_context")
|
| 750 |
+
api_index = state.get("api_index", 0)
|
| 751 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 752 |
+
|
| 753 |
+
# ==========================================
|
| 754 |
+
# استخراج پروفایل کاربر از حافظه
|
| 755 |
+
# ==========================================
|
| 756 |
+
user_profile = {}
|
| 757 |
+
if user_name and state.get("memory") and user_name in state["memory"]:
|
| 758 |
+
user_profile = state["memory"][user_name].get("profile", {})
|
| 759 |
+
# ==========================================
|
| 760 |
+
|
| 761 |
+
query_category = classify_query_local(user_message)
|
| 762 |
+
print("[handle_chat] query_category =", query_category)
|
| 763 |
+
|
| 764 |
+
new_history, _, status_msg = predict_new(
|
| 765 |
+
text=user_message,
|
| 766 |
+
history=state.get("history", []),
|
| 767 |
+
top_p=0.95,
|
| 768 |
+
temperature=1.0,
|
| 769 |
+
max_length_tokens=1024,
|
| 770 |
+
max_context_length_tokens=4096,
|
| 771 |
+
user_name=user_name,
|
| 772 |
+
user_memory=user_memory,
|
| 773 |
+
user_memory_index=user_memory_index,
|
| 774 |
+
service_context=service_context,
|
| 775 |
+
api_index=api_index,
|
| 776 |
+
semantic_memory_text=semantic_memory_text,
|
| 777 |
+
query_category=query_category,
|
| 778 |
+
user_profile=user_profile
|
| 779 |
+
|
| 780 |
+
)
|
| 781 |
+
|
| 782 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 783 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 784 |
+
|
| 785 |
+
state["history"] = new_history
|
| 786 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 787 |
+
|
| 788 |
+
return "", new_history, state
|
| 789 |
+
|
| 790 |
+
def clear_history(state):
|
| 791 |
+
state["history"] = []
|
| 792 |
+
return [], state
|
| 793 |
+
|
| 794 |
+
def handle_new_session(state):
|
| 795 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 796 |
+
user_name = state.get("user_name")
|
| 797 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 798 |
+
print("Error: User not logged in or memory missing.")
|
| 799 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 800 |
+
return [], state, gr.update() # خروجی سوم اضافه شد
|
| 801 |
+
|
| 802 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 803 |
+
user_data = state["memory"][user_name]
|
| 804 |
+
|
| 805 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 806 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 807 |
+
last_session = user_data["sessions"][-1]
|
| 808 |
+
|
| 809 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 810 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 811 |
+
session_date = last_session.get("date", "")
|
| 812 |
+
session_id = last_session.get("session_id", 0)
|
| 813 |
+
|
| 814 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 815 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 816 |
+
|
| 817 |
+
if "episodic_memory" not in user_data:
|
| 818 |
+
user_data["episodic_memory"] = []
|
| 819 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 820 |
+
|
| 821 |
+
# ==========================================
|
| 822 |
+
# بهروزرسانی حافظه سمانتیک
|
| 823 |
+
# ==========================================
|
| 824 |
+
try:
|
| 825 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 826 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 827 |
+
|
| 828 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 829 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 830 |
+
|
| 831 |
+
# ذخیره دیتای جدید
|
| 832 |
+
user_data["semantic_memory"] = updated_semantic
|
| 833 |
+
except Exception as e:
|
| 834 |
+
print(f"Error updating semantic memory: {e}")
|
| 835 |
+
# ==========================================
|
| 836 |
+
|
| 837 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 838 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 839 |
+
|
| 840 |
+
new_session = {
|
| 841 |
+
"session_id": new_session_id,
|
| 842 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 843 |
+
"conversation": []
|
| 844 |
+
}
|
| 845 |
+
|
| 846 |
+
if "sessions" not in user_data:
|
| 847 |
+
user_data["sessions"] = []
|
| 848 |
+
|
| 849 |
+
user_data["sessions"].append(new_session)
|
| 850 |
+
|
| 851 |
+
# پاک کردن تاریخچه چت در state
|
| 852 |
+
state["history"] = []
|
| 853 |
+
|
| 854 |
+
# محاسبه شماره جلسه فعلی (چون از 0 ش��وع میشود، +1 میکنیم)
|
| 855 |
+
session_number = len(user_data["sessions"])
|
| 856 |
+
new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
|
| 857 |
+
|
| 858 |
+
# بازگرداندن خروجی جدید برای active_header
|
| 859 |
+
return [], state, gr.update(value=new_header_text)
|
| 860 |
+
|
| 861 |
+
check_user_btn.click(
|
| 862 |
+
handle_login_check,
|
| 863 |
+
inputs=[username_input, state],
|
| 864 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 865 |
+
show_progress="hidden"
|
| 866 |
+
)
|
| 867 |
+
|
| 868 |
+
register_btn.click(
|
| 869 |
+
handle_register,
|
| 870 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 871 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 872 |
+
show_progress="hidden"
|
| 873 |
+
)
|
| 874 |
+
|
| 875 |
+
switch_user_btn.click(
|
| 876 |
+
switch_user,
|
| 877 |
+
inputs=[state],
|
| 878 |
+
# system_msg به انتهای لیست خروجیها اضافه شد
|
| 879 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
|
| 880 |
+
show_progress="hidden"
|
| 881 |
+
)
|
| 882 |
+
|
| 883 |
+
|
| 884 |
+
submit_btn.click(
|
| 885 |
+
handle_chat,
|
| 886 |
+
inputs=[user_input, state],
|
| 887 |
+
outputs=[user_input, chatbot, state],
|
| 888 |
+
show_progress="hidden"
|
| 889 |
+
)
|
| 890 |
+
|
| 891 |
+
user_input.submit(
|
| 892 |
+
handle_chat,
|
| 893 |
+
inputs=[user_input, state],
|
| 894 |
+
outputs=[user_input, chatbot, state],
|
| 895 |
+
show_progress="hidden"
|
| 896 |
+
)
|
| 897 |
+
|
| 898 |
+
clear_btn.click(
|
| 899 |
+
clear_history,
|
| 900 |
+
inputs=[state],
|
| 901 |
+
outputs=[chatbot, state],
|
| 902 |
+
show_progress="hidden"
|
| 903 |
+
)
|
| 904 |
+
|
| 905 |
+
# تغییر از clear_history به handle_new_session
|
| 906 |
+
new_session_btn.click(
|
| 907 |
+
handle_new_session,
|
| 908 |
+
inputs=[state],
|
| 909 |
+
outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
|
| 910 |
+
show_progress="hidden"
|
| 911 |
+
)
|
| 912 |
+
|
| 913 |
+
return demo
|
| 914 |
+
|
| 915 |
+
|
| 916 |
+
def main():
|
| 917 |
+
"""Main function to initialize and launch the interface."""
|
| 918 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 919 |
+
|
| 920 |
+
if not gapgpt_api_key:
|
| 921 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 922 |
+
else:
|
| 923 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 924 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 925 |
+
|
| 926 |
+
# تنظیم LLM (مدل زبانی)
|
| 927 |
+
llm = LlamaIndexOpenAI(
|
| 928 |
+
model="gpt-4o",
|
| 929 |
+
temperature=1,
|
| 930 |
+
max_tokens=1024,
|
| 931 |
+
top_p=0.95,
|
| 932 |
+
frequency_penalty=0.4,
|
| 933 |
+
presence_penalty=0.2,
|
| 934 |
+
api_key=gapgpt_api_key,
|
| 935 |
+
api_base=GAPGPT_BASE_URL,
|
| 936 |
+
)
|
| 937 |
+
|
| 938 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 939 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 940 |
+
embed_model = OpenAIEmbedding(
|
| 941 |
+
api_key=gapgpt_api_key,
|
| 942 |
+
api_base=GAPGPT_BASE_URL,
|
| 943 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 944 |
+
)
|
| 945 |
+
|
| 946 |
+
# اعمال تنظیمات سراسری
|
| 947 |
+
Settings.llm = llm
|
| 948 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 949 |
+
|
| 950 |
+
Settings.prompt_helper = PromptHelper(
|
| 951 |
+
context_window=4096,
|
| 952 |
+
num_output=256,
|
| 953 |
+
chunk_overlap_ratio=20 / 4096,
|
| 954 |
+
tokenizer=tokenizer,
|
| 955 |
+
)
|
| 956 |
+
|
| 957 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 958 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 959 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 960 |
+
if 'api_keys' not in locals():
|
| 961 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 962 |
+
|
| 963 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 964 |
+
demo.launch(
|
| 965 |
+
server_name="127.0.0.1",
|
| 966 |
+
server_port=7860,
|
| 967 |
+
share=True
|
| 968 |
+
)
|
| 969 |
+
|
| 970 |
+
|
| 971 |
+
if __name__ == "__main__":
|
| 972 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 973 |
+
main()
|
Backup code/app_V14.py
ADDED
|
@@ -0,0 +1,1032 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
user_profile=None
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
):
|
| 335 |
+
chatgpt_cfg = {
|
| 336 |
+
"model": "gpt-4o",
|
| 337 |
+
"temperature": temperature,
|
| 338 |
+
"max_tokens": max_length_tokens,
|
| 339 |
+
"top_p": top_p,
|
| 340 |
+
"frequency_penalty": 0.4,
|
| 341 |
+
"presence_penalty": 0.2,
|
| 342 |
+
"n": 1,
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
if text == "":
|
| 346 |
+
# Return same history if empty input
|
| 347 |
+
return history, history, "Empty context."
|
| 348 |
+
|
| 349 |
+
# Ensure history is initialized
|
| 350 |
+
if history is None:
|
| 351 |
+
history = []
|
| 352 |
+
|
| 353 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 354 |
+
history=history,
|
| 355 |
+
query=text, # Changed name to match prompt_utils
|
| 356 |
+
user_memory=user_memory,
|
| 357 |
+
user_name=user_name,
|
| 358 |
+
user_memory_index=user_memory_index,
|
| 359 |
+
service_context=service_context,
|
| 360 |
+
api_keys=api_keys,
|
| 361 |
+
api_index=api_index,
|
| 362 |
+
meta_prompt=meta_prompt,
|
| 363 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 364 |
+
data_args=data_args,
|
| 365 |
+
boot_actual_name=boot_actual_name,
|
| 366 |
+
semantic_memory_text=semantic_memory_text,
|
| 367 |
+
query_category=query_category,
|
| 368 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 369 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ==========================================
|
| 373 |
+
# اضافه کردن پروفایل به System Prompt
|
| 374 |
+
# ==========================================
|
| 375 |
+
if user_profile:
|
| 376 |
+
profile_str = (
|
| 377 |
+
f"\n\n[User Profile Information]:\n"
|
| 378 |
+
f"- Age: {user_profile.get('age', 'Unknown')}\n"
|
| 379 |
+
f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
|
| 380 |
+
f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
|
| 381 |
+
f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
|
| 382 |
+
f"Use this context subtly when talking to the user."
|
| 383 |
+
)
|
| 384 |
+
system_prompt += profile_str
|
| 385 |
+
# ==========================================
|
| 386 |
+
|
| 387 |
+
# Handle context window slicing manually if needed,
|
| 388 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 389 |
+
current_history_for_llm = history
|
| 390 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 391 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 392 |
+
|
| 393 |
+
response = chatgpt_chat(
|
| 394 |
+
prompt=text,
|
| 395 |
+
system=system_prompt,
|
| 396 |
+
history=current_history_for_llm,
|
| 397 |
+
gpt_config=chatgpt_cfg,
|
| 398 |
+
api_index=api_index,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
torch.cuda.empty_cache()
|
| 402 |
+
|
| 403 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 404 |
+
new_history = history + [
|
| 405 |
+
{"role": "user", "content": text},
|
| 406 |
+
{"role": "assistant", "content": response}
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 410 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 411 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 412 |
+
if user_name:
|
| 413 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 414 |
+
# or pass a converted version. Let's try passing the new format.
|
| 415 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 416 |
+
|
| 417 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 418 |
+
return new_history, new_history, "Generating..."
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
def create_gradio_interface(service_context, api_keys):
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 426 |
+
custom_css = """
|
| 427 |
+
/* استایل دکمه ارسال (Send) */
|
| 428 |
+
.send-btn {
|
| 429 |
+
border: 3px solid #0066cc !important;
|
| 430 |
+
border-radius: 12px !important;
|
| 431 |
+
background-color: white !important;
|
| 432 |
+
color: black !important;
|
| 433 |
+
font-weight: bold !important;
|
| 434 |
+
font-size: 16px !important;
|
| 435 |
+
transition: all 0.3s ease !important;
|
| 436 |
+
}
|
| 437 |
+
.send-btn:hover {
|
| 438 |
+
background-color: #0066cc !important;
|
| 439 |
+
color: white !important;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 443 |
+
.bottom-actions-row {
|
| 444 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
padding: 5px !important;
|
| 447 |
+
margin-top: 10px !important;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
.action-btn {
|
| 451 |
+
border: none !important;
|
| 452 |
+
background: transparent !important;
|
| 453 |
+
color: black !important;
|
| 454 |
+
font-weight: bold !important;
|
| 455 |
+
box-shadow: none !important;
|
| 456 |
+
transition: all 0.3s ease !important;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.action-btn:hover {
|
| 460 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 461 |
+
border-radius: 8px !important;
|
| 462 |
+
}
|
| 463 |
+
/* ========================================== */
|
| 464 |
+
/* لودینگ تمامصفحه و غیرفعالسازی تعاملات */
|
| 465 |
+
/* ========================================== */
|
| 466 |
+
|
| 467 |
+
/* مخفی کردن نوار پیشرفت پیشفرض Gradio */
|
| 468 |
+
.progress-level, .progress-text, .progress-level svg, .progress-level img {
|
| 469 |
+
display: none !important;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
/* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایلها روی body اعمال میشود */
|
| 473 |
+
body:has(.progress-level) {
|
| 474 |
+
pointer-events: none !important; /* غیرفعال کردن تمام کلیکها */
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
/* ایجاد هاله نیمهشفاف روی کل صفحه */
|
| 478 |
+
body:has(.progress-level)::after {
|
| 479 |
+
content: "";
|
| 480 |
+
position: fixed;
|
| 481 |
+
top: 0; left: 0;
|
| 482 |
+
width: 100vw; height: 100vh;
|
| 483 |
+
background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمهشفاف */
|
| 484 |
+
z-index: 9998;
|
| 485 |
+
pointer-events: all; /* برای گرفتن کلیکها و جلوگیری از عبور آنها */
|
| 486 |
+
cursor: wait;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
/* ایجاد اسپینر لودینگ در مرکز صفحه */
|
| 490 |
+
body:has(.progress-level)::before {
|
| 491 |
+
content: "";
|
| 492 |
+
position: fixed;
|
| 493 |
+
top: 50%; left: 50%;
|
| 494 |
+
transform: translate(-50%, -50%);
|
| 495 |
+
width: 60px; height: 60px;
|
| 496 |
+
border: 6px solid #e5e7eb;
|
| 497 |
+
border-top-color: #0066cc;
|
| 498 |
+
border-radius: 50%;
|
| 499 |
+
animation: spin 1s linear infinite;
|
| 500 |
+
z-index: 9999;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
@keyframes spin {
|
| 504 |
+
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
| 505 |
+
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
/* انیمیشن چرخش */
|
| 510 |
+
@keyframes spin {
|
| 511 |
+
0% { transform: rotate(0deg); }
|
| 512 |
+
100% { transform: rotate(360deg); }
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 516 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 517 |
+
/*
|
| 518 |
+
.progress-text {
|
| 519 |
+
display: none !important;
|
| 520 |
+
}
|
| 521 |
+
*/
|
| 522 |
+
/* انیمیشن سه نقطه در حال تایپ */
|
| 523 |
+
.typing-dots::after {
|
| 524 |
+
content: '';
|
| 525 |
+
animation: typing 1.5s infinite;
|
| 526 |
+
}
|
| 527 |
+
@keyframes typing {
|
| 528 |
+
0% { content: ''; }
|
| 529 |
+
25% { content: ' .'; }
|
| 530 |
+
50% { content: ' . .'; }
|
| 531 |
+
75% { content: ' . . .'; }
|
| 532 |
+
100% { content: ''; }
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
"""
|
| 537 |
+
|
| 538 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 539 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 540 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 541 |
+
|
| 542 |
+
# بقیه کدهای شما...
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
state = gr.State({
|
| 546 |
+
"history": [],
|
| 547 |
+
"user_name": None,
|
| 548 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 549 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 550 |
+
"service_context": service_context,
|
| 551 |
+
"api_keys": api_keys,
|
| 552 |
+
"api_index": 0,
|
| 553 |
+
"semantic_memory_text": "",
|
| 554 |
+
"new_conversation": True,
|
| 555 |
+
"initialized": False
|
| 556 |
+
})
|
| 557 |
+
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 561 |
+
with gr.Row():
|
| 562 |
+
|
| 563 |
+
# ==========================================
|
| 564 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 565 |
+
# ==========================================
|
| 566 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 567 |
+
with gr.Sidebar(open=True) as login_page:
|
| 568 |
+
|
| 569 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 570 |
+
|
| 571 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 572 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 573 |
+
|
| 574 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 575 |
+
|
| 576 |
+
with gr.Column(visible=False) as registration_fields:
|
| 577 |
+
gr.Markdown("### ✨ New User Registration")
|
| 578 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 579 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 580 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 581 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 582 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
# ==========================================
|
| 586 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 587 |
+
# ==========================================
|
| 588 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 589 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 590 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 591 |
+
#system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 592 |
+
|
| 593 |
+
with gr.Group():
|
| 594 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
|
| 595 |
+
|
| 596 |
+
with gr.Row():
|
| 597 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 598 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 599 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 600 |
+
|
| 601 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 602 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 603 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 604 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 605 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 606 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 607 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 608 |
+
|
| 609 |
+
# -------------------------------------------------------
|
| 610 |
+
# Internal Functions
|
| 611 |
+
# -------------------------------------------------------
|
| 612 |
+
def handle_login_check(name, state):
|
| 613 |
+
if not name.strip():
|
| 614 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 615 |
+
|
| 616 |
+
if name in memory:
|
| 617 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 618 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 619 |
+
|
| 620 |
+
new_state = state.copy()
|
| 621 |
+
new_state["user_name"] = name
|
| 622 |
+
new_state["memory"] = memory
|
| 623 |
+
new_state["initialized"] = True
|
| 624 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 625 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 626 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 627 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 628 |
+
new_state["history"] = []
|
| 629 |
+
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 634 |
+
|
| 635 |
+
return (
|
| 636 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 637 |
+
gr.update(visible=False),
|
| 638 |
+
gr.update(visible=True),
|
| 639 |
+
gr.update(visible=False, value=""),
|
| 640 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 641 |
+
gr.update(value=welcome_msg),
|
| 642 |
+
new_state
|
| 643 |
+
)
|
| 644 |
+
else:
|
| 645 |
+
return (
|
| 646 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 647 |
+
gr.update(visible=True),
|
| 648 |
+
gr.update(visible=False),
|
| 649 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 650 |
+
gr.update(),
|
| 651 |
+
gr.update(),
|
| 652 |
+
state
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 656 |
+
name = str(name).strip()
|
| 657 |
+
|
| 658 |
+
if not name:
|
| 659 |
+
raise gr.Error("Please enter a valid user name.")
|
| 660 |
+
|
| 661 |
+
# Registration is only for new users.
|
| 662 |
+
if name in memory:
|
| 663 |
+
raise gr.Error(
|
| 664 |
+
f"User '{name}' already exists. Please use the login form."
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
# Create the user before trying to build or load their indices.
|
| 668 |
+
memory[name] = {
|
| 669 |
+
"profile": {
|
| 670 |
+
"age": age,
|
| 671 |
+
"gender": gender,
|
| 672 |
+
"occupation": occupation,
|
| 673 |
+
"residence": residence,
|
| 674 |
+
},
|
| 675 |
+
"sessions": [],
|
| 676 |
+
"episodic_memory": [],
|
| 677 |
+
"semantic_memory": {},
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
try:
|
| 681 |
+
(
|
| 682 |
+
_,
|
| 683 |
+
user_memory,
|
| 684 |
+
sessions_memory,
|
| 685 |
+
episodic_memory,
|
| 686 |
+
semantic_memory,
|
| 687 |
+
) = enter_name_llamaindex(
|
| 688 |
+
name=name,
|
| 689 |
+
memory=memory,
|
| 690 |
+
data_args=data_args,
|
| 691 |
+
update_memory_index=True,
|
| 692 |
+
)
|
| 693 |
+
except Exception:
|
| 694 |
+
# Avoid leaving a partially registered user in memory.
|
| 695 |
+
memory.pop(name, None)
|
| 696 |
+
raise
|
| 697 |
+
|
| 698 |
+
new_state = dict(state or {})
|
| 699 |
+
new_state.update(
|
| 700 |
+
{
|
| 701 |
+
"user_name": name,
|
| 702 |
+
"memory": memory,
|
| 703 |
+
"initialized": True,
|
| 704 |
+
"history": [],
|
| 705 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 706 |
+
"user_memory_index": sessions_memory,
|
| 707 |
+
"episodic_memory_index": episodic_memory,
|
| 708 |
+
"semantic_memory_index": semantic_memory,
|
| 709 |
+
}
|
| 710 |
+
)
|
| 711 |
+
|
| 712 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 713 |
+
|
| 714 |
+
return (
|
| 715 |
+
gr.update(open=False),
|
| 716 |
+
gr.update(visible=False),
|
| 717 |
+
gr.update(visible=True),
|
| 718 |
+
gr.update(visible=False, value=""),
|
| 719 |
+
gr.update(
|
| 720 |
+
value=(
|
| 721 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 722 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 723 |
+
)
|
| 724 |
+
),
|
| 725 |
+
gr.update(value=welcome_msg),
|
| 726 |
+
new_state,
|
| 727 |
+
)
|
| 728 |
+
|
| 729 |
+
def switch_user(state):
|
| 730 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 731 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 732 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 733 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 734 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 735 |
+
# ==========================================
|
| 736 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 737 |
+
# ==========================================
|
| 738 |
+
try:
|
| 739 |
+
user_mem = state["memory"][state["user_name"]]
|
| 740 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 741 |
+
|
| 742 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 743 |
+
|
| 744 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 745 |
+
except Exception as e:
|
| 746 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 747 |
+
# ==========================================
|
| 748 |
+
|
| 749 |
+
new_state = state.copy()
|
| 750 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 751 |
+
|
| 752 |
+
return (
|
| 753 |
+
gr.update(open=True), # 1. باز شدن سایدبار
|
| 754 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام
|
| 755 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 756 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 757 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 758 |
+
new_state, # 6. استیت جدید
|
| 759 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 760 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 761 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 762 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 763 |
+
gr.update(value=""), # 11. پاک کردن residence_input
|
| 764 |
+
gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
|
| 768 |
+
def handle_chat(user_message, state):
|
| 769 |
+
if not user_message.strip():
|
| 770 |
+
print("[handle_chat] empty message")
|
| 771 |
+
print("[handle_chat] state =", state)
|
| 772 |
+
# تبدیل return به yield
|
| 773 |
+
yield gr.update(), state.get("history", []), state
|
| 774 |
+
return
|
| 775 |
+
|
| 776 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 777 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 778 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 779 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 780 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 781 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 782 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 783 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 784 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 785 |
+
|
| 786 |
+
# ==========================================
|
| 787 |
+
# ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
|
| 788 |
+
# ==========================================
|
| 789 |
+
current_history = state.get("history", [])
|
| 790 |
+
temp_history = current_history + [
|
| 791 |
+
{"role": "user", "content": user_message},
|
| 792 |
+
{"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
|
| 793 |
+
]
|
| 794 |
+
|
| 795 |
+
# باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI میفرستیم
|
| 796 |
+
yield gr.update(value=""), temp_history, state
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
# ادامه پردازشهای اصلی تابع شما
|
| 800 |
+
user_name = state.get("user_name")
|
| 801 |
+
user_memory_index = state.get("user_memory_index")
|
| 802 |
+
user_memory = state.get("user_memory", {})
|
| 803 |
+
user_memory_index = state.get("user_memory_index")
|
| 804 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 805 |
+
service_context = state.get("service_context")
|
| 806 |
+
api_index = state.get("api_index", 0)
|
| 807 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 808 |
+
|
| 809 |
+
# ==========================================
|
| 810 |
+
# استخراج پروفایل کاربر از حافظه
|
| 811 |
+
# ==========================================
|
| 812 |
+
user_profile = {}
|
| 813 |
+
if user_name and state.get("memory") and user_name in state["memory"]:
|
| 814 |
+
user_profile = state["memory"][user_name].get("profile", {})
|
| 815 |
+
# ==========================================
|
| 816 |
+
|
| 817 |
+
query_category = classify_query_local(user_message)
|
| 818 |
+
print("[handle_chat] query_category =", query_category)
|
| 819 |
+
|
| 820 |
+
# ارسال current_history به مدل (بدون انیمیشن موقت)
|
| 821 |
+
new_history, _, status_msg = predict_new(
|
| 822 |
+
text=user_message,
|
| 823 |
+
history=current_history,
|
| 824 |
+
top_p=0.95,
|
| 825 |
+
temperature=1.0,
|
| 826 |
+
max_length_tokens=1024,
|
| 827 |
+
max_context_length_tokens=4096,
|
| 828 |
+
user_name=user_name,
|
| 829 |
+
user_memory=user_memory,
|
| 830 |
+
user_memory_index=user_memory_index,
|
| 831 |
+
service_context=service_context,
|
| 832 |
+
api_index=api_index,
|
| 833 |
+
semantic_memory_text=semantic_memory_text,
|
| 834 |
+
query_category=query_category,
|
| 835 |
+
user_profile=user_profile
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 839 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 840 |
+
|
| 841 |
+
state["history"] = new_history
|
| 842 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 843 |
+
|
| 844 |
+
# ==========================================
|
| 845 |
+
# ۳. جایگزینی پیام لودینگ با پاسخ نهایی
|
| 846 |
+
# ==========================================
|
| 847 |
+
yield gr.update(), new_history, state
|
| 848 |
+
|
| 849 |
+
def clear_history(state):
|
| 850 |
+
state["history"] = []
|
| 851 |
+
return [], state
|
| 852 |
+
|
| 853 |
+
def handle_new_session(state):
|
| 854 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 855 |
+
user_name = state.get("user_name")
|
| 856 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 857 |
+
print("Error: User not logged in or memory missing.")
|
| 858 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 859 |
+
return [], state, gr.update() # خروجی سوم اضافه شد
|
| 860 |
+
|
| 861 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 862 |
+
user_data = state["memory"][user_name]
|
| 863 |
+
|
| 864 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 865 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 866 |
+
last_session = user_data["sessions"][-1]
|
| 867 |
+
|
| 868 |
+
# فقط در صورتی حافظه را استخراج کن که ��لسه قبلی خالی نباشد
|
| 869 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 870 |
+
session_date = last_session.get("date", "")
|
| 871 |
+
session_id = last_session.get("session_id", 0)
|
| 872 |
+
|
| 873 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 874 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 875 |
+
|
| 876 |
+
if "episodic_memory" not in user_data:
|
| 877 |
+
user_data["episodic_memory"] = []
|
| 878 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 879 |
+
|
| 880 |
+
# ==========================================
|
| 881 |
+
# بهروزرسانی حافظه سمانتیک
|
| 882 |
+
# ==========================================
|
| 883 |
+
try:
|
| 884 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 885 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 886 |
+
|
| 887 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 888 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 889 |
+
|
| 890 |
+
# ذخیره دیتای جدید
|
| 891 |
+
user_data["semantic_memory"] = updated_semantic
|
| 892 |
+
except Exception as e:
|
| 893 |
+
print(f"Error updating semantic memory: {e}")
|
| 894 |
+
# ==========================================
|
| 895 |
+
|
| 896 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 897 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 898 |
+
|
| 899 |
+
new_session = {
|
| 900 |
+
"session_id": new_session_id,
|
| 901 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 902 |
+
"conversation": []
|
| 903 |
+
}
|
| 904 |
+
|
| 905 |
+
if "sessions" not in user_data:
|
| 906 |
+
user_data["sessions"] = []
|
| 907 |
+
|
| 908 |
+
user_data["sessions"].append(new_session)
|
| 909 |
+
|
| 910 |
+
# پاک کردن تاریخچه چت در state
|
| 911 |
+
state["history"] = []
|
| 912 |
+
|
| 913 |
+
# محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
|
| 914 |
+
session_number = len(user_data["sessions"])
|
| 915 |
+
new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
|
| 916 |
+
|
| 917 |
+
# بازگرداندن خروجی جدید برای active_header
|
| 918 |
+
return [], state, gr.update(value=new_header_text)
|
| 919 |
+
|
| 920 |
+
check_user_btn.click(
|
| 921 |
+
handle_login_check,
|
| 922 |
+
inputs=[username_input, state],
|
| 923 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 924 |
+
# show_progress="hidden"
|
| 925 |
+
)
|
| 926 |
+
|
| 927 |
+
register_btn.click(
|
| 928 |
+
handle_register,
|
| 929 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 930 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 931 |
+
# show_progress="hidden"
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
switch_user_btn.click(
|
| 935 |
+
switch_user,
|
| 936 |
+
inputs=[state],
|
| 937 |
+
# system_msg به انتهای لیست خروجیها اضافه شد
|
| 938 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
|
| 939 |
+
# show_progress="hidden"
|
| 940 |
+
)
|
| 941 |
+
|
| 942 |
+
|
| 943 |
+
submit_btn.click(
|
| 944 |
+
handle_chat,
|
| 945 |
+
inputs=[user_input, state],
|
| 946 |
+
outputs=[user_input, chatbot, state],
|
| 947 |
+
# show_progress="hidden"
|
| 948 |
+
)
|
| 949 |
+
|
| 950 |
+
user_input.submit(
|
| 951 |
+
handle_chat,
|
| 952 |
+
inputs=[user_input, state],
|
| 953 |
+
outputs=[user_input, chatbot, state],
|
| 954 |
+
# show_progress="hidden"
|
| 955 |
+
)
|
| 956 |
+
|
| 957 |
+
clear_btn.click(
|
| 958 |
+
clear_history,
|
| 959 |
+
inputs=[state],
|
| 960 |
+
outputs=[chatbot, state],
|
| 961 |
+
# show_progress="hidden"
|
| 962 |
+
)
|
| 963 |
+
|
| 964 |
+
# تغییر از clear_history به handle_new_session
|
| 965 |
+
new_session_btn.click(
|
| 966 |
+
handle_new_session,
|
| 967 |
+
inputs=[state],
|
| 968 |
+
outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
|
| 969 |
+
# show_progress="hidden"
|
| 970 |
+
)
|
| 971 |
+
|
| 972 |
+
return demo
|
| 973 |
+
|
| 974 |
+
|
| 975 |
+
def main():
|
| 976 |
+
"""Main function to initialize and launch the interface."""
|
| 977 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 978 |
+
|
| 979 |
+
if not gapgpt_api_key:
|
| 980 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 981 |
+
else:
|
| 982 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی ��رای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 983 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 984 |
+
|
| 985 |
+
# تنظیم LLM (مدل زبانی)
|
| 986 |
+
llm = LlamaIndexOpenAI(
|
| 987 |
+
model="gpt-4o",
|
| 988 |
+
temperature=1,
|
| 989 |
+
max_tokens=1024,
|
| 990 |
+
top_p=0.95,
|
| 991 |
+
frequency_penalty=0.4,
|
| 992 |
+
presence_penalty=0.2,
|
| 993 |
+
api_key=gapgpt_api_key,
|
| 994 |
+
api_base=GAPGPT_BASE_URL,
|
| 995 |
+
)
|
| 996 |
+
|
| 997 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 998 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 999 |
+
embed_model = OpenAIEmbedding(
|
| 1000 |
+
api_key=gapgpt_api_key,
|
| 1001 |
+
api_base=GAPGPT_BASE_URL,
|
| 1002 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 1003 |
+
)
|
| 1004 |
+
|
| 1005 |
+
# اعمال تنظیمات سراسری
|
| 1006 |
+
Settings.llm = llm
|
| 1007 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 1008 |
+
|
| 1009 |
+
Settings.prompt_helper = PromptHelper(
|
| 1010 |
+
context_window=4096,
|
| 1011 |
+
num_output=256,
|
| 1012 |
+
chunk_overlap_ratio=20 / 4096,
|
| 1013 |
+
tokenizer=tokenizer,
|
| 1014 |
+
)
|
| 1015 |
+
|
| 1016 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 1017 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 1018 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 1019 |
+
if 'api_keys' not in locals():
|
| 1020 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 1021 |
+
|
| 1022 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 1023 |
+
demo.launch(
|
| 1024 |
+
server_name="127.0.0.1",
|
| 1025 |
+
server_port=7860,
|
| 1026 |
+
share=True
|
| 1027 |
+
)
|
| 1028 |
+
|
| 1029 |
+
|
| 1030 |
+
if __name__ == "__main__":
|
| 1031 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 1032 |
+
main()
|
Backup code/app_V15.py
ADDED
|
@@ -0,0 +1,1031 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Classification_Model", "final_xlm_r_model_router")
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "api_key_list.txt")
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "memories", "update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
user_profile=None
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
):
|
| 335 |
+
chatgpt_cfg = {
|
| 336 |
+
"model": "gpt-4o",
|
| 337 |
+
"temperature": temperature,
|
| 338 |
+
"max_tokens": max_length_tokens,
|
| 339 |
+
"top_p": top_p,
|
| 340 |
+
"frequency_penalty": 0.4,
|
| 341 |
+
"presence_penalty": 0.2,
|
| 342 |
+
"n": 1,
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
if text == "":
|
| 346 |
+
# Return same history if empty input
|
| 347 |
+
return history, history, "Empty context."
|
| 348 |
+
|
| 349 |
+
# Ensure history is initialized
|
| 350 |
+
if history is None:
|
| 351 |
+
history = []
|
| 352 |
+
|
| 353 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 354 |
+
history=history,
|
| 355 |
+
query=text, # Changed name to match prompt_utils
|
| 356 |
+
user_memory=user_memory,
|
| 357 |
+
user_name=user_name,
|
| 358 |
+
user_memory_index=user_memory_index,
|
| 359 |
+
service_context=service_context,
|
| 360 |
+
api_keys=api_keys,
|
| 361 |
+
api_index=api_index,
|
| 362 |
+
meta_prompt=meta_prompt,
|
| 363 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 364 |
+
data_args=data_args,
|
| 365 |
+
boot_actual_name=boot_actual_name,
|
| 366 |
+
semantic_memory_text=semantic_memory_text,
|
| 367 |
+
query_category=query_category,
|
| 368 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 369 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ==========================================
|
| 373 |
+
# اضافه کردن پروفایل به System Prompt
|
| 374 |
+
# ==========================================
|
| 375 |
+
if user_profile:
|
| 376 |
+
profile_str = (
|
| 377 |
+
f"\n\n[User Profile Information]:\n"
|
| 378 |
+
f"- Age: {user_profile.get('age', 'Unknown')}\n"
|
| 379 |
+
f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
|
| 380 |
+
f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
|
| 381 |
+
f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
|
| 382 |
+
f"Use this context subtly when talking to the user."
|
| 383 |
+
)
|
| 384 |
+
system_prompt += profile_str
|
| 385 |
+
# ==========================================
|
| 386 |
+
|
| 387 |
+
# Handle context window slicing manually if needed,
|
| 388 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 389 |
+
current_history_for_llm = history
|
| 390 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 391 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 392 |
+
|
| 393 |
+
response = chatgpt_chat(
|
| 394 |
+
prompt=text,
|
| 395 |
+
system=system_prompt,
|
| 396 |
+
history=current_history_for_llm,
|
| 397 |
+
gpt_config=chatgpt_cfg,
|
| 398 |
+
api_index=api_index,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
torch.cuda.empty_cache()
|
| 402 |
+
|
| 403 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 404 |
+
new_history = history + [
|
| 405 |
+
{"role": "user", "content": text},
|
| 406 |
+
{"role": "assistant", "content": response}
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 410 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 411 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 412 |
+
if user_name:
|
| 413 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 414 |
+
# or pass a converted version. Let's try passing the new format.
|
| 415 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 416 |
+
|
| 417 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 418 |
+
return new_history, new_history, "Generating..."
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
def create_gradio_interface(service_context, api_keys):
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 426 |
+
custom_css = """
|
| 427 |
+
/* استایل دکمه ارسال (Send) */
|
| 428 |
+
.send-btn {
|
| 429 |
+
border: 3px solid #0066cc !important;
|
| 430 |
+
border-radius: 12px !important;
|
| 431 |
+
background-color: white !important;
|
| 432 |
+
color: black !important;
|
| 433 |
+
font-weight: bold !important;
|
| 434 |
+
font-size: 16px !important;
|
| 435 |
+
transition: all 0.3s ease !important;
|
| 436 |
+
}
|
| 437 |
+
.send-btn:hover {
|
| 438 |
+
background-color: #0066cc !important;
|
| 439 |
+
color: white !important;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 443 |
+
.bottom-actions-row {
|
| 444 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
padding: 5px !important;
|
| 447 |
+
margin-top: 10px !important;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
.action-btn {
|
| 451 |
+
border: none !important;
|
| 452 |
+
background: transparent !important;
|
| 453 |
+
color: black !important;
|
| 454 |
+
font-weight: bold !important;
|
| 455 |
+
box-shadow: none !important;
|
| 456 |
+
transition: all 0.3s ease !important;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.action-btn:hover {
|
| 460 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 461 |
+
border-radius: 8px !important;
|
| 462 |
+
}
|
| 463 |
+
/* ========================================== */
|
| 464 |
+
/* لودینگ تمامصفحه و غیرفعالسازی تعاملات */
|
| 465 |
+
/* ========================================== */
|
| 466 |
+
|
| 467 |
+
/* مخفی کردن نوار پیشرفت پیشفرض Gradio */
|
| 468 |
+
.progress-level, .progress-text, .progress-level svg, .progress-level img {
|
| 469 |
+
display: none !important;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
/* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایلها روی body اعمال میشود */
|
| 473 |
+
body:has(.progress-level) {
|
| 474 |
+
pointer-events: none !important; /* غیرفعال کردن تمام کلیکها */
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
/* ایجاد هاله نیمهشفاف روی کل صفحه */
|
| 478 |
+
body:has(.progress-level)::after {
|
| 479 |
+
content: "";
|
| 480 |
+
position: fixed;
|
| 481 |
+
top: 0; left: 0;
|
| 482 |
+
width: 100vw; height: 100vh;
|
| 483 |
+
background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمهشفاف */
|
| 484 |
+
z-index: 9998;
|
| 485 |
+
pointer-events: all; /* برای گرفتن کلیکها و جلوگیری از عبور آنها */
|
| 486 |
+
cursor: wait;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
/* ایجاد اسپینر لودینگ در مرکز صفحه */
|
| 490 |
+
body:has(.progress-level)::before {
|
| 491 |
+
content: "";
|
| 492 |
+
position: fixed;
|
| 493 |
+
top: 50%; left: 50%;
|
| 494 |
+
transform: translate(-50%, -50%);
|
| 495 |
+
width: 60px; height: 60px;
|
| 496 |
+
border: 6px solid #e5e7eb;
|
| 497 |
+
border-top-color: #0066cc;
|
| 498 |
+
border-radius: 50%;
|
| 499 |
+
animation: spin 1s linear infinite;
|
| 500 |
+
z-index: 9999;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
@keyframes spin {
|
| 504 |
+
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
| 505 |
+
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
/* انیمیشن چرخش */
|
| 510 |
+
@keyframes spin {
|
| 511 |
+
0% { transform: rotate(0deg); }
|
| 512 |
+
100% { transform: rotate(360deg); }
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 516 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 517 |
+
/*
|
| 518 |
+
.progress-text {
|
| 519 |
+
display: none !important;
|
| 520 |
+
}
|
| 521 |
+
*/
|
| 522 |
+
/* انیمیشن سه نقطه در حال تایپ */
|
| 523 |
+
.typing-dots::after {
|
| 524 |
+
content: '';
|
| 525 |
+
animation: typing 1.5s infinite;
|
| 526 |
+
}
|
| 527 |
+
@keyframes typing {
|
| 528 |
+
0% { content: ''; }
|
| 529 |
+
25% { content: ' .'; }
|
| 530 |
+
50% { content: ' . .'; }
|
| 531 |
+
75% { content: ' . . .'; }
|
| 532 |
+
100% { content: ''; }
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
"""
|
| 537 |
+
|
| 538 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 539 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 540 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 541 |
+
|
| 542 |
+
# بقیه کدهای شما...
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
state = gr.State({
|
| 546 |
+
"history": [],
|
| 547 |
+
"user_name": None,
|
| 548 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 549 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 550 |
+
"service_context": service_context,
|
| 551 |
+
"api_keys": api_keys,
|
| 552 |
+
"api_index": 0,
|
| 553 |
+
"semantic_memory_text": "",
|
| 554 |
+
"new_conversation": True,
|
| 555 |
+
"initialized": False
|
| 556 |
+
})
|
| 557 |
+
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 561 |
+
with gr.Row():
|
| 562 |
+
|
| 563 |
+
# ==========================================
|
| 564 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 565 |
+
# ==========================================
|
| 566 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 567 |
+
with gr.Sidebar(open=True) as login_page:
|
| 568 |
+
|
| 569 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 570 |
+
|
| 571 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 572 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 573 |
+
|
| 574 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 575 |
+
|
| 576 |
+
with gr.Column(visible=False) as registration_fields:
|
| 577 |
+
gr.Markdown("### ✨ New User Registration")
|
| 578 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 579 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 580 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 581 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 582 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
# ==========================================
|
| 586 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 587 |
+
# ==========================================
|
| 588 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 589 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 590 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 591 |
+
#system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 592 |
+
|
| 593 |
+
with gr.Group():
|
| 594 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
|
| 595 |
+
|
| 596 |
+
with gr.Row():
|
| 597 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 598 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 599 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 600 |
+
|
| 601 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 602 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 603 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 604 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 605 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 606 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 607 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 608 |
+
|
| 609 |
+
# -------------------------------------------------------
|
| 610 |
+
# Internal Functions
|
| 611 |
+
# -------------------------------------------------------
|
| 612 |
+
def handle_login_check(name, state):
|
| 613 |
+
if not name.strip():
|
| 614 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 615 |
+
|
| 616 |
+
if name in memory:
|
| 617 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 618 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 619 |
+
|
| 620 |
+
new_state = state.copy()
|
| 621 |
+
new_state["user_name"] = name
|
| 622 |
+
new_state["memory"] = memory
|
| 623 |
+
new_state["initialized"] = True
|
| 624 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 625 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 626 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 627 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 628 |
+
new_state["history"] = []
|
| 629 |
+
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 634 |
+
|
| 635 |
+
return (
|
| 636 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 637 |
+
gr.update(visible=False),
|
| 638 |
+
gr.update(visible=True),
|
| 639 |
+
gr.update(visible=False, value=""),
|
| 640 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 641 |
+
gr.update(value=welcome_msg),
|
| 642 |
+
new_state
|
| 643 |
+
)
|
| 644 |
+
else:
|
| 645 |
+
return (
|
| 646 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 647 |
+
gr.update(visible=True),
|
| 648 |
+
gr.update(visible=False),
|
| 649 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 650 |
+
gr.update(),
|
| 651 |
+
gr.update(),
|
| 652 |
+
state
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 656 |
+
name = str(name).strip()
|
| 657 |
+
|
| 658 |
+
if not name:
|
| 659 |
+
raise gr.Error("Please enter a valid user name.")
|
| 660 |
+
|
| 661 |
+
# Registration is only for new users.
|
| 662 |
+
if name in memory:
|
| 663 |
+
raise gr.Error(
|
| 664 |
+
f"User '{name}' already exists. Please use the login form."
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
# Create the user before trying to build or load their indices.
|
| 668 |
+
memory[name] = {
|
| 669 |
+
"profile": {
|
| 670 |
+
"age": age,
|
| 671 |
+
"gender": gender,
|
| 672 |
+
"occupation": occupation,
|
| 673 |
+
"residence": residence,
|
| 674 |
+
},
|
| 675 |
+
"sessions": [],
|
| 676 |
+
"episodic_memory": [],
|
| 677 |
+
"semantic_memory": {},
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
try:
|
| 681 |
+
(
|
| 682 |
+
_,
|
| 683 |
+
user_memory,
|
| 684 |
+
sessions_memory,
|
| 685 |
+
episodic_memory,
|
| 686 |
+
semantic_memory,
|
| 687 |
+
) = enter_name_llamaindex(
|
| 688 |
+
name=name,
|
| 689 |
+
memory=memory,
|
| 690 |
+
data_args=data_args,
|
| 691 |
+
update_memory_index=True,
|
| 692 |
+
)
|
| 693 |
+
except Exception:
|
| 694 |
+
# Avoid leaving a partially registered user in memory.
|
| 695 |
+
memory.pop(name, None)
|
| 696 |
+
raise
|
| 697 |
+
|
| 698 |
+
new_state = dict(state or {})
|
| 699 |
+
new_state.update(
|
| 700 |
+
{
|
| 701 |
+
"user_name": name,
|
| 702 |
+
"memory": memory,
|
| 703 |
+
"initialized": True,
|
| 704 |
+
"history": [],
|
| 705 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 706 |
+
"user_memory_index": sessions_memory,
|
| 707 |
+
"episodic_memory_index": episodic_memory,
|
| 708 |
+
"semantic_memory_index": semantic_memory,
|
| 709 |
+
}
|
| 710 |
+
)
|
| 711 |
+
|
| 712 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 713 |
+
|
| 714 |
+
return (
|
| 715 |
+
gr.update(open=False),
|
| 716 |
+
gr.update(visible=False),
|
| 717 |
+
gr.update(visible=True),
|
| 718 |
+
gr.update(visible=False, value=""),
|
| 719 |
+
gr.update(
|
| 720 |
+
value=(
|
| 721 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 722 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 723 |
+
)
|
| 724 |
+
),
|
| 725 |
+
gr.update(value=welcome_msg),
|
| 726 |
+
new_state,
|
| 727 |
+
)
|
| 728 |
+
|
| 729 |
+
def switch_user(state):
|
| 730 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 731 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 732 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 733 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 734 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 735 |
+
# ==========================================
|
| 736 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 737 |
+
# ==========================================
|
| 738 |
+
try:
|
| 739 |
+
user_mem = state["memory"][state["user_name"]]
|
| 740 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 741 |
+
|
| 742 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 743 |
+
|
| 744 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 745 |
+
except Exception as e:
|
| 746 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 747 |
+
# ==========================================
|
| 748 |
+
|
| 749 |
+
new_state = state.copy()
|
| 750 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 751 |
+
|
| 752 |
+
return (
|
| 753 |
+
gr.update(open=True), # 1. باز شدن سایدبار
|
| 754 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام
|
| 755 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 756 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 757 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 758 |
+
new_state, # 6. استیت جدید
|
| 759 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 760 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 761 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 762 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 763 |
+
gr.update(value=""), # 11. پاک کردن residence_input
|
| 764 |
+
gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
|
| 768 |
+
def handle_chat(user_message, state):
|
| 769 |
+
if not user_message.strip():
|
| 770 |
+
print("[handle_chat] empty message")
|
| 771 |
+
print("[handle_chat] state =", state)
|
| 772 |
+
# تبدیل return به yield
|
| 773 |
+
yield gr.update(), state.get("history", []), state
|
| 774 |
+
return
|
| 775 |
+
|
| 776 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 777 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 778 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 779 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 780 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 781 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 782 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 783 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 784 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 785 |
+
|
| 786 |
+
# ==========================================
|
| 787 |
+
# ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
|
| 788 |
+
# ==========================================
|
| 789 |
+
current_history = state.get("history", [])
|
| 790 |
+
temp_history = current_history + [
|
| 791 |
+
{"role": "user", "content": user_message},
|
| 792 |
+
{"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
|
| 793 |
+
]
|
| 794 |
+
|
| 795 |
+
# باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI میفرستیم
|
| 796 |
+
yield gr.update(value=""), temp_history, state
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
# ادامه پردازشهای اصلی تابع شما
|
| 800 |
+
user_name = state.get("user_name")
|
| 801 |
+
user_memory_index = state.get("user_memory_index")
|
| 802 |
+
user_memory = state.get("user_memory", {})
|
| 803 |
+
user_memory_index = state.get("user_memory_index")
|
| 804 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 805 |
+
service_context = state.get("service_context")
|
| 806 |
+
api_index = state.get("api_index", 0)
|
| 807 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 808 |
+
|
| 809 |
+
# ==========================================
|
| 810 |
+
# استخراج پروفایل کاربر از حافظه
|
| 811 |
+
# ==========================================
|
| 812 |
+
user_profile = {}
|
| 813 |
+
if user_name and state.get("memory") and user_name in state["memory"]:
|
| 814 |
+
user_profile = state["memory"][user_name].get("profile", {})
|
| 815 |
+
# ==========================================
|
| 816 |
+
|
| 817 |
+
query_category = classify_query_local(user_message)
|
| 818 |
+
print("[handle_chat] query_category =", query_category)
|
| 819 |
+
|
| 820 |
+
# ارسال current_history به مدل (بدون انیمیشن موقت)
|
| 821 |
+
new_history, _, status_msg = predict_new(
|
| 822 |
+
text=user_message,
|
| 823 |
+
history=current_history,
|
| 824 |
+
top_p=0.95,
|
| 825 |
+
temperature=1.0,
|
| 826 |
+
max_length_tokens=1024,
|
| 827 |
+
max_context_length_tokens=4096,
|
| 828 |
+
user_name=user_name,
|
| 829 |
+
user_memory=user_memory,
|
| 830 |
+
user_memory_index=user_memory_index,
|
| 831 |
+
service_context=service_context,
|
| 832 |
+
api_index=api_index,
|
| 833 |
+
semantic_memory_text=semantic_memory_text,
|
| 834 |
+
query_category=query_category,
|
| 835 |
+
user_profile=user_profile
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 839 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 840 |
+
|
| 841 |
+
state["history"] = new_history
|
| 842 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 843 |
+
|
| 844 |
+
# ==========================================
|
| 845 |
+
# ۳. جایگزینی پیام لودینگ با پاسخ نهایی
|
| 846 |
+
# ==========================================
|
| 847 |
+
yield gr.update(), new_history, state
|
| 848 |
+
|
| 849 |
+
def clear_history(state):
|
| 850 |
+
state["history"] = []
|
| 851 |
+
return [], state
|
| 852 |
+
|
| 853 |
+
def handle_new_session(state):
|
| 854 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 855 |
+
user_name = state.get("user_name")
|
| 856 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 857 |
+
print("Error: User not logged in or memory missing.")
|
| 858 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 859 |
+
return [], state, gr.update() # خروجی سوم اضافه شد
|
| 860 |
+
|
| 861 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 862 |
+
user_data = state["memory"][user_name]
|
| 863 |
+
|
| 864 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 865 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 866 |
+
last_session = user_data["sessions"][-1]
|
| 867 |
+
|
| 868 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 869 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 870 |
+
session_date = last_session.get("date", "")
|
| 871 |
+
session_id = last_session.get("session_id", 0)
|
| 872 |
+
|
| 873 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 874 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 875 |
+
|
| 876 |
+
if "episodic_memory" not in user_data:
|
| 877 |
+
user_data["episodic_memory"] = []
|
| 878 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 879 |
+
|
| 880 |
+
# ==========================================
|
| 881 |
+
# بهروزرسانی حافظه سمانتیک
|
| 882 |
+
# ==========================================
|
| 883 |
+
try:
|
| 884 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 885 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 886 |
+
|
| 887 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 888 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 889 |
+
|
| 890 |
+
# ذخیره دیتای جدید
|
| 891 |
+
user_data["semantic_memory"] = updated_semantic
|
| 892 |
+
except Exception as e:
|
| 893 |
+
print(f"Error updating semantic memory: {e}")
|
| 894 |
+
# ==========================================
|
| 895 |
+
|
| 896 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 897 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 898 |
+
|
| 899 |
+
new_session = {
|
| 900 |
+
"session_id": new_session_id,
|
| 901 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 902 |
+
"conversation": []
|
| 903 |
+
}
|
| 904 |
+
|
| 905 |
+
if "sessions" not in user_data:
|
| 906 |
+
user_data["sessions"] = []
|
| 907 |
+
|
| 908 |
+
user_data["sessions"].append(new_session)
|
| 909 |
+
|
| 910 |
+
# پاک کردن تاریخچه چت در state
|
| 911 |
+
state["history"] = []
|
| 912 |
+
|
| 913 |
+
# محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
|
| 914 |
+
session_number = len(user_data["sessions"])
|
| 915 |
+
new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
|
| 916 |
+
|
| 917 |
+
# بازگرداندن خروجی جدید برای active_header
|
| 918 |
+
return [], state, gr.update(value=new_header_text)
|
| 919 |
+
|
| 920 |
+
check_user_btn.click(
|
| 921 |
+
handle_login_check,
|
| 922 |
+
inputs=[username_input, state],
|
| 923 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 924 |
+
# show_progress="hidden"
|
| 925 |
+
)
|
| 926 |
+
|
| 927 |
+
register_btn.click(
|
| 928 |
+
handle_register,
|
| 929 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 930 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 931 |
+
# show_progress="hidden"
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
switch_user_btn.click(
|
| 935 |
+
switch_user,
|
| 936 |
+
inputs=[state],
|
| 937 |
+
# system_msg به انتهای لیست خروجیها اضافه شد
|
| 938 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
|
| 939 |
+
# show_progress="hidden"
|
| 940 |
+
)
|
| 941 |
+
|
| 942 |
+
|
| 943 |
+
submit_btn.click(
|
| 944 |
+
handle_chat,
|
| 945 |
+
inputs=[user_input, state],
|
| 946 |
+
outputs=[user_input, chatbot, state],
|
| 947 |
+
# show_progress="hidden"
|
| 948 |
+
)
|
| 949 |
+
|
| 950 |
+
user_input.submit(
|
| 951 |
+
handle_chat,
|
| 952 |
+
inputs=[user_input, state],
|
| 953 |
+
outputs=[user_input, chatbot, state],
|
| 954 |
+
# show_progress="hidden"
|
| 955 |
+
)
|
| 956 |
+
|
| 957 |
+
clear_btn.click(
|
| 958 |
+
clear_history,
|
| 959 |
+
inputs=[state],
|
| 960 |
+
outputs=[chatbot, state],
|
| 961 |
+
# show_progress="hidden"
|
| 962 |
+
)
|
| 963 |
+
|
| 964 |
+
# تغییر از clear_history به handle_new_session
|
| 965 |
+
new_session_btn.click(
|
| 966 |
+
handle_new_session,
|
| 967 |
+
inputs=[state],
|
| 968 |
+
outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
|
| 969 |
+
# show_progress="hidden"
|
| 970 |
+
)
|
| 971 |
+
|
| 972 |
+
return demo
|
| 973 |
+
|
| 974 |
+
|
| 975 |
+
def main():
|
| 976 |
+
"""Main function to initialize and launch the interface."""
|
| 977 |
+
global api_keys
|
| 978 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 979 |
+
|
| 980 |
+
if not gapgpt_api_key:
|
| 981 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 982 |
+
else:
|
| 983 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 984 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 985 |
+
# ← این خط اضافه شد
|
| 986 |
+
if gapgpt_api_key not in api_keys:
|
| 987 |
+
api_keys.insert(0, gapgpt_api_key)
|
| 988 |
+
|
| 989 |
+
# تنظیم LLM (مدل زبانی)
|
| 990 |
+
llm = LlamaIndexOpenAI(
|
| 991 |
+
model="gpt-4o",
|
| 992 |
+
temperature=1,
|
| 993 |
+
max_tokens=1024,
|
| 994 |
+
top_p=0.95,
|
| 995 |
+
frequency_penalty=0.4,
|
| 996 |
+
presence_penalty=0.2,
|
| 997 |
+
api_key=gapgpt_api_key,
|
| 998 |
+
api_base=GAPGPT_BASE_URL,
|
| 999 |
+
)
|
| 1000 |
+
|
| 1001 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 1002 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 1003 |
+
embed_model = OpenAIEmbedding(
|
| 1004 |
+
api_key=gapgpt_api_key,
|
| 1005 |
+
api_base=GAPGPT_BASE_URL,
|
| 1006 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 1007 |
+
)
|
| 1008 |
+
|
| 1009 |
+
# اعمال تنظیمات سراسری
|
| 1010 |
+
Settings.llm = llm
|
| 1011 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 1012 |
+
|
| 1013 |
+
Settings.prompt_helper = PromptHelper(
|
| 1014 |
+
context_window=4096,
|
| 1015 |
+
num_output=256,
|
| 1016 |
+
chunk_overlap_ratio=20 / 4096,
|
| 1017 |
+
tokenizer=tokenizer,
|
| 1018 |
+
)
|
| 1019 |
+
|
| 1020 |
+
|
| 1021 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 1022 |
+
demo.launch(
|
| 1023 |
+
server_name="0.0.0.0",
|
| 1024 |
+
server_port=7860,
|
| 1025 |
+
share=False # در محیط داکر معمولاً share روی False تنظیم میشود مگر اینکه تونل نیاز داشته باشید
|
| 1026 |
+
)
|
| 1027 |
+
|
| 1028 |
+
|
| 1029 |
+
if __name__ == "__main__":
|
| 1030 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 1031 |
+
main()
|
Backup code/app_V2.py
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
|
| 13 |
+
import gradio as gr
|
| 14 |
+
import nltk
|
| 15 |
+
import torch
|
| 16 |
+
import tiktoken
|
| 17 |
+
|
| 18 |
+
from openai import OpenAI as OpenAIClient
|
| 19 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 20 |
+
|
| 21 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 22 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 23 |
+
from llama_index.core import Settings
|
| 24 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 25 |
+
|
| 26 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 27 |
+
sys.path.append(prompt_path)
|
| 28 |
+
|
| 29 |
+
# Assuming these imports exist in your local environment
|
| 30 |
+
from utils.sys_args import data_args, model_args
|
| 31 |
+
from utils.app_modules.utils import *
|
| 32 |
+
from utils.app_modules.presets import *
|
| 33 |
+
from utils.app_modules.overwrites import *
|
| 34 |
+
from utils.prompt_utils import *
|
| 35 |
+
from utils.memory_utils import (
|
| 36 |
+
enter_name_llamaindex,
|
| 37 |
+
summarize_memory_event_personality,
|
| 38 |
+
save_local_memory,
|
| 39 |
+
extract_session_summary,
|
| 40 |
+
extract_semantic_memory,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# Ensure NLTK data path
|
| 44 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 45 |
+
|
| 46 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 47 |
+
|
| 48 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 49 |
+
openai_client_cache = {}
|
| 50 |
+
|
| 51 |
+
import torch
|
| 52 |
+
import torch.nn.functional as F
|
| 53 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 57 |
+
|
| 58 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 59 |
+
|
| 60 |
+
try:
|
| 61 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 62 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model.eval()
|
| 64 |
+
print("Local classifier loaded successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Error loading local classifier: {e}")
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 70 |
+
if not api_key:
|
| 71 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 72 |
+
if api_key not in openai_client_cache:
|
| 73 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 74 |
+
return openai_client_cache[api_key]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
os_name = platform.system()
|
| 78 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 79 |
+
stop_stream = False
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def signal_handler(signal_number, frame):
|
| 83 |
+
global stop_stream
|
| 84 |
+
stop_stream = True
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 88 |
+
|
| 89 |
+
# Update this path to your actual file location
|
| 90 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def read_apis(path):
|
| 94 |
+
api_keys_local = []
|
| 95 |
+
if os.path.exists(path):
|
| 96 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 97 |
+
for line in f:
|
| 98 |
+
line = line.strip()
|
| 99 |
+
if line:
|
| 100 |
+
api_keys_local.append(line)
|
| 101 |
+
return api_keys_local
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 105 |
+
|
| 106 |
+
# Ensure directory exists
|
| 107 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 108 |
+
|
| 109 |
+
if not os.path.exists(memory_dir):
|
| 110 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 111 |
+
|
| 112 |
+
global memory
|
| 113 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 114 |
+
language = 'en'
|
| 115 |
+
user_keyword = generate_user_keyword()[language]
|
| 116 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 117 |
+
boot_name = boot_name_dict[language]
|
| 118 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 119 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 120 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 122 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 123 |
+
|
| 124 |
+
api_keys = read_apis(api_path)
|
| 125 |
+
# Fallback if file is empty or missing for testing purposes
|
| 126 |
+
if not api_keys:
|
| 127 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 128 |
+
|
| 129 |
+
new_conversation = False
|
| 130 |
+
chatgpt_config = {
|
| 131 |
+
"model": "gpt-4o",
|
| 132 |
+
"temperature": 1,
|
| 133 |
+
"max_tokens": 1024,
|
| 134 |
+
"top_p": 0.95,
|
| 135 |
+
"frequency_penalty": 0.4,
|
| 136 |
+
"presence_penalty": 0.2,
|
| 137 |
+
"n": 1,
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
deactivated_keys = []
|
| 141 |
+
logging.basicConfig(
|
| 142 |
+
level=logging.DEBUG,
|
| 143 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 148 |
+
"""
|
| 149 |
+
Handles the chat request to OpenAI.
|
| 150 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 151 |
+
"""
|
| 152 |
+
retry_times, count = 5, 0
|
| 153 |
+
response = None
|
| 154 |
+
|
| 155 |
+
while response is None and count < retry_times:
|
| 156 |
+
try:
|
| 157 |
+
request = copy.deepcopy(gpt_config)
|
| 158 |
+
|
| 159 |
+
# Initial system and greeting messages
|
| 160 |
+
if data_args.language == 'en':
|
| 161 |
+
message = [
|
| 162 |
+
{"role": "system", "content": system.strip()},
|
| 163 |
+
{"role": "user", "content": "Hi!"},
|
| 164 |
+
{"role": "assistant",
|
| 165 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 166 |
+
]
|
| 167 |
+
else:
|
| 168 |
+
message = [
|
| 169 |
+
{"role": "system", "content": system.strip()},
|
| 170 |
+
{"role": "user", "content": "Hi"},
|
| 171 |
+
{"role": "assistant",
|
| 172 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 173 |
+
]
|
| 174 |
+
|
| 175 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 176 |
+
if history:
|
| 177 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 178 |
+
if isinstance(history[0], list):
|
| 179 |
+
# Convert old format temporarily if encountered
|
| 180 |
+
for q, a in history:
|
| 181 |
+
message.append({"role": "user", "content": str(q)})
|
| 182 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 183 |
+
elif isinstance(history[0], dict):
|
| 184 |
+
# New format
|
| 185 |
+
for msg in history:
|
| 186 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 187 |
+
message.append(msg)
|
| 188 |
+
|
| 189 |
+
# Add the current prompt
|
| 190 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 191 |
+
|
| 192 |
+
if not api_keys:
|
| 193 |
+
return "Error: No API Keys available."
|
| 194 |
+
|
| 195 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 196 |
+
|
| 197 |
+
# New OpenAI 1.x Syntax
|
| 198 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 199 |
+
|
| 200 |
+
except Exception as e:
|
| 201 |
+
print(f"Chat Error: {e}")
|
| 202 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 203 |
+
deactivated_keys.append(api_keys[api_index])
|
| 204 |
+
|
| 205 |
+
if api_keys:
|
| 206 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 207 |
+
loop_check = 0
|
| 208 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 209 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 210 |
+
loop_check += 1
|
| 211 |
+
count += 1
|
| 212 |
+
|
| 213 |
+
if response:
|
| 214 |
+
response = response.choices[0].message.content
|
| 215 |
+
else:
|
| 216 |
+
response = ''
|
| 217 |
+
return response
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def classify_query_local(text):
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 224 |
+
id2label_map = {
|
| 225 |
+
0: "episodic_memory",
|
| 226 |
+
1: "semantic_memory",
|
| 227 |
+
2: "semantic-episodic",
|
| 228 |
+
3: "unknown"
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
try:
|
| 232 |
+
|
| 233 |
+
inputs = _tokenizer(
|
| 234 |
+
text,
|
| 235 |
+
return_tensors="pt",
|
| 236 |
+
truncation=True,
|
| 237 |
+
padding=True,
|
| 238 |
+
max_length=512
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
with torch.no_grad():
|
| 244 |
+
outputs = _classifier_model(**inputs)
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
logits = outputs.logits
|
| 248 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 249 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 253 |
+
|
| 254 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 255 |
+
return category
|
| 256 |
+
|
| 257 |
+
except Exception as e:
|
| 258 |
+
print(f"Error in local classification: {e}")
|
| 259 |
+
return "unknown"
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 264 |
+
response = None
|
| 265 |
+
count = 0
|
| 266 |
+
local_deactivated = []
|
| 267 |
+
print("text********:", text)
|
| 268 |
+
|
| 269 |
+
system_prompt = """
|
| 270 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 271 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 272 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 273 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 274 |
+
|
| 275 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 276 |
+
""".strip()
|
| 277 |
+
|
| 278 |
+
if not api_keys:
|
| 279 |
+
return "unknown"
|
| 280 |
+
|
| 281 |
+
while response is None and count < retry_times:
|
| 282 |
+
try:
|
| 283 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 284 |
+
|
| 285 |
+
# New OpenAI 1.x Syntax
|
| 286 |
+
response = client.chat.completions.create(
|
| 287 |
+
messages=[
|
| 288 |
+
{"role": "system", "content": system_prompt},
|
| 289 |
+
{"role": "user", "content": text.strip()},
|
| 290 |
+
],
|
| 291 |
+
**copy.deepcopy(gpt_config),
|
| 292 |
+
)
|
| 293 |
+
except Exception as e:
|
| 294 |
+
print(f"Classify Error: {e}")
|
| 295 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 296 |
+
local_deactivated.append(api_keys[api_index])
|
| 297 |
+
|
| 298 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 299 |
+
while api_keys[api_index] in local_deactivated:
|
| 300 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 301 |
+
count += 1
|
| 302 |
+
|
| 303 |
+
if response:
|
| 304 |
+
category = response.choices[0].message.content.strip().lower()
|
| 305 |
+
# Basic cleanup
|
| 306 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 307 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 308 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 309 |
+
else: category = "unknown"
|
| 310 |
+
else:
|
| 311 |
+
category = "unknown"
|
| 312 |
+
|
| 313 |
+
return category
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def predict_new(
|
| 317 |
+
text,
|
| 318 |
+
history,
|
| 319 |
+
top_p,
|
| 320 |
+
temperature,
|
| 321 |
+
max_length_tokens,
|
| 322 |
+
max_context_length_tokens,
|
| 323 |
+
user_name,
|
| 324 |
+
user_memory,
|
| 325 |
+
user_memory_index,
|
| 326 |
+
service_context,
|
| 327 |
+
api_index,
|
| 328 |
+
semantic_memory_text,
|
| 329 |
+
query_category,
|
| 330 |
+
):
|
| 331 |
+
chatgpt_cfg = {
|
| 332 |
+
"model": "gpt-4o",
|
| 333 |
+
"temperature": temperature,
|
| 334 |
+
"max_tokens": max_length_tokens,
|
| 335 |
+
"top_p": top_p,
|
| 336 |
+
"frequency_penalty": 0.4,
|
| 337 |
+
"presence_penalty": 0.2,
|
| 338 |
+
"n": 1,
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
if text == "":
|
| 342 |
+
# Return same history if empty input
|
| 343 |
+
return history, history, "Empty context."
|
| 344 |
+
|
| 345 |
+
# Ensure history is initialized
|
| 346 |
+
if history is None:
|
| 347 |
+
history = []
|
| 348 |
+
|
| 349 |
+
system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
|
| 350 |
+
history=history,
|
| 351 |
+
query=text, # Changed name to match prompt_utils
|
| 352 |
+
user_memory=user_memory,
|
| 353 |
+
user_name=user_name,
|
| 354 |
+
user_memory_index=user_memory_index,
|
| 355 |
+
service_context=service_context,
|
| 356 |
+
api_keys=api_keys,
|
| 357 |
+
api_index=api_index,
|
| 358 |
+
meta_prompt=meta_prompt,
|
| 359 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 360 |
+
data_args=data_args,
|
| 361 |
+
boot_actual_name=boot_actual_name,
|
| 362 |
+
semantic_memory_text=semantic_memory_text,
|
| 363 |
+
query_category=query_category,
|
| 364 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 365 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# Handle context window slicing manually if needed,
|
| 369 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 370 |
+
current_history_for_llm = history
|
| 371 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 372 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 373 |
+
|
| 374 |
+
response = chatgpt_chat(
|
| 375 |
+
prompt=text,
|
| 376 |
+
system=system_prompt,
|
| 377 |
+
history=current_history_for_llm,
|
| 378 |
+
gpt_config=chatgpt_cfg,
|
| 379 |
+
api_index=api_index,
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
torch.cuda.empty_cache()
|
| 383 |
+
|
| 384 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 385 |
+
new_history = history + [
|
| 386 |
+
{"role": "user", "content": text},
|
| 387 |
+
{"role": "assistant", "content": response}
|
| 388 |
+
]
|
| 389 |
+
|
| 390 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 391 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 392 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 393 |
+
if user_name:
|
| 394 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 395 |
+
# or pass a converted version. Let's try passing the new format.
|
| 396 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 397 |
+
|
| 398 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 399 |
+
return new_history, new_history, "Generating..."
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
import gradio as gr
|
| 403 |
+
import time
|
| 404 |
+
|
| 405 |
+
import gradio as gr
|
| 406 |
+
|
| 407 |
+
def create_gradio_interface(service_context, api_keys):
|
| 408 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 409 |
+
|
| 410 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 411 |
+
gr.HTML("""
|
| 412 |
+
<style>
|
| 413 |
+
.center-content {
|
| 414 |
+
display: flex;
|
| 415 |
+
flex-direction: column;
|
| 416 |
+
align-items: center;
|
| 417 |
+
justify-content: center;
|
| 418 |
+
}
|
| 419 |
+
/* -- استایلهای فرم ورود -- */
|
| 420 |
+
.login-box {
|
| 421 |
+
max-width: 400px !important;
|
| 422 |
+
margin: 0 auto !important;
|
| 423 |
+
width: 100% !important;
|
| 424 |
+
}
|
| 425 |
+
.login-btn, .login-btn:hover {
|
| 426 |
+
background-color: #3498db !important;
|
| 427 |
+
background-image: none !important;
|
| 428 |
+
color: white !important;
|
| 429 |
+
border: none !important;
|
| 430 |
+
}
|
| 431 |
+
/* -- استایلهای محیط چت -- */
|
| 432 |
+
.chat-box {
|
| 433 |
+
max-width: 800px !important;
|
| 434 |
+
margin: 0 auto !important;
|
| 435 |
+
width: 100% !important;
|
| 436 |
+
}
|
| 437 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 438 |
+
.mobile-button, .mobile-button:hover {
|
| 439 |
+
background-color: #3498db !important;
|
| 440 |
+
background-image: none !important;
|
| 441 |
+
color: white !important;
|
| 442 |
+
border: none !important;
|
| 443 |
+
}
|
| 444 |
+
.gr-textbox textarea {
|
| 445 |
+
font-size: 16px;
|
| 446 |
+
}
|
| 447 |
+
.gr-chatbot {
|
| 448 |
+
font-size: 15px;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 452 |
+
.slide-up {
|
| 453 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
@keyframes slideUpAnimation {
|
| 457 |
+
0% {
|
| 458 |
+
transform: translateY(0);
|
| 459 |
+
opacity: 1;
|
| 460 |
+
max-height: 1000px;
|
| 461 |
+
}
|
| 462 |
+
100% {
|
| 463 |
+
transform: translateY(-100%);
|
| 464 |
+
opacity: 0;
|
| 465 |
+
max-height: 0px;
|
| 466 |
+
overflow: hidden;
|
| 467 |
+
margin: 0 !important;
|
| 468 |
+
padding: 0 !important;
|
| 469 |
+
border: none !important;
|
| 470 |
+
}
|
| 471 |
+
}
|
| 472 |
+
</style>
|
| 473 |
+
""")
|
| 474 |
+
|
| 475 |
+
state = gr.State({
|
| 476 |
+
"history": [],
|
| 477 |
+
"user_name": None,
|
| 478 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 479 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 480 |
+
"service_context": service_context,
|
| 481 |
+
"api_keys": api_keys,
|
| 482 |
+
"api_index": 0,
|
| 483 |
+
"semantic_memory_text": "",
|
| 484 |
+
"new_conversation": True,
|
| 485 |
+
"initialized": False
|
| 486 |
+
})
|
| 487 |
+
|
| 488 |
+
# ==========================================
|
| 489 |
+
# 1. LOGIN PAGE
|
| 490 |
+
# ==========================================
|
| 491 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 492 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 493 |
+
|
| 494 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 495 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 496 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 497 |
+
|
| 498 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 499 |
+
|
| 500 |
+
with gr.Column(visible=False) as registration_fields:
|
| 501 |
+
gr.Markdown("### ✨ New User Registration")
|
| 502 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 503 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 504 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 505 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 506 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 507 |
+
|
| 508 |
+
# ==========================================
|
| 509 |
+
# 2. CHAT PAGE
|
| 510 |
+
# ==========================================
|
| 511 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 512 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 513 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 514 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 515 |
+
|
| 516 |
+
with gr.Group():
|
| 517 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 518 |
+
|
| 519 |
+
with gr.Row():
|
| 520 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 521 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 522 |
+
|
| 523 |
+
with gr.Row(equal_height=True):
|
| 524 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 525 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 526 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 527 |
+
|
| 528 |
+
# -------------------------------------------------------
|
| 529 |
+
# Internal Functions
|
| 530 |
+
# -------------------------------------------------------
|
| 531 |
+
def handle_login_check(name, state):
|
| 532 |
+
if not name.strip():
|
| 533 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 534 |
+
|
| 535 |
+
if name in memory:
|
| 536 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 537 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 538 |
+
|
| 539 |
+
new_state = state.copy()
|
| 540 |
+
new_state["user_name"] = name
|
| 541 |
+
new_state["memory"] = memory
|
| 542 |
+
new_state["initialized"] = True
|
| 543 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 544 |
+
new_state["history"] = []
|
| 545 |
+
|
| 546 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 547 |
+
|
| 548 |
+
return (
|
| 549 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 550 |
+
gr.update(visible=False),
|
| 551 |
+
gr.update(visible=True),
|
| 552 |
+
gr.update(visible=False, value=""),
|
| 553 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 554 |
+
gr.update(value=welcome_msg),
|
| 555 |
+
new_state
|
| 556 |
+
)
|
| 557 |
+
else:
|
| 558 |
+
return (
|
| 559 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 560 |
+
gr.update(visible=True),
|
| 561 |
+
gr.update(visible=False),
|
| 562 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 563 |
+
gr.update(),
|
| 564 |
+
gr.update(),
|
| 565 |
+
state
|
| 566 |
+
)
|
| 567 |
+
|
| 568 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 569 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 570 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 571 |
+
|
| 572 |
+
new_state = state.copy()
|
| 573 |
+
new_state["user_name"] = name
|
| 574 |
+
new_state["memory"] = memory
|
| 575 |
+
new_state["initialized"] = True
|
| 576 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 577 |
+
new_state["history"] = []
|
| 578 |
+
|
| 579 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 580 |
+
|
| 581 |
+
return (
|
| 582 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
|
| 583 |
+
gr.update(visible=False),
|
| 584 |
+
gr.update(visible=True),
|
| 585 |
+
gr.update(visible=False, value=""),
|
| 586 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 587 |
+
gr.update(value=welcome_msg),
|
| 588 |
+
new_state
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
def switch_user(state):
|
| 592 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 593 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 594 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 595 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 596 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 597 |
+
|
| 598 |
+
new_state = state.copy()
|
| 599 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 600 |
+
|
| 601 |
+
return (
|
| 602 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 603 |
+
gr.update(visible=False),
|
| 604 |
+
gr.update(visible=False),
|
| 605 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 606 |
+
gr.update(value=""),
|
| 607 |
+
new_state,
|
| 608 |
+
gr.update(value=[])
|
| 609 |
+
)
|
| 610 |
+
|
| 611 |
+
def handle_chat(user_message, state):
|
| 612 |
+
if not user_message.strip():
|
| 613 |
+
return gr.update(), state.get("history", []), state
|
| 614 |
+
|
| 615 |
+
user_name = state.get("user_name")
|
| 616 |
+
user_memory = state.get("memory")
|
| 617 |
+
service_context = state.get("service_context")
|
| 618 |
+
api_index = state.get("api_index", 0)
|
| 619 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 620 |
+
|
| 621 |
+
query_category = classify_query_local(user_message)
|
| 622 |
+
|
| 623 |
+
new_history, _, status_msg = predict_new(
|
| 624 |
+
text=user_message,
|
| 625 |
+
history=state.get("history", []),
|
| 626 |
+
top_p=0.95,
|
| 627 |
+
temperature=1.0,
|
| 628 |
+
max_length_tokens=1024,
|
| 629 |
+
max_context_length_tokens=4096,
|
| 630 |
+
user_name=user_name,
|
| 631 |
+
user_memory=user_memory,
|
| 632 |
+
user_memory_index=None,
|
| 633 |
+
service_context=service_context,
|
| 634 |
+
api_index=api_index,
|
| 635 |
+
semantic_memory_text=semantic_memory_text,
|
| 636 |
+
query_category=query_category
|
| 637 |
+
)
|
| 638 |
+
|
| 639 |
+
state["history"] = new_history
|
| 640 |
+
return "", new_history, state
|
| 641 |
+
|
| 642 |
+
def clear_history(state):
|
| 643 |
+
state["history"] = []
|
| 644 |
+
return [], state
|
| 645 |
+
|
| 646 |
+
# -------------------------------------------------------
|
| 647 |
+
# Event Bindings
|
| 648 |
+
# -------------------------------------------------------
|
| 649 |
+
check_user_btn.click(
|
| 650 |
+
handle_login_check,
|
| 651 |
+
inputs=[username_input, state],
|
| 652 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
register_btn.click(
|
| 656 |
+
handle_register,
|
| 657 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 658 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 659 |
+
)
|
| 660 |
+
|
| 661 |
+
switch_user_btn.click(
|
| 662 |
+
switch_user,
|
| 663 |
+
inputs=[state],
|
| 664 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
submit_btn.click(
|
| 668 |
+
handle_chat,
|
| 669 |
+
inputs=[user_input, state],
|
| 670 |
+
outputs=[user_input, chatbot, state]
|
| 671 |
+
)
|
| 672 |
+
|
| 673 |
+
user_input.submit(
|
| 674 |
+
handle_chat,
|
| 675 |
+
inputs=[user_input, state],
|
| 676 |
+
outputs=[user_input, chatbot, state]
|
| 677 |
+
)
|
| 678 |
+
|
| 679 |
+
clear_btn.click(
|
| 680 |
+
clear_history,
|
| 681 |
+
inputs=[state],
|
| 682 |
+
outputs=[chatbot, state]
|
| 683 |
+
)
|
| 684 |
+
|
| 685 |
+
new_session_btn.click(
|
| 686 |
+
clear_history,
|
| 687 |
+
inputs=[state],
|
| 688 |
+
outputs=[chatbot, state]
|
| 689 |
+
)
|
| 690 |
+
|
| 691 |
+
return demo
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
def main():
|
| 695 |
+
"""Main function to initialize and launch the interface."""
|
| 696 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 697 |
+
|
| 698 |
+
if not gapgpt_api_key:
|
| 699 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 700 |
+
else:
|
| 701 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 702 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 703 |
+
|
| 704 |
+
# تنظیم LLM (مدل زبانی)
|
| 705 |
+
llm = LlamaIndexOpenAI(
|
| 706 |
+
model="gpt-4o",
|
| 707 |
+
temperature=1,
|
| 708 |
+
max_tokens=1024,
|
| 709 |
+
top_p=0.95,
|
| 710 |
+
frequency_penalty=0.4,
|
| 711 |
+
presence_penalty=0.2,
|
| 712 |
+
api_key=gapgpt_api_key,
|
| 713 |
+
api_base=GAPGPT_BASE_URL,
|
| 714 |
+
)
|
| 715 |
+
|
| 716 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 717 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 718 |
+
embed_model = OpenAIEmbedding(
|
| 719 |
+
api_key=gapgpt_api_key,
|
| 720 |
+
api_base=GAPGPT_BASE_URL,
|
| 721 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 722 |
+
)
|
| 723 |
+
|
| 724 |
+
# اعمال تنظیمات سراسری
|
| 725 |
+
Settings.llm = llm
|
| 726 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 727 |
+
|
| 728 |
+
Settings.prompt_helper = PromptHelper(
|
| 729 |
+
context_window=4096,
|
| 730 |
+
num_output=256,
|
| 731 |
+
chunk_overlap_ratio=20 / 4096,
|
| 732 |
+
tokenizer=tokenizer,
|
| 733 |
+
)
|
| 734 |
+
|
| 735 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 736 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 737 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 738 |
+
if 'api_keys' not in locals():
|
| 739 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 740 |
+
|
| 741 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 742 |
+
demo.launch(
|
| 743 |
+
server_name="127.0.0.1",
|
| 744 |
+
server_port=7860,
|
| 745 |
+
share=True
|
| 746 |
+
)
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
if __name__ == "__main__":
|
| 750 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 751 |
+
main()
|
Backup code/app_V3.py
ADDED
|
@@ -0,0 +1,751 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
|
| 13 |
+
import gradio as gr
|
| 14 |
+
import nltk
|
| 15 |
+
import torch
|
| 16 |
+
import tiktoken
|
| 17 |
+
|
| 18 |
+
from openai import OpenAI as OpenAIClient
|
| 19 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 20 |
+
|
| 21 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 22 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 23 |
+
from llama_index.core import Settings
|
| 24 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 25 |
+
|
| 26 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 27 |
+
sys.path.append(prompt_path)
|
| 28 |
+
|
| 29 |
+
# Assuming these imports exist in your local environment
|
| 30 |
+
from utils.sys_args import data_args, model_args
|
| 31 |
+
from utils.app_modules.utils import *
|
| 32 |
+
from utils.app_modules.presets import *
|
| 33 |
+
from utils.app_modules.overwrites import *
|
| 34 |
+
from utils.prompt_utils import *
|
| 35 |
+
from utils.memory_utils import (
|
| 36 |
+
enter_name_llamaindex,
|
| 37 |
+
summarize_memory_event_personality,
|
| 38 |
+
save_local_memory,
|
| 39 |
+
extract_session_summary,
|
| 40 |
+
extract_semantic_memory,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# Ensure NLTK data path
|
| 44 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 45 |
+
|
| 46 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 47 |
+
|
| 48 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 49 |
+
openai_client_cache = {}
|
| 50 |
+
|
| 51 |
+
import torch
|
| 52 |
+
import torch.nn.functional as F
|
| 53 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 57 |
+
|
| 58 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 59 |
+
|
| 60 |
+
try:
|
| 61 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 62 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model.eval()
|
| 64 |
+
print("Local classifier loaded successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Error loading local classifier: {e}")
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 70 |
+
if not api_key:
|
| 71 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 72 |
+
if api_key not in openai_client_cache:
|
| 73 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 74 |
+
return openai_client_cache[api_key]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
os_name = platform.system()
|
| 78 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 79 |
+
stop_stream = False
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def signal_handler(signal_number, frame):
|
| 83 |
+
global stop_stream
|
| 84 |
+
stop_stream = True
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 88 |
+
|
| 89 |
+
# Update this path to your actual file location
|
| 90 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def read_apis(path):
|
| 94 |
+
api_keys_local = []
|
| 95 |
+
if os.path.exists(path):
|
| 96 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 97 |
+
for line in f:
|
| 98 |
+
line = line.strip()
|
| 99 |
+
if line:
|
| 100 |
+
api_keys_local.append(line)
|
| 101 |
+
return api_keys_local
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 105 |
+
|
| 106 |
+
# Ensure directory exists
|
| 107 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 108 |
+
|
| 109 |
+
if not os.path.exists(memory_dir):
|
| 110 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 111 |
+
|
| 112 |
+
global memory
|
| 113 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 114 |
+
language = 'en'
|
| 115 |
+
user_keyword = generate_user_keyword()[language]
|
| 116 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 117 |
+
boot_name = boot_name_dict[language]
|
| 118 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 119 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 120 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 122 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 123 |
+
|
| 124 |
+
api_keys = read_apis(api_path)
|
| 125 |
+
# Fallback if file is empty or missing for testing purposes
|
| 126 |
+
if not api_keys:
|
| 127 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 128 |
+
|
| 129 |
+
new_conversation = False
|
| 130 |
+
chatgpt_config = {
|
| 131 |
+
"model": "gpt-4o",
|
| 132 |
+
"temperature": 1,
|
| 133 |
+
"max_tokens": 1024,
|
| 134 |
+
"top_p": 0.95,
|
| 135 |
+
"frequency_penalty": 0.4,
|
| 136 |
+
"presence_penalty": 0.2,
|
| 137 |
+
"n": 1,
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
deactivated_keys = []
|
| 141 |
+
logging.basicConfig(
|
| 142 |
+
level=logging.DEBUG,
|
| 143 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 148 |
+
"""
|
| 149 |
+
Handles the chat request to OpenAI.
|
| 150 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 151 |
+
"""
|
| 152 |
+
retry_times, count = 5, 0
|
| 153 |
+
response = None
|
| 154 |
+
|
| 155 |
+
while response is None and count < retry_times:
|
| 156 |
+
try:
|
| 157 |
+
request = copy.deepcopy(gpt_config)
|
| 158 |
+
|
| 159 |
+
# Initial system and greeting messages
|
| 160 |
+
if data_args.language == 'en':
|
| 161 |
+
message = [
|
| 162 |
+
{"role": "system", "content": system.strip()},
|
| 163 |
+
{"role": "user", "content": "Hi!"},
|
| 164 |
+
{"role": "assistant",
|
| 165 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 166 |
+
]
|
| 167 |
+
else:
|
| 168 |
+
message = [
|
| 169 |
+
{"role": "system", "content": system.strip()},
|
| 170 |
+
{"role": "user", "content": "Hi"},
|
| 171 |
+
{"role": "assistant",
|
| 172 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 173 |
+
]
|
| 174 |
+
|
| 175 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 176 |
+
if history:
|
| 177 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 178 |
+
if isinstance(history[0], list):
|
| 179 |
+
# Convert old format temporarily if encountered
|
| 180 |
+
for q, a in history:
|
| 181 |
+
message.append({"role": "user", "content": str(q)})
|
| 182 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 183 |
+
elif isinstance(history[0], dict):
|
| 184 |
+
# New format
|
| 185 |
+
for msg in history:
|
| 186 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 187 |
+
message.append(msg)
|
| 188 |
+
|
| 189 |
+
# Add the current prompt
|
| 190 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 191 |
+
|
| 192 |
+
if not api_keys:
|
| 193 |
+
return "Error: No API Keys available."
|
| 194 |
+
|
| 195 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 196 |
+
|
| 197 |
+
# New OpenAI 1.x Syntax
|
| 198 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 199 |
+
|
| 200 |
+
except Exception as e:
|
| 201 |
+
print(f"Chat Error: {e}")
|
| 202 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 203 |
+
deactivated_keys.append(api_keys[api_index])
|
| 204 |
+
|
| 205 |
+
if api_keys:
|
| 206 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 207 |
+
loop_check = 0
|
| 208 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 209 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 210 |
+
loop_check += 1
|
| 211 |
+
count += 1
|
| 212 |
+
|
| 213 |
+
if response:
|
| 214 |
+
response = response.choices[0].message.content
|
| 215 |
+
else:
|
| 216 |
+
response = ''
|
| 217 |
+
return response
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def classify_query_local(text):
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 224 |
+
id2label_map = {
|
| 225 |
+
0: "episodic_memory",
|
| 226 |
+
1: "semantic_memory",
|
| 227 |
+
2: "semantic-episodic",
|
| 228 |
+
3: "unknown"
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
try:
|
| 232 |
+
|
| 233 |
+
inputs = _tokenizer(
|
| 234 |
+
text,
|
| 235 |
+
return_tensors="pt",
|
| 236 |
+
truncation=True,
|
| 237 |
+
padding=True,
|
| 238 |
+
max_length=512
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
with torch.no_grad():
|
| 244 |
+
outputs = _classifier_model(**inputs)
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
logits = outputs.logits
|
| 248 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 249 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 253 |
+
|
| 254 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 255 |
+
return category
|
| 256 |
+
|
| 257 |
+
except Exception as e:
|
| 258 |
+
print(f"Error in local classification: {e}")
|
| 259 |
+
return "unknown"
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 264 |
+
response = None
|
| 265 |
+
count = 0
|
| 266 |
+
local_deactivated = []
|
| 267 |
+
print("text********:", text)
|
| 268 |
+
|
| 269 |
+
system_prompt = """
|
| 270 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 271 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 272 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 273 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 274 |
+
|
| 275 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 276 |
+
""".strip()
|
| 277 |
+
|
| 278 |
+
if not api_keys:
|
| 279 |
+
return "unknown"
|
| 280 |
+
|
| 281 |
+
while response is None and count < retry_times:
|
| 282 |
+
try:
|
| 283 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 284 |
+
|
| 285 |
+
# New OpenAI 1.x Syntax
|
| 286 |
+
response = client.chat.completions.create(
|
| 287 |
+
messages=[
|
| 288 |
+
{"role": "system", "content": system_prompt},
|
| 289 |
+
{"role": "user", "content": text.strip()},
|
| 290 |
+
],
|
| 291 |
+
**copy.deepcopy(gpt_config),
|
| 292 |
+
)
|
| 293 |
+
except Exception as e:
|
| 294 |
+
print(f"Classify Error: {e}")
|
| 295 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 296 |
+
local_deactivated.append(api_keys[api_index])
|
| 297 |
+
|
| 298 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 299 |
+
while api_keys[api_index] in local_deactivated:
|
| 300 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 301 |
+
count += 1
|
| 302 |
+
|
| 303 |
+
if response:
|
| 304 |
+
category = response.choices[0].message.content.strip().lower()
|
| 305 |
+
# Basic cleanup
|
| 306 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 307 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 308 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 309 |
+
else: category = "unknown"
|
| 310 |
+
else:
|
| 311 |
+
category = "unknown"
|
| 312 |
+
|
| 313 |
+
return category
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def predict_new(
|
| 317 |
+
text,
|
| 318 |
+
history,
|
| 319 |
+
top_p,
|
| 320 |
+
temperature,
|
| 321 |
+
max_length_tokens,
|
| 322 |
+
max_context_length_tokens,
|
| 323 |
+
user_name,
|
| 324 |
+
user_memory,
|
| 325 |
+
user_memory_index,
|
| 326 |
+
service_context,
|
| 327 |
+
api_index,
|
| 328 |
+
semantic_memory_text,
|
| 329 |
+
query_category,
|
| 330 |
+
):
|
| 331 |
+
chatgpt_cfg = {
|
| 332 |
+
"model": "gpt-4o",
|
| 333 |
+
"temperature": temperature,
|
| 334 |
+
"max_tokens": max_length_tokens,
|
| 335 |
+
"top_p": top_p,
|
| 336 |
+
"frequency_penalty": 0.4,
|
| 337 |
+
"presence_penalty": 0.2,
|
| 338 |
+
"n": 1,
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
if text == "":
|
| 342 |
+
# Return same history if empty input
|
| 343 |
+
return history, history, "Empty context."
|
| 344 |
+
|
| 345 |
+
# Ensure history is initialized
|
| 346 |
+
if history is None:
|
| 347 |
+
history = []
|
| 348 |
+
|
| 349 |
+
system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
|
| 350 |
+
history=history,
|
| 351 |
+
query=text, # Changed name to match prompt_utils
|
| 352 |
+
user_memory=user_memory,
|
| 353 |
+
user_name=user_name,
|
| 354 |
+
user_memory_index=user_memory_index,
|
| 355 |
+
service_context=service_context,
|
| 356 |
+
api_keys=api_keys,
|
| 357 |
+
api_index=api_index,
|
| 358 |
+
meta_prompt=meta_prompt,
|
| 359 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 360 |
+
data_args=data_args,
|
| 361 |
+
boot_actual_name=boot_actual_name,
|
| 362 |
+
semantic_memory_text=semantic_memory_text,
|
| 363 |
+
query_category=query_category,
|
| 364 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 365 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# Handle context window slicing manually if needed,
|
| 369 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 370 |
+
current_history_for_llm = history
|
| 371 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 372 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 373 |
+
|
| 374 |
+
response = chatgpt_chat(
|
| 375 |
+
prompt=text,
|
| 376 |
+
system=system_prompt,
|
| 377 |
+
history=current_history_for_llm,
|
| 378 |
+
gpt_config=chatgpt_cfg,
|
| 379 |
+
api_index=api_index,
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
torch.cuda.empty_cache()
|
| 383 |
+
|
| 384 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 385 |
+
new_history = history + [
|
| 386 |
+
{"role": "user", "content": text},
|
| 387 |
+
{"role": "assistant", "content": response}
|
| 388 |
+
]
|
| 389 |
+
|
| 390 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 391 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 392 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 393 |
+
if user_name:
|
| 394 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 395 |
+
# or pass a converted version. Let's try passing the new format.
|
| 396 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 397 |
+
|
| 398 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 399 |
+
return new_history, new_history, "Generating..."
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
import gradio as gr
|
| 403 |
+
import time
|
| 404 |
+
|
| 405 |
+
import gradio as gr
|
| 406 |
+
|
| 407 |
+
def create_gradio_interface(service_context, api_keys):
|
| 408 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 409 |
+
|
| 410 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 411 |
+
gr.HTML("""
|
| 412 |
+
<style>
|
| 413 |
+
.center-content {
|
| 414 |
+
display: flex;
|
| 415 |
+
flex-direction: column;
|
| 416 |
+
align-items: center;
|
| 417 |
+
justify-content: center;
|
| 418 |
+
}
|
| 419 |
+
/* -- استایلهای فرم ورود -- */
|
| 420 |
+
.login-box {
|
| 421 |
+
max-width: 400px !important;
|
| 422 |
+
margin: 0 auto !important;
|
| 423 |
+
width: 100% !important;
|
| 424 |
+
}
|
| 425 |
+
.login-btn, .login-btn:hover {
|
| 426 |
+
background-color: #3498db !important;
|
| 427 |
+
background-image: none !important;
|
| 428 |
+
color: white !important;
|
| 429 |
+
border: none !important;
|
| 430 |
+
}
|
| 431 |
+
/* -- استایلهای محیط چت -- */
|
| 432 |
+
.chat-box {
|
| 433 |
+
max-width: 800px !important;
|
| 434 |
+
margin: 0 auto !important;
|
| 435 |
+
width: 100% !important;
|
| 436 |
+
}
|
| 437 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 438 |
+
.mobile-button, .mobile-button:hover {
|
| 439 |
+
background-color: #3498db !important;
|
| 440 |
+
background-image: none !important;
|
| 441 |
+
color: white !important;
|
| 442 |
+
border: none !important;
|
| 443 |
+
}
|
| 444 |
+
.gr-textbox textarea {
|
| 445 |
+
font-size: 16px;
|
| 446 |
+
}
|
| 447 |
+
.gr-chatbot {
|
| 448 |
+
font-size: 15px;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 452 |
+
.slide-up {
|
| 453 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
@keyframes slideUpAnimation {
|
| 457 |
+
0% {
|
| 458 |
+
transform: translateY(0);
|
| 459 |
+
opacity: 1;
|
| 460 |
+
max-height: 1000px;
|
| 461 |
+
}
|
| 462 |
+
100% {
|
| 463 |
+
transform: translateY(-100%);
|
| 464 |
+
opacity: 0;
|
| 465 |
+
max-height: 0px;
|
| 466 |
+
overflow: hidden;
|
| 467 |
+
margin: 0 !important;
|
| 468 |
+
padding: 0 !important;
|
| 469 |
+
border: none !important;
|
| 470 |
+
}
|
| 471 |
+
}
|
| 472 |
+
</style>
|
| 473 |
+
""")
|
| 474 |
+
|
| 475 |
+
state = gr.State({
|
| 476 |
+
"history": [],
|
| 477 |
+
"user_name": None,
|
| 478 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 479 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 480 |
+
"service_context": service_context,
|
| 481 |
+
"api_keys": api_keys,
|
| 482 |
+
"api_index": 0,
|
| 483 |
+
"semantic_memory_text": "",
|
| 484 |
+
"new_conversation": True,
|
| 485 |
+
"initialized": False
|
| 486 |
+
})
|
| 487 |
+
|
| 488 |
+
# ==========================================
|
| 489 |
+
# 1. LOGIN PAGE
|
| 490 |
+
# ==========================================
|
| 491 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 492 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 493 |
+
|
| 494 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 495 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 496 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 497 |
+
|
| 498 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 499 |
+
|
| 500 |
+
with gr.Column(visible=False) as registration_fields:
|
| 501 |
+
gr.Markdown("### ✨ New User Registration")
|
| 502 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 503 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 504 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 505 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 506 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 507 |
+
|
| 508 |
+
# ==========================================
|
| 509 |
+
# 2. CHAT PAGE
|
| 510 |
+
# ==========================================
|
| 511 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 512 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 513 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 514 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 515 |
+
|
| 516 |
+
with gr.Group():
|
| 517 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 518 |
+
|
| 519 |
+
with gr.Row():
|
| 520 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 521 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 522 |
+
|
| 523 |
+
with gr.Row(equal_height=True):
|
| 524 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 525 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 526 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 527 |
+
|
| 528 |
+
# -------------------------------------------------------
|
| 529 |
+
# Internal Functions
|
| 530 |
+
# -------------------------------------------------------
|
| 531 |
+
def handle_login_check(name, state):
|
| 532 |
+
if not name.strip():
|
| 533 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 534 |
+
|
| 535 |
+
if name in memory:
|
| 536 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 537 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 538 |
+
|
| 539 |
+
new_state = state.copy()
|
| 540 |
+
new_state["user_name"] = name
|
| 541 |
+
new_state["memory"] = memory
|
| 542 |
+
new_state["initialized"] = True
|
| 543 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 544 |
+
new_state["history"] = []
|
| 545 |
+
|
| 546 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 547 |
+
|
| 548 |
+
return (
|
| 549 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 550 |
+
gr.update(visible=False),
|
| 551 |
+
gr.update(visible=True),
|
| 552 |
+
gr.update(visible=False, value=""),
|
| 553 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 554 |
+
gr.update(value=welcome_msg),
|
| 555 |
+
new_state
|
| 556 |
+
)
|
| 557 |
+
else:
|
| 558 |
+
return (
|
| 559 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 560 |
+
gr.update(visible=True),
|
| 561 |
+
gr.update(visible=False),
|
| 562 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 563 |
+
gr.update(),
|
| 564 |
+
gr.update(),
|
| 565 |
+
state
|
| 566 |
+
)
|
| 567 |
+
|
| 568 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 569 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 570 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 571 |
+
|
| 572 |
+
new_state = state.copy()
|
| 573 |
+
new_state["user_name"] = name
|
| 574 |
+
new_state["memory"] = memory
|
| 575 |
+
new_state["initialized"] = True
|
| 576 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 577 |
+
new_state["history"] = []
|
| 578 |
+
|
| 579 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 580 |
+
|
| 581 |
+
return (
|
| 582 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
|
| 583 |
+
gr.update(visible=False),
|
| 584 |
+
gr.update(visible=True),
|
| 585 |
+
gr.update(visible=False, value=""),
|
| 586 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 587 |
+
gr.update(value=welcome_msg),
|
| 588 |
+
new_state
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
def switch_user(state):
|
| 592 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 593 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 594 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 595 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 596 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 597 |
+
|
| 598 |
+
new_state = state.copy()
|
| 599 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 600 |
+
|
| 601 |
+
return (
|
| 602 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 603 |
+
gr.update(visible=False),
|
| 604 |
+
gr.update(visible=False),
|
| 605 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 606 |
+
gr.update(value=""),
|
| 607 |
+
new_state,
|
| 608 |
+
gr.update(value=[])
|
| 609 |
+
)
|
| 610 |
+
|
| 611 |
+
def handle_chat(user_message, state):
|
| 612 |
+
if not user_message.strip():
|
| 613 |
+
return gr.update(), state.get("history", []), state
|
| 614 |
+
|
| 615 |
+
user_name = state.get("user_name")
|
| 616 |
+
user_memory = state.get("memory")
|
| 617 |
+
service_context = state.get("service_context")
|
| 618 |
+
api_index = state.get("api_index", 0)
|
| 619 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 620 |
+
|
| 621 |
+
query_category = classify_query_local(user_message)
|
| 622 |
+
|
| 623 |
+
new_history, _, status_msg = predict_new(
|
| 624 |
+
text=user_message,
|
| 625 |
+
history=state.get("history", []),
|
| 626 |
+
top_p=0.95,
|
| 627 |
+
temperature=1.0,
|
| 628 |
+
max_length_tokens=1024,
|
| 629 |
+
max_context_length_tokens=4096,
|
| 630 |
+
user_name=user_name,
|
| 631 |
+
user_memory=user_memory,
|
| 632 |
+
user_memory_index=None,
|
| 633 |
+
service_context=service_context,
|
| 634 |
+
api_index=api_index,
|
| 635 |
+
semantic_memory_text=semantic_memory_text,
|
| 636 |
+
query_category=query_category
|
| 637 |
+
)
|
| 638 |
+
|
| 639 |
+
state["history"] = new_history
|
| 640 |
+
return "", new_history, state
|
| 641 |
+
|
| 642 |
+
def clear_history(state):
|
| 643 |
+
state["history"] = []
|
| 644 |
+
return [], state
|
| 645 |
+
|
| 646 |
+
# -------------------------------------------------------
|
| 647 |
+
# Event Bindings
|
| 648 |
+
# -------------------------------------------------------
|
| 649 |
+
check_user_btn.click(
|
| 650 |
+
handle_login_check,
|
| 651 |
+
inputs=[username_input, state],
|
| 652 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
register_btn.click(
|
| 656 |
+
handle_register,
|
| 657 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 658 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 659 |
+
)
|
| 660 |
+
|
| 661 |
+
switch_user_btn.click(
|
| 662 |
+
switch_user,
|
| 663 |
+
inputs=[state],
|
| 664 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
submit_btn.click(
|
| 668 |
+
handle_chat,
|
| 669 |
+
inputs=[user_input, state],
|
| 670 |
+
outputs=[user_input, chatbot, state]
|
| 671 |
+
)
|
| 672 |
+
|
| 673 |
+
user_input.submit(
|
| 674 |
+
handle_chat,
|
| 675 |
+
inputs=[user_input, state],
|
| 676 |
+
outputs=[user_input, chatbot, state]
|
| 677 |
+
)
|
| 678 |
+
|
| 679 |
+
clear_btn.click(
|
| 680 |
+
clear_history,
|
| 681 |
+
inputs=[state],
|
| 682 |
+
outputs=[chatbot, state]
|
| 683 |
+
)
|
| 684 |
+
|
| 685 |
+
new_session_btn.click(
|
| 686 |
+
clear_history,
|
| 687 |
+
inputs=[state],
|
| 688 |
+
outputs=[chatbot, state]
|
| 689 |
+
)
|
| 690 |
+
|
| 691 |
+
return demo
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
def main():
|
| 695 |
+
"""Main function to initialize and launch the interface."""
|
| 696 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 697 |
+
|
| 698 |
+
if not gapgpt_api_key:
|
| 699 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 700 |
+
else:
|
| 701 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 702 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 703 |
+
|
| 704 |
+
# تنظیم LLM (مدل زبانی)
|
| 705 |
+
llm = LlamaIndexOpenAI(
|
| 706 |
+
model="gpt-4o",
|
| 707 |
+
temperature=1,
|
| 708 |
+
max_tokens=1024,
|
| 709 |
+
top_p=0.95,
|
| 710 |
+
frequency_penalty=0.4,
|
| 711 |
+
presence_penalty=0.2,
|
| 712 |
+
api_key=gapgpt_api_key,
|
| 713 |
+
api_base=GAPGPT_BASE_URL,
|
| 714 |
+
)
|
| 715 |
+
|
| 716 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 717 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 718 |
+
embed_model = OpenAIEmbedding(
|
| 719 |
+
api_key=gapgpt_api_key,
|
| 720 |
+
api_base=GAPGPT_BASE_URL,
|
| 721 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 722 |
+
)
|
| 723 |
+
|
| 724 |
+
# اعمال تنظیمات سراسری
|
| 725 |
+
Settings.llm = llm
|
| 726 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 727 |
+
|
| 728 |
+
Settings.prompt_helper = PromptHelper(
|
| 729 |
+
context_window=4096,
|
| 730 |
+
num_output=256,
|
| 731 |
+
chunk_overlap_ratio=20 / 4096,
|
| 732 |
+
tokenizer=tokenizer,
|
| 733 |
+
)
|
| 734 |
+
|
| 735 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 736 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 737 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 738 |
+
if 'api_keys' not in locals():
|
| 739 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 740 |
+
|
| 741 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 742 |
+
demo.launch(
|
| 743 |
+
server_name="127.0.0.1",
|
| 744 |
+
server_port=7860,
|
| 745 |
+
share=True
|
| 746 |
+
)
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
if __name__ == "__main__":
|
| 750 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 751 |
+
main()
|
Backup code/app_V4.py
ADDED
|
@@ -0,0 +1,855 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
|
| 13 |
+
import gradio as gr
|
| 14 |
+
import nltk
|
| 15 |
+
import torch
|
| 16 |
+
import tiktoken
|
| 17 |
+
|
| 18 |
+
from openai import OpenAI as OpenAIClient
|
| 19 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 20 |
+
|
| 21 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 22 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 23 |
+
from llama_index.core import Settings
|
| 24 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 25 |
+
|
| 26 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 27 |
+
sys.path.append(prompt_path)
|
| 28 |
+
|
| 29 |
+
# Assuming these imports exist in your local environment
|
| 30 |
+
from utils.sys_args import data_args, model_args
|
| 31 |
+
from utils.app_modules.utils import *
|
| 32 |
+
from utils.app_modules.presets import *
|
| 33 |
+
from utils.app_modules.overwrites import *
|
| 34 |
+
from utils.prompt_utils import *
|
| 35 |
+
from utils.memory_utils import (
|
| 36 |
+
enter_name_llamaindex,
|
| 37 |
+
summarize_memory_event_personality,
|
| 38 |
+
save_local_memory,
|
| 39 |
+
extract_session_summary,
|
| 40 |
+
extract_semantic_memory,
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
# Ensure NLTK data path
|
| 44 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 45 |
+
|
| 46 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 47 |
+
|
| 48 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 49 |
+
openai_client_cache = {}
|
| 50 |
+
|
| 51 |
+
import torch
|
| 52 |
+
import torch.nn.functional as F
|
| 53 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 57 |
+
|
| 58 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 59 |
+
|
| 60 |
+
try:
|
| 61 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 62 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model.eval()
|
| 64 |
+
print("Local classifier loaded successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
print(f"Error loading local classifier: {e}")
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 70 |
+
if not api_key:
|
| 71 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 72 |
+
if api_key not in openai_client_cache:
|
| 73 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 74 |
+
return openai_client_cache[api_key]
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
os_name = platform.system()
|
| 78 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 79 |
+
stop_stream = False
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def signal_handler(signal_number, frame):
|
| 83 |
+
global stop_stream
|
| 84 |
+
stop_stream = True
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 88 |
+
|
| 89 |
+
# Update this path to your actual file location
|
| 90 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def read_apis(path):
|
| 94 |
+
api_keys_local = []
|
| 95 |
+
if os.path.exists(path):
|
| 96 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 97 |
+
for line in f:
|
| 98 |
+
line = line.strip()
|
| 99 |
+
if line:
|
| 100 |
+
api_keys_local.append(line)
|
| 101 |
+
return api_keys_local
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 105 |
+
|
| 106 |
+
# Ensure directory exists
|
| 107 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 108 |
+
|
| 109 |
+
if not os.path.exists(memory_dir):
|
| 110 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 111 |
+
|
| 112 |
+
global memory
|
| 113 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 114 |
+
language = 'en'
|
| 115 |
+
user_keyword = generate_user_keyword()[language]
|
| 116 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 117 |
+
boot_name = boot_name_dict[language]
|
| 118 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 119 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 120 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 122 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 123 |
+
|
| 124 |
+
api_keys = read_apis(api_path)
|
| 125 |
+
# Fallback if file is empty or missing for testing purposes
|
| 126 |
+
if not api_keys:
|
| 127 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 128 |
+
|
| 129 |
+
new_conversation = False
|
| 130 |
+
chatgpt_config = {
|
| 131 |
+
"model": "gpt-4o",
|
| 132 |
+
"temperature": 1,
|
| 133 |
+
"max_tokens": 1024,
|
| 134 |
+
"top_p": 0.95,
|
| 135 |
+
"frequency_penalty": 0.4,
|
| 136 |
+
"presence_penalty": 0.2,
|
| 137 |
+
"n": 1,
|
| 138 |
+
}
|
| 139 |
+
|
| 140 |
+
deactivated_keys = []
|
| 141 |
+
logging.basicConfig(
|
| 142 |
+
level=logging.DEBUG,
|
| 143 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 148 |
+
"""
|
| 149 |
+
Handles the chat request to OpenAI.
|
| 150 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 151 |
+
"""
|
| 152 |
+
retry_times, count = 5, 0
|
| 153 |
+
response = None
|
| 154 |
+
|
| 155 |
+
while response is None and count < retry_times:
|
| 156 |
+
try:
|
| 157 |
+
request = copy.deepcopy(gpt_config)
|
| 158 |
+
|
| 159 |
+
# Initial system and greeting messages
|
| 160 |
+
if data_args.language == 'en':
|
| 161 |
+
message = [
|
| 162 |
+
{"role": "system", "content": system.strip()},
|
| 163 |
+
{"role": "user", "content": "Hi!"},
|
| 164 |
+
{"role": "assistant",
|
| 165 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 166 |
+
]
|
| 167 |
+
else:
|
| 168 |
+
message = [
|
| 169 |
+
{"role": "system", "content": system.strip()},
|
| 170 |
+
{"role": "user", "content": "Hi"},
|
| 171 |
+
{"role": "assistant",
|
| 172 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 173 |
+
]
|
| 174 |
+
|
| 175 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 176 |
+
if history:
|
| 177 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 178 |
+
if isinstance(history[0], list):
|
| 179 |
+
# Convert old format temporarily if encountered
|
| 180 |
+
for q, a in history:
|
| 181 |
+
message.append({"role": "user", "content": str(q)})
|
| 182 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 183 |
+
elif isinstance(history[0], dict):
|
| 184 |
+
# New format
|
| 185 |
+
for msg in history:
|
| 186 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 187 |
+
message.append(msg)
|
| 188 |
+
|
| 189 |
+
# Add the current prompt
|
| 190 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 191 |
+
|
| 192 |
+
if not api_keys:
|
| 193 |
+
return "Error: No API Keys available."
|
| 194 |
+
|
| 195 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 196 |
+
|
| 197 |
+
# New OpenAI 1.x Syntax
|
| 198 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 199 |
+
|
| 200 |
+
except Exception as e:
|
| 201 |
+
print(f"Chat Error: {e}")
|
| 202 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 203 |
+
deactivated_keys.append(api_keys[api_index])
|
| 204 |
+
|
| 205 |
+
if api_keys:
|
| 206 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 207 |
+
loop_check = 0
|
| 208 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 209 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 210 |
+
loop_check += 1
|
| 211 |
+
count += 1
|
| 212 |
+
|
| 213 |
+
if response:
|
| 214 |
+
response = response.choices[0].message.content
|
| 215 |
+
else:
|
| 216 |
+
response = ''
|
| 217 |
+
return response
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
def classify_query_local(text):
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 224 |
+
id2label_map = {
|
| 225 |
+
0: "episodic_memory",
|
| 226 |
+
1: "semantic_memory",
|
| 227 |
+
2: "semantic-episodic",
|
| 228 |
+
3: "unknown"
|
| 229 |
+
}
|
| 230 |
+
|
| 231 |
+
try:
|
| 232 |
+
|
| 233 |
+
inputs = _tokenizer(
|
| 234 |
+
text,
|
| 235 |
+
return_tensors="pt",
|
| 236 |
+
truncation=True,
|
| 237 |
+
padding=True,
|
| 238 |
+
max_length=512
|
| 239 |
+
)
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
with torch.no_grad():
|
| 244 |
+
outputs = _classifier_model(**inputs)
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
logits = outputs.logits
|
| 248 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 249 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 253 |
+
|
| 254 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 255 |
+
return category
|
| 256 |
+
|
| 257 |
+
except Exception as e:
|
| 258 |
+
print(f"Error in local classification: {e}")
|
| 259 |
+
return "unknown"
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 264 |
+
response = None
|
| 265 |
+
count = 0
|
| 266 |
+
local_deactivated = []
|
| 267 |
+
print("text********:", text)
|
| 268 |
+
|
| 269 |
+
system_prompt = """
|
| 270 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 271 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 272 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 273 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 274 |
+
|
| 275 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 276 |
+
""".strip()
|
| 277 |
+
|
| 278 |
+
if not api_keys:
|
| 279 |
+
return "unknown"
|
| 280 |
+
|
| 281 |
+
while response is None and count < retry_times:
|
| 282 |
+
try:
|
| 283 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 284 |
+
|
| 285 |
+
# New OpenAI 1.x Syntax
|
| 286 |
+
response = client.chat.completions.create(
|
| 287 |
+
messages=[
|
| 288 |
+
{"role": "system", "content": system_prompt},
|
| 289 |
+
{"role": "user", "content": text.strip()},
|
| 290 |
+
],
|
| 291 |
+
**copy.deepcopy(gpt_config),
|
| 292 |
+
)
|
| 293 |
+
except Exception as e:
|
| 294 |
+
print(f"Classify Error: {e}")
|
| 295 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 296 |
+
local_deactivated.append(api_keys[api_index])
|
| 297 |
+
|
| 298 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 299 |
+
while api_keys[api_index] in local_deactivated:
|
| 300 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 301 |
+
count += 1
|
| 302 |
+
|
| 303 |
+
if response:
|
| 304 |
+
category = response.choices[0].message.content.strip().lower()
|
| 305 |
+
# Basic cleanup
|
| 306 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 307 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 308 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 309 |
+
else: category = "unknown"
|
| 310 |
+
else:
|
| 311 |
+
category = "unknown"
|
| 312 |
+
|
| 313 |
+
return category
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
def predict_new(
|
| 317 |
+
text,
|
| 318 |
+
history,
|
| 319 |
+
top_p,
|
| 320 |
+
temperature,
|
| 321 |
+
max_length_tokens,
|
| 322 |
+
max_context_length_tokens,
|
| 323 |
+
user_name,
|
| 324 |
+
user_memory,
|
| 325 |
+
user_memory_index,
|
| 326 |
+
service_context,
|
| 327 |
+
api_index,
|
| 328 |
+
semantic_memory_text,
|
| 329 |
+
query_category,
|
| 330 |
+
):
|
| 331 |
+
chatgpt_cfg = {
|
| 332 |
+
"model": "gpt-4o",
|
| 333 |
+
"temperature": temperature,
|
| 334 |
+
"max_tokens": max_length_tokens,
|
| 335 |
+
"top_p": top_p,
|
| 336 |
+
"frequency_penalty": 0.4,
|
| 337 |
+
"presence_penalty": 0.2,
|
| 338 |
+
"n": 1,
|
| 339 |
+
}
|
| 340 |
+
|
| 341 |
+
if text == "":
|
| 342 |
+
# Return same history if empty input
|
| 343 |
+
return history, history, "Empty context."
|
| 344 |
+
|
| 345 |
+
# Ensure history is initialized
|
| 346 |
+
if history is None:
|
| 347 |
+
history = []
|
| 348 |
+
|
| 349 |
+
system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
|
| 350 |
+
history=history,
|
| 351 |
+
query=text, # Changed name to match prompt_utils
|
| 352 |
+
user_memory=user_memory,
|
| 353 |
+
user_name=user_name,
|
| 354 |
+
user_memory_index=user_memory_index,
|
| 355 |
+
service_context=service_context,
|
| 356 |
+
api_keys=api_keys,
|
| 357 |
+
api_index=api_index,
|
| 358 |
+
meta_prompt=meta_prompt,
|
| 359 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 360 |
+
data_args=data_args,
|
| 361 |
+
boot_actual_name=boot_actual_name,
|
| 362 |
+
semantic_memory_text=semantic_memory_text,
|
| 363 |
+
query_category=query_category,
|
| 364 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 365 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
# Handle context window slicing manually if needed,
|
| 369 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 370 |
+
current_history_for_llm = history
|
| 371 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 372 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 373 |
+
|
| 374 |
+
response = chatgpt_chat(
|
| 375 |
+
prompt=text,
|
| 376 |
+
system=system_prompt,
|
| 377 |
+
history=current_history_for_llm,
|
| 378 |
+
gpt_config=chatgpt_cfg,
|
| 379 |
+
api_index=api_index,
|
| 380 |
+
)
|
| 381 |
+
|
| 382 |
+
torch.cuda.empty_cache()
|
| 383 |
+
|
| 384 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 385 |
+
new_history = history + [
|
| 386 |
+
{"role": "user", "content": text},
|
| 387 |
+
{"role": "assistant", "content": response}
|
| 388 |
+
]
|
| 389 |
+
|
| 390 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 391 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 392 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 393 |
+
if user_name:
|
| 394 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 395 |
+
# or pass a converted version. Let's try passing the new format.
|
| 396 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 397 |
+
|
| 398 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 399 |
+
return new_history, new_history, "Generating..."
|
| 400 |
+
|
| 401 |
+
|
| 402 |
+
import gradio as gr
|
| 403 |
+
import time
|
| 404 |
+
|
| 405 |
+
import gradio as gr
|
| 406 |
+
|
| 407 |
+
def create_gradio_interface(service_context, api_keys):
|
| 408 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 409 |
+
|
| 410 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 411 |
+
gr.HTML("""
|
| 412 |
+
<style>
|
| 413 |
+
.center-content {
|
| 414 |
+
display: flex;
|
| 415 |
+
flex-direction: column;
|
| 416 |
+
align-items: center;
|
| 417 |
+
justify-content: center;
|
| 418 |
+
}
|
| 419 |
+
/* -- استایلهای فرم ورود -- */
|
| 420 |
+
.login-box {
|
| 421 |
+
max-width: 400px !important;
|
| 422 |
+
margin: 0 auto !important;
|
| 423 |
+
width: 100% !important;
|
| 424 |
+
}
|
| 425 |
+
.login-btn, .login-btn:hover {
|
| 426 |
+
background-color: #3498db !important;
|
| 427 |
+
background-image: none !important;
|
| 428 |
+
color: white !important;
|
| 429 |
+
border: none !important;
|
| 430 |
+
}
|
| 431 |
+
/* -- استایلهای محیط چت -- */
|
| 432 |
+
.chat-box {
|
| 433 |
+
max-width: 800px !important;
|
| 434 |
+
margin: 0 auto !important;
|
| 435 |
+
width: 100% !important;
|
| 436 |
+
}
|
| 437 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 438 |
+
.mobile-button, .mobile-button:hover {
|
| 439 |
+
background-color: #3498db !important;
|
| 440 |
+
background-image: none !important;
|
| 441 |
+
color: white !important;
|
| 442 |
+
border: none !important;
|
| 443 |
+
}
|
| 444 |
+
.gr-textbox textarea {
|
| 445 |
+
font-size: 16px;
|
| 446 |
+
}
|
| 447 |
+
.gr-chatbot {
|
| 448 |
+
font-size: 15px;
|
| 449 |
+
}
|
| 450 |
+
|
| 451 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 452 |
+
.slide-up {
|
| 453 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
@keyframes slideUpAnimation {
|
| 457 |
+
0% {
|
| 458 |
+
transform: translateY(0);
|
| 459 |
+
opacity: 1;
|
| 460 |
+
max-height: 1000px;
|
| 461 |
+
}
|
| 462 |
+
100% {
|
| 463 |
+
transform: translateY(-100%);
|
| 464 |
+
opacity: 0;
|
| 465 |
+
max-height: 0px;
|
| 466 |
+
overflow: hidden;
|
| 467 |
+
margin: 0 !important;
|
| 468 |
+
padding: 0 !important;
|
| 469 |
+
border: none !important;
|
| 470 |
+
}
|
| 471 |
+
}
|
| 472 |
+
</style>
|
| 473 |
+
""")
|
| 474 |
+
|
| 475 |
+
state = gr.State({
|
| 476 |
+
"history": [],
|
| 477 |
+
"user_name": None,
|
| 478 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 479 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 480 |
+
"service_context": service_context,
|
| 481 |
+
"api_keys": api_keys,
|
| 482 |
+
"api_index": 0,
|
| 483 |
+
"semantic_memory_text": "",
|
| 484 |
+
"new_conversation": True,
|
| 485 |
+
"initialized": False
|
| 486 |
+
})
|
| 487 |
+
|
| 488 |
+
# ==========================================
|
| 489 |
+
# 1. LOGIN PAGE
|
| 490 |
+
# ==========================================
|
| 491 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 492 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 493 |
+
|
| 494 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 495 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 496 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 497 |
+
|
| 498 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 499 |
+
|
| 500 |
+
with gr.Column(visible=False) as registration_fields:
|
| 501 |
+
gr.Markdown("### ✨ New User Registration")
|
| 502 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 503 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 504 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 505 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 506 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 507 |
+
|
| 508 |
+
# ==========================================
|
| 509 |
+
# 2. CHAT PAGE
|
| 510 |
+
# ==========================================
|
| 511 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 512 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 513 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 514 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 515 |
+
|
| 516 |
+
with gr.Group():
|
| 517 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 518 |
+
|
| 519 |
+
with gr.Row():
|
| 520 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 521 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 522 |
+
|
| 523 |
+
with gr.Row(equal_height=True):
|
| 524 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 525 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 526 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 527 |
+
|
| 528 |
+
# -------------------------------------------------------
|
| 529 |
+
# Internal Functions
|
| 530 |
+
# -------------------------------------------------------
|
| 531 |
+
def handle_login_check(name, state):
|
| 532 |
+
if not name.strip():
|
| 533 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 534 |
+
|
| 535 |
+
if name in memory:
|
| 536 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 537 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 538 |
+
|
| 539 |
+
new_state = state.copy()
|
| 540 |
+
new_state["user_name"] = name
|
| 541 |
+
new_state["memory"] = memory
|
| 542 |
+
new_state["initialized"] = True
|
| 543 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 544 |
+
new_state["history"] = []
|
| 545 |
+
|
| 546 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 547 |
+
|
| 548 |
+
return (
|
| 549 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 550 |
+
gr.update(visible=False),
|
| 551 |
+
gr.update(visible=True),
|
| 552 |
+
gr.update(visible=False, value=""),
|
| 553 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 554 |
+
gr.update(value=welcome_msg),
|
| 555 |
+
new_state
|
| 556 |
+
)
|
| 557 |
+
else:
|
| 558 |
+
return (
|
| 559 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 560 |
+
gr.update(visible=True),
|
| 561 |
+
gr.update(visible=False),
|
| 562 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 563 |
+
gr.update(),
|
| 564 |
+
gr.update(),
|
| 565 |
+
state
|
| 566 |
+
)
|
| 567 |
+
|
| 568 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 569 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 570 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 571 |
+
|
| 572 |
+
new_state = state.copy()
|
| 573 |
+
new_state["user_name"] = name
|
| 574 |
+
new_state["memory"] = memory
|
| 575 |
+
new_state["initialized"] = True
|
| 576 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 577 |
+
new_state["history"] = []
|
| 578 |
+
|
| 579 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 580 |
+
|
| 581 |
+
return (
|
| 582 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
|
| 583 |
+
gr.update(visible=False),
|
| 584 |
+
gr.update(visible=True),
|
| 585 |
+
gr.update(visible=False, value=""),
|
| 586 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 587 |
+
gr.update(value=welcome_msg),
|
| 588 |
+
new_state
|
| 589 |
+
)
|
| 590 |
+
|
| 591 |
+
def switch_user(state):
|
| 592 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 593 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 594 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 595 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 596 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 597 |
+
|
| 598 |
+
new_state = state.copy()
|
| 599 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 600 |
+
|
| 601 |
+
return (
|
| 602 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 603 |
+
gr.update(visible=False),
|
| 604 |
+
gr.update(visible=False),
|
| 605 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 606 |
+
gr.update(value=""),
|
| 607 |
+
new_state,
|
| 608 |
+
gr.update(value=[])
|
| 609 |
+
)
|
| 610 |
+
|
| 611 |
+
def handle_chat(user_message, state):
|
| 612 |
+
if not user_message.strip():
|
| 613 |
+
return gr.update(), state.get("history", []), state
|
| 614 |
+
|
| 615 |
+
user_name = state.get("user_name")
|
| 616 |
+
user_memory = state.get("memory")
|
| 617 |
+
service_context = state.get("service_context")
|
| 618 |
+
api_index = state.get("api_index", 0)
|
| 619 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 620 |
+
|
| 621 |
+
query_category = classify_query_local(user_message)
|
| 622 |
+
|
| 623 |
+
new_history, _, status_msg = predict_new(
|
| 624 |
+
text=user_message,
|
| 625 |
+
history=state.get("history", []),
|
| 626 |
+
top_p=0.95,
|
| 627 |
+
temperature=1.0,
|
| 628 |
+
max_length_tokens=1024,
|
| 629 |
+
max_context_length_tokens=4096,
|
| 630 |
+
user_name=user_name,
|
| 631 |
+
user_memory=user_memory,
|
| 632 |
+
user_memory_index=None,
|
| 633 |
+
service_context=service_context,
|
| 634 |
+
api_index=api_index,
|
| 635 |
+
semantic_memory_text=semantic_memory_text,
|
| 636 |
+
query_category=query_category
|
| 637 |
+
)
|
| 638 |
+
|
| 639 |
+
state["history"] = new_history
|
| 640 |
+
return "", new_history, state
|
| 641 |
+
|
| 642 |
+
def clear_history(state):
|
| 643 |
+
state["history"] = []
|
| 644 |
+
return [], state
|
| 645 |
+
|
| 646 |
+
def handle_new_session(state):
|
| 647 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 648 |
+
user_name = state.get("user_name")
|
| 649 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 650 |
+
print("Error: User not logged in or memory missing.")
|
| 651 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 652 |
+
return [], state
|
| 653 |
+
|
| 654 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 655 |
+
user_data = state["memory"][user_name]
|
| 656 |
+
|
| 657 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 658 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 659 |
+
last_session = user_data["sessions"][-1]
|
| 660 |
+
|
| 661 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 662 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 663 |
+
session_date = last_session.get("date", "")
|
| 664 |
+
session_id = last_session.get("session_id", 0)
|
| 665 |
+
|
| 666 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 667 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 668 |
+
|
| 669 |
+
if "episodic_memory" not in user_data:
|
| 670 |
+
user_data["episodic_memory"] = []
|
| 671 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 672 |
+
|
| 673 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 674 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 675 |
+
|
| 676 |
+
new_session = {
|
| 677 |
+
"session_id": new_session_id,
|
| 678 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 679 |
+
"conversation": []
|
| 680 |
+
}
|
| 681 |
+
|
| 682 |
+
if "sessions" not in user_data:
|
| 683 |
+
user_data["sessions"] = []
|
| 684 |
+
|
| 685 |
+
user_data["sessions"].append(new_session)
|
| 686 |
+
|
| 687 |
+
# پاک کردن تاریخچه چت در state
|
| 688 |
+
state["history"] = []
|
| 689 |
+
|
| 690 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 691 |
+
return [], state
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
# اگر state خالی است یا کلید user_data را ندارد
|
| 695 |
+
if not state or "user_data" not in state:
|
| 696 |
+
print("Error: user_data not found in state.")
|
| 697 |
+
# مقادیر بازگشتی را بر اساس خروجیهای تابع خود تنظیم کنید
|
| 698 |
+
# مثلاً برگرداندن state فعلی و یک لیست خالی برای چتباکس
|
| 699 |
+
return state, []
|
| 700 |
+
|
| 701 |
+
# دریافت امن اطلاعات کاربر
|
| 702 |
+
user_data = state["user_data"]
|
| 703 |
+
|
| 704 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی (قبل از ساخت جلسه جدید) ---
|
| 705 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 706 |
+
last_session = user_data["sessions"][-1]
|
| 707 |
+
|
| 708 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد (کاربر حرفی زده باشد)
|
| 709 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 710 |
+
|
| 711 |
+
# استخراج حافظه اپیزودیک از مکالمات جلسه قبل
|
| 712 |
+
ep_summary = extract_session_summary(last_session["conversation"])
|
| 713 |
+
|
| 714 |
+
# اضافه کردن تاریخ و ID همان جلسه به حافظه اپیزودیک استخراج شده
|
| 715 |
+
ep_summary["session_date"] = last_session["date"]
|
| 716 |
+
ep_summary["session_id"] = last_session.get("session_id", 0)
|
| 717 |
+
|
| 718 |
+
# ذخیره در لیست حافظه اپیزودیک
|
| 719 |
+
if "episodic_memory" not in user_data:
|
| 720 |
+
user_data["episodic_memory"] = []
|
| 721 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 722 |
+
|
| 723 |
+
# (اگر حافظه سمانتیک هم دارید، اینجا آپدیت کنید)
|
| 724 |
+
|
| 725 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 726 |
+
|
| 727 |
+
# محاسبه ID جدید (بر اساس تعداد جلسات فعلی)
|
| 728 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 729 |
+
|
| 730 |
+
new_session = {
|
| 731 |
+
"session_id": new_session_id, # <--- مشکل اختصاص نیافتن ID اینجا حل میشود
|
| 732 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 733 |
+
"conversation": []
|
| 734 |
+
}
|
| 735 |
+
|
| 736 |
+
if "sessions" not in user_data:
|
| 737 |
+
user_data["sessions"] = []
|
| 738 |
+
|
| 739 |
+
user_data["sessions"].append(new_session)
|
| 740 |
+
|
| 741 |
+
# پاک کردن تاریخچه چت در رابط کاربری (Gradio)
|
| 742 |
+
state["history"] = []
|
| 743 |
+
|
| 744 |
+
return state
|
| 745 |
+
|
| 746 |
+
|
| 747 |
+
# -------------------------------------------------------
|
| 748 |
+
# Event Bindings
|
| 749 |
+
# -------------------------------------------------------
|
| 750 |
+
check_user_btn.click(
|
| 751 |
+
handle_login_check,
|
| 752 |
+
inputs=[username_input, state],
|
| 753 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 754 |
+
)
|
| 755 |
+
|
| 756 |
+
register_btn.click(
|
| 757 |
+
handle_register,
|
| 758 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 759 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 760 |
+
)
|
| 761 |
+
|
| 762 |
+
switch_user_btn.click(
|
| 763 |
+
switch_user,
|
| 764 |
+
inputs=[state],
|
| 765 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 766 |
+
)
|
| 767 |
+
|
| 768 |
+
submit_btn.click(
|
| 769 |
+
handle_chat,
|
| 770 |
+
inputs=[user_input, state],
|
| 771 |
+
outputs=[user_input, chatbot, state]
|
| 772 |
+
)
|
| 773 |
+
|
| 774 |
+
user_input.submit(
|
| 775 |
+
handle_chat,
|
| 776 |
+
inputs=[user_input, state],
|
| 777 |
+
outputs=[user_input, chatbot, state]
|
| 778 |
+
)
|
| 779 |
+
|
| 780 |
+
clear_btn.click(
|
| 781 |
+
clear_history,
|
| 782 |
+
inputs=[state],
|
| 783 |
+
outputs=[chatbot, state]
|
| 784 |
+
)
|
| 785 |
+
|
| 786 |
+
# تغییر از clear_history به handle_new_session
|
| 787 |
+
new_session_btn.click(
|
| 788 |
+
handle_new_session,
|
| 789 |
+
inputs=[state],
|
| 790 |
+
outputs=[chatbot, state]
|
| 791 |
+
|
| 792 |
+
|
| 793 |
+
)
|
| 794 |
+
|
| 795 |
+
return demo
|
| 796 |
+
|
| 797 |
+
|
| 798 |
+
def main():
|
| 799 |
+
"""Main function to initialize and launch the interface."""
|
| 800 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 801 |
+
|
| 802 |
+
if not gapgpt_api_key:
|
| 803 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 804 |
+
else:
|
| 805 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 806 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 807 |
+
|
| 808 |
+
# تنظیم LLM (مدل زبانی)
|
| 809 |
+
llm = LlamaIndexOpenAI(
|
| 810 |
+
model="gpt-4o",
|
| 811 |
+
temperature=1,
|
| 812 |
+
max_tokens=1024,
|
| 813 |
+
top_p=0.95,
|
| 814 |
+
frequency_penalty=0.4,
|
| 815 |
+
presence_penalty=0.2,
|
| 816 |
+
api_key=gapgpt_api_key,
|
| 817 |
+
api_base=GAPGPT_BASE_URL,
|
| 818 |
+
)
|
| 819 |
+
|
| 820 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 821 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 822 |
+
embed_model = OpenAIEmbedding(
|
| 823 |
+
api_key=gapgpt_api_key,
|
| 824 |
+
api_base=GAPGPT_BASE_URL,
|
| 825 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 826 |
+
)
|
| 827 |
+
|
| 828 |
+
# اعمال تنظیمات سراسری
|
| 829 |
+
Settings.llm = llm
|
| 830 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 831 |
+
|
| 832 |
+
Settings.prompt_helper = PromptHelper(
|
| 833 |
+
context_window=4096,
|
| 834 |
+
num_output=256,
|
| 835 |
+
chunk_overlap_ratio=20 / 4096,
|
| 836 |
+
tokenizer=tokenizer,
|
| 837 |
+
)
|
| 838 |
+
|
| 839 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 840 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 841 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 842 |
+
if 'api_keys' not in locals():
|
| 843 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 844 |
+
|
| 845 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 846 |
+
demo.launch(
|
| 847 |
+
server_name="127.0.0.1",
|
| 848 |
+
server_port=7860,
|
| 849 |
+
share=True
|
| 850 |
+
)
|
| 851 |
+
|
| 852 |
+
|
| 853 |
+
if __name__ == "__main__":
|
| 854 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 855 |
+
main()
|
Backup code/app_V5.py
ADDED
|
@@ -0,0 +1,881 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
):
|
| 332 |
+
chatgpt_cfg = {
|
| 333 |
+
"model": "gpt-4o",
|
| 334 |
+
"temperature": temperature,
|
| 335 |
+
"max_tokens": max_length_tokens,
|
| 336 |
+
"top_p": top_p,
|
| 337 |
+
"frequency_penalty": 0.4,
|
| 338 |
+
"presence_penalty": 0.2,
|
| 339 |
+
"n": 1,
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
if text == "":
|
| 343 |
+
# Return same history if empty input
|
| 344 |
+
return history, history, "Empty context."
|
| 345 |
+
|
| 346 |
+
# Ensure history is initialized
|
| 347 |
+
if history is None:
|
| 348 |
+
history = []
|
| 349 |
+
|
| 350 |
+
system_prompt, related_memo = build_prompt_with_search_memory_llamaindex(
|
| 351 |
+
history=history,
|
| 352 |
+
query=text, # Changed name to match prompt_utils
|
| 353 |
+
user_memory=user_memory,
|
| 354 |
+
user_name=user_name,
|
| 355 |
+
user_memory_index=user_memory_index,
|
| 356 |
+
service_context=service_context,
|
| 357 |
+
api_keys=api_keys,
|
| 358 |
+
api_index=api_index,
|
| 359 |
+
meta_prompt=meta_prompt,
|
| 360 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 361 |
+
data_args=data_args,
|
| 362 |
+
boot_actual_name=boot_actual_name,
|
| 363 |
+
semantic_memory_text=semantic_memory_text,
|
| 364 |
+
query_category=query_category,
|
| 365 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 366 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
# Handle context window slicing manually if needed,
|
| 370 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 371 |
+
current_history_for_llm = history
|
| 372 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 373 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 374 |
+
|
| 375 |
+
response = chatgpt_chat(
|
| 376 |
+
prompt=text,
|
| 377 |
+
system=system_prompt,
|
| 378 |
+
history=current_history_for_llm,
|
| 379 |
+
gpt_config=chatgpt_cfg,
|
| 380 |
+
api_index=api_index,
|
| 381 |
+
)
|
| 382 |
+
|
| 383 |
+
torch.cuda.empty_cache()
|
| 384 |
+
|
| 385 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 386 |
+
new_history = history + [
|
| 387 |
+
{"role": "user", "content": text},
|
| 388 |
+
{"role": "assistant", "content": response}
|
| 389 |
+
]
|
| 390 |
+
|
| 391 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 392 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 393 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 394 |
+
if user_name:
|
| 395 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 396 |
+
# or pass a converted version. Let's try passing the new format.
|
| 397 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 398 |
+
|
| 399 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 400 |
+
return new_history, new_history, "Generating..."
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def create_gradio_interface(service_context, api_keys):
|
| 405 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 406 |
+
|
| 407 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 408 |
+
gr.HTML("""
|
| 409 |
+
<style>
|
| 410 |
+
.center-content {
|
| 411 |
+
display: flex;
|
| 412 |
+
flex-direction: column;
|
| 413 |
+
align-items: center;
|
| 414 |
+
justify-content: center;
|
| 415 |
+
}
|
| 416 |
+
/* -- استایلهای فرم ورود -- */
|
| 417 |
+
.login-box {
|
| 418 |
+
max-width: 400px !important;
|
| 419 |
+
margin: 0 auto !important;
|
| 420 |
+
width: 100% !important;
|
| 421 |
+
}
|
| 422 |
+
.login-btn, .login-btn:hover {
|
| 423 |
+
background-color: #3498db !important;
|
| 424 |
+
background-image: none !important;
|
| 425 |
+
color: white !important;
|
| 426 |
+
border: none !important;
|
| 427 |
+
}
|
| 428 |
+
/* -- استایلهای محیط چت -- */
|
| 429 |
+
.chat-box {
|
| 430 |
+
max-width: 800px !important;
|
| 431 |
+
margin: 0 auto !important;
|
| 432 |
+
width: 100% !important;
|
| 433 |
+
}
|
| 434 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 435 |
+
.mobile-button, .mobile-button:hover {
|
| 436 |
+
background-color: #3498db !important;
|
| 437 |
+
background-image: none !important;
|
| 438 |
+
color: white !important;
|
| 439 |
+
border: none !important;
|
| 440 |
+
}
|
| 441 |
+
.gr-textbox textarea {
|
| 442 |
+
font-size: 16px;
|
| 443 |
+
}
|
| 444 |
+
.gr-chatbot {
|
| 445 |
+
font-size: 15px;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 449 |
+
.slide-up {
|
| 450 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
@keyframes slideUpAnimation {
|
| 454 |
+
0% {
|
| 455 |
+
transform: translateY(0);
|
| 456 |
+
opacity: 1;
|
| 457 |
+
max-height: 1000px;
|
| 458 |
+
}
|
| 459 |
+
100% {
|
| 460 |
+
transform: translateY(-100%);
|
| 461 |
+
opacity: 0;
|
| 462 |
+
max-height: 0px;
|
| 463 |
+
overflow: hidden;
|
| 464 |
+
margin: 0 !important;
|
| 465 |
+
padding: 0 !important;
|
| 466 |
+
border: none !important;
|
| 467 |
+
}
|
| 468 |
+
}
|
| 469 |
+
</style>
|
| 470 |
+
""")
|
| 471 |
+
|
| 472 |
+
state = gr.State({
|
| 473 |
+
"history": [],
|
| 474 |
+
"user_name": None,
|
| 475 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 476 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 477 |
+
"service_context": service_context,
|
| 478 |
+
"api_keys": api_keys,
|
| 479 |
+
"api_index": 0,
|
| 480 |
+
"semantic_memory_text": "",
|
| 481 |
+
"new_conversation": True,
|
| 482 |
+
"initialized": False
|
| 483 |
+
})
|
| 484 |
+
|
| 485 |
+
# ==========================================
|
| 486 |
+
# 1. LOGIN PAGE
|
| 487 |
+
# ==========================================
|
| 488 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 489 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 490 |
+
|
| 491 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 492 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 493 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 494 |
+
|
| 495 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 496 |
+
|
| 497 |
+
with gr.Column(visible=False) as registration_fields:
|
| 498 |
+
gr.Markdown("### ✨ New User Registration")
|
| 499 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 500 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 501 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 502 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 503 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 504 |
+
|
| 505 |
+
# ==========================================
|
| 506 |
+
# 2. CHAT PAGE
|
| 507 |
+
# ==========================================
|
| 508 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 509 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 510 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 511 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 512 |
+
|
| 513 |
+
with gr.Group():
|
| 514 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 515 |
+
|
| 516 |
+
with gr.Row():
|
| 517 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 518 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 519 |
+
|
| 520 |
+
with gr.Row(equal_height=True):
|
| 521 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 522 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 523 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 524 |
+
|
| 525 |
+
# -------------------------------------------------------
|
| 526 |
+
# Internal Functions
|
| 527 |
+
# -------------------------------------------------------
|
| 528 |
+
def handle_login_check(name, state):
|
| 529 |
+
if not name.strip():
|
| 530 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 531 |
+
|
| 532 |
+
if name in memory:
|
| 533 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 534 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 535 |
+
|
| 536 |
+
new_state = state.copy()
|
| 537 |
+
new_state["user_name"] = name
|
| 538 |
+
new_state["memory"] = memory
|
| 539 |
+
new_state["initialized"] = True
|
| 540 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 541 |
+
new_state["history"] = []
|
| 542 |
+
|
| 543 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 544 |
+
|
| 545 |
+
return (
|
| 546 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 547 |
+
gr.update(visible=False),
|
| 548 |
+
gr.update(visible=True),
|
| 549 |
+
gr.update(visible=False, value=""),
|
| 550 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 551 |
+
gr.update(value=welcome_msg),
|
| 552 |
+
new_state
|
| 553 |
+
)
|
| 554 |
+
else:
|
| 555 |
+
return (
|
| 556 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 557 |
+
gr.update(visible=True),
|
| 558 |
+
gr.update(visible=False),
|
| 559 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 560 |
+
gr.update(),
|
| 561 |
+
gr.update(),
|
| 562 |
+
state
|
| 563 |
+
)
|
| 564 |
+
|
| 565 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 566 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 567 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 568 |
+
|
| 569 |
+
new_state = state.copy()
|
| 570 |
+
new_state["user_name"] = name
|
| 571 |
+
new_state["memory"] = memory
|
| 572 |
+
new_state["initialized"] = True
|
| 573 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 574 |
+
new_state["history"] = []
|
| 575 |
+
|
| 576 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 577 |
+
|
| 578 |
+
return (
|
| 579 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
|
| 580 |
+
gr.update(visible=False),
|
| 581 |
+
gr.update(visible=True),
|
| 582 |
+
gr.update(visible=False, value=""),
|
| 583 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 584 |
+
gr.update(value=welcome_msg),
|
| 585 |
+
new_state
|
| 586 |
+
)
|
| 587 |
+
|
| 588 |
+
def switch_user(state):
|
| 589 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 590 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 591 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 592 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 593 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 594 |
+
# ==========================================
|
| 595 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 596 |
+
# ==========================================
|
| 597 |
+
try:
|
| 598 |
+
user_mem = state["memory"][state["user_name"]]
|
| 599 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 600 |
+
|
| 601 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 602 |
+
|
| 603 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 604 |
+
except Exception as e:
|
| 605 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 606 |
+
# ==========================================
|
| 607 |
+
|
| 608 |
+
new_state = state.copy()
|
| 609 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 610 |
+
|
| 611 |
+
return (
|
| 612 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 613 |
+
gr.update(visible=False),
|
| 614 |
+
gr.update(visible=False),
|
| 615 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 616 |
+
gr.update(value=""),
|
| 617 |
+
new_state,
|
| 618 |
+
gr.update(value=[])
|
| 619 |
+
)
|
| 620 |
+
|
| 621 |
+
def handle_chat(user_message, state):
|
| 622 |
+
if not user_message.strip():
|
| 623 |
+
return gr.update(), state.get("history", []), state
|
| 624 |
+
|
| 625 |
+
user_name = state.get("user_name")
|
| 626 |
+
user_memory = state.get("memory")
|
| 627 |
+
service_context = state.get("service_context")
|
| 628 |
+
api_index = state.get("api_index", 0)
|
| 629 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 630 |
+
|
| 631 |
+
query_category = classify_query_local(user_message)
|
| 632 |
+
|
| 633 |
+
new_history, _, status_msg = predict_new(
|
| 634 |
+
text=user_message,
|
| 635 |
+
history=state.get("history", []),
|
| 636 |
+
top_p=0.95,
|
| 637 |
+
temperature=1.0,
|
| 638 |
+
max_length_tokens=1024,
|
| 639 |
+
max_context_length_tokens=4096,
|
| 640 |
+
user_name=user_name,
|
| 641 |
+
user_memory=user_memory,
|
| 642 |
+
user_memory_index=None,
|
| 643 |
+
service_context=service_context,
|
| 644 |
+
api_index=api_index,
|
| 645 |
+
semantic_memory_text=semantic_memory_text,
|
| 646 |
+
query_category=query_category
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
state["history"] = new_history
|
| 650 |
+
return "", new_history, state
|
| 651 |
+
|
| 652 |
+
def clear_history(state):
|
| 653 |
+
state["history"] = []
|
| 654 |
+
return [], state
|
| 655 |
+
|
| 656 |
+
def handle_new_session(state):
|
| 657 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 658 |
+
user_name = state.get("user_name")
|
| 659 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 660 |
+
print("Error: User not logged in or memory missing.")
|
| 661 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 662 |
+
return [], state
|
| 663 |
+
|
| 664 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 665 |
+
user_data = state["memory"][user_name]
|
| 666 |
+
|
| 667 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 668 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 669 |
+
last_session = user_data["sessions"][-1]
|
| 670 |
+
|
| 671 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 672 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 673 |
+
session_date = last_session.get("date", "")
|
| 674 |
+
session_id = last_session.get("session_id", 0)
|
| 675 |
+
|
| 676 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 677 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 678 |
+
|
| 679 |
+
if "episodic_memory" not in user_data:
|
| 680 |
+
user_data["episodic_memory"] = []
|
| 681 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 682 |
+
|
| 683 |
+
# ==========================================
|
| 684 |
+
# بهروزرسانی حافظه سمانتیک
|
| 685 |
+
# ==========================================
|
| 686 |
+
try:
|
| 687 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 688 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 689 |
+
|
| 690 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 691 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 692 |
+
|
| 693 |
+
# ذخیره دیتای جدید
|
| 694 |
+
user_data["semantic_memory"] = updated_semantic
|
| 695 |
+
except Exception as e:
|
| 696 |
+
print(f"Error updating semantic memory: {e}")
|
| 697 |
+
# ==========================================
|
| 698 |
+
|
| 699 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 700 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 701 |
+
|
| 702 |
+
new_session = {
|
| 703 |
+
"session_id": new_session_id,
|
| 704 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 705 |
+
"conversation": []
|
| 706 |
+
}
|
| 707 |
+
|
| 708 |
+
if "sessions" not in user_data:
|
| 709 |
+
user_data["sessions"] = []
|
| 710 |
+
|
| 711 |
+
user_data["sessions"].append(new_session)
|
| 712 |
+
|
| 713 |
+
# پاک کردن تاریخچه چت در state
|
| 714 |
+
state["history"] = []
|
| 715 |
+
|
| 716 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 717 |
+
return [], state
|
| 718 |
+
|
| 719 |
+
|
| 720 |
+
# اگر state خالی است یا کلید user_data را ندارد
|
| 721 |
+
if not state or "user_data" not in state:
|
| 722 |
+
print("Error: user_data not found in state.")
|
| 723 |
+
# مقادیر بازگشتی را بر اساس خروجیهای تابع خود تنظیم کنید
|
| 724 |
+
# مثلاً برگرداندن state فعلی و یک لیست خالی برای چتباکس
|
| 725 |
+
return state, []
|
| 726 |
+
|
| 727 |
+
# دریافت امن اطلاعات کاربر
|
| 728 |
+
user_data = state["user_data"]
|
| 729 |
+
|
| 730 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی (قبل از ساخت جلسه جدید) ---
|
| 731 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 732 |
+
last_session = user_data["sessions"][-1]
|
| 733 |
+
|
| 734 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد (کاربر حرفی زده باشد)
|
| 735 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 736 |
+
|
| 737 |
+
# استخراج حافظه اپیزودیک از مکالمات جلسه قبل
|
| 738 |
+
ep_summary = extract_session_summary(last_session["conversation"])
|
| 739 |
+
|
| 740 |
+
# اضافه کردن تاریخ و ID همان جلسه به حافظه اپیزودیک استخراج شده
|
| 741 |
+
ep_summary["session_date"] = last_session["date"]
|
| 742 |
+
ep_summary["session_id"] = last_session.get("session_id", 0)
|
| 743 |
+
|
| 744 |
+
# ذخیره در لیست حافظه اپیزودیک
|
| 745 |
+
if "episodic_memory" not in user_data:
|
| 746 |
+
user_data["episodic_memory"] = []
|
| 747 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 748 |
+
|
| 749 |
+
# (اگر حافظه سمانتیک هم دارید، اینجا آپدیت کنید)
|
| 750 |
+
|
| 751 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 752 |
+
|
| 753 |
+
# محاسبه ID جدید (بر اساس تعداد جلسات فعلی)
|
| 754 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 755 |
+
|
| 756 |
+
new_session = {
|
| 757 |
+
"session_id": new_session_id, # <--- مشکل اختصاص نیافتن ID اینجا حل میشود
|
| 758 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 759 |
+
"conversation": []
|
| 760 |
+
}
|
| 761 |
+
|
| 762 |
+
if "sessions" not in user_data:
|
| 763 |
+
user_data["sessions"] = []
|
| 764 |
+
|
| 765 |
+
user_data["sessions"].append(new_session)
|
| 766 |
+
|
| 767 |
+
# پاک کردن تاریخچه چت در رابط کاربری (Gradio)
|
| 768 |
+
state["history"] = []
|
| 769 |
+
|
| 770 |
+
return state
|
| 771 |
+
|
| 772 |
+
|
| 773 |
+
# -------------------------------------------------------
|
| 774 |
+
# Event Bindings
|
| 775 |
+
# -------------------------------------------------------
|
| 776 |
+
check_user_btn.click(
|
| 777 |
+
handle_login_check,
|
| 778 |
+
inputs=[username_input, state],
|
| 779 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 780 |
+
)
|
| 781 |
+
|
| 782 |
+
register_btn.click(
|
| 783 |
+
handle_register,
|
| 784 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 785 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 786 |
+
)
|
| 787 |
+
|
| 788 |
+
switch_user_btn.click(
|
| 789 |
+
switch_user,
|
| 790 |
+
inputs=[state],
|
| 791 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 792 |
+
)
|
| 793 |
+
|
| 794 |
+
submit_btn.click(
|
| 795 |
+
handle_chat,
|
| 796 |
+
inputs=[user_input, state],
|
| 797 |
+
outputs=[user_input, chatbot, state]
|
| 798 |
+
)
|
| 799 |
+
|
| 800 |
+
user_input.submit(
|
| 801 |
+
handle_chat,
|
| 802 |
+
inputs=[user_input, state],
|
| 803 |
+
outputs=[user_input, chatbot, state]
|
| 804 |
+
)
|
| 805 |
+
|
| 806 |
+
clear_btn.click(
|
| 807 |
+
clear_history,
|
| 808 |
+
inputs=[state],
|
| 809 |
+
outputs=[chatbot, state]
|
| 810 |
+
)
|
| 811 |
+
|
| 812 |
+
# تغییر از clear_history به handle_new_session
|
| 813 |
+
new_session_btn.click(
|
| 814 |
+
handle_new_session,
|
| 815 |
+
inputs=[state],
|
| 816 |
+
outputs=[chatbot, state]
|
| 817 |
+
|
| 818 |
+
|
| 819 |
+
)
|
| 820 |
+
|
| 821 |
+
return demo
|
| 822 |
+
|
| 823 |
+
|
| 824 |
+
def main():
|
| 825 |
+
"""Main function to initialize and launch the interface."""
|
| 826 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 827 |
+
|
| 828 |
+
if not gapgpt_api_key:
|
| 829 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 830 |
+
else:
|
| 831 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 832 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 833 |
+
|
| 834 |
+
# تنظیم LLM (مدل زبانی)
|
| 835 |
+
llm = LlamaIndexOpenAI(
|
| 836 |
+
model="gpt-4o",
|
| 837 |
+
temperature=1,
|
| 838 |
+
max_tokens=1024,
|
| 839 |
+
top_p=0.95,
|
| 840 |
+
frequency_penalty=0.4,
|
| 841 |
+
presence_penalty=0.2,
|
| 842 |
+
api_key=gapgpt_api_key,
|
| 843 |
+
api_base=GAPGPT_BASE_URL,
|
| 844 |
+
)
|
| 845 |
+
|
| 846 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 847 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 848 |
+
embed_model = OpenAIEmbedding(
|
| 849 |
+
api_key=gapgpt_api_key,
|
| 850 |
+
api_base=GAPGPT_BASE_URL,
|
| 851 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میک��د
|
| 852 |
+
)
|
| 853 |
+
|
| 854 |
+
# اعمال تنظیمات سراسری
|
| 855 |
+
Settings.llm = llm
|
| 856 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 857 |
+
|
| 858 |
+
Settings.prompt_helper = PromptHelper(
|
| 859 |
+
context_window=4096,
|
| 860 |
+
num_output=256,
|
| 861 |
+
chunk_overlap_ratio=20 / 4096,
|
| 862 |
+
tokenizer=tokenizer,
|
| 863 |
+
)
|
| 864 |
+
|
| 865 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 866 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 867 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 868 |
+
if 'api_keys' not in locals():
|
| 869 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 870 |
+
|
| 871 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 872 |
+
demo.launch(
|
| 873 |
+
server_name="127.0.0.1",
|
| 874 |
+
server_port=7860,
|
| 875 |
+
share=True
|
| 876 |
+
)
|
| 877 |
+
|
| 878 |
+
|
| 879 |
+
if __name__ == "__main__":
|
| 880 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 881 |
+
main()
|
Backup code/app_V6.py
ADDED
|
@@ -0,0 +1,854 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
):
|
| 332 |
+
chatgpt_cfg = {
|
| 333 |
+
"model": "gpt-4o",
|
| 334 |
+
"temperature": temperature,
|
| 335 |
+
"max_tokens": max_length_tokens,
|
| 336 |
+
"top_p": top_p,
|
| 337 |
+
"frequency_penalty": 0.4,
|
| 338 |
+
"presence_penalty": 0.2,
|
| 339 |
+
"n": 1,
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
if text == "":
|
| 343 |
+
# Return same history if empty input
|
| 344 |
+
return history, history, "Empty context."
|
| 345 |
+
|
| 346 |
+
# Ensure history is initialized
|
| 347 |
+
if history is None:
|
| 348 |
+
history = []
|
| 349 |
+
|
| 350 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 351 |
+
history=history,
|
| 352 |
+
query=text, # Changed name to match prompt_utils
|
| 353 |
+
user_memory=user_memory,
|
| 354 |
+
user_name=user_name,
|
| 355 |
+
user_memory_index=user_memory_index,
|
| 356 |
+
service_context=service_context,
|
| 357 |
+
api_keys=api_keys,
|
| 358 |
+
api_index=api_index,
|
| 359 |
+
meta_prompt=meta_prompt,
|
| 360 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 361 |
+
data_args=data_args,
|
| 362 |
+
boot_actual_name=boot_actual_name,
|
| 363 |
+
semantic_memory_text=semantic_memory_text,
|
| 364 |
+
query_category=query_category,
|
| 365 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 366 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
# Handle context window slicing manually if needed,
|
| 370 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 371 |
+
current_history_for_llm = history
|
| 372 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 373 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 374 |
+
|
| 375 |
+
response = chatgpt_chat(
|
| 376 |
+
prompt=text,
|
| 377 |
+
system=system_prompt,
|
| 378 |
+
history=current_history_for_llm,
|
| 379 |
+
gpt_config=chatgpt_cfg,
|
| 380 |
+
api_index=api_index,
|
| 381 |
+
)
|
| 382 |
+
|
| 383 |
+
torch.cuda.empty_cache()
|
| 384 |
+
|
| 385 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 386 |
+
new_history = history + [
|
| 387 |
+
{"role": "user", "content": text},
|
| 388 |
+
{"role": "assistant", "content": response}
|
| 389 |
+
]
|
| 390 |
+
|
| 391 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 392 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 393 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 394 |
+
if user_name:
|
| 395 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 396 |
+
# or pass a converted version. Let's try passing the new format.
|
| 397 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 398 |
+
|
| 399 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 400 |
+
return new_history, new_history, "Generating..."
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def create_gradio_interface(service_context, api_keys):
|
| 405 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 406 |
+
|
| 407 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 408 |
+
gr.HTML("""
|
| 409 |
+
<style>
|
| 410 |
+
.center-content {
|
| 411 |
+
display: flex;
|
| 412 |
+
flex-direction: column;
|
| 413 |
+
align-items: center;
|
| 414 |
+
justify-content: center;
|
| 415 |
+
}
|
| 416 |
+
/* -- استایلهای فرم ورود -- */
|
| 417 |
+
.login-box {
|
| 418 |
+
max-width: 400px !important;
|
| 419 |
+
margin: 0 auto !important;
|
| 420 |
+
width: 100% !important;
|
| 421 |
+
}
|
| 422 |
+
.login-btn, .login-btn:hover {
|
| 423 |
+
background-color: #3498db !important;
|
| 424 |
+
background-image: none !important;
|
| 425 |
+
color: white !important;
|
| 426 |
+
border: none !important;
|
| 427 |
+
}
|
| 428 |
+
/* -- استایلهای محیط چت -- */
|
| 429 |
+
.chat-box {
|
| 430 |
+
max-width: 800px !important;
|
| 431 |
+
margin: 0 auto !important;
|
| 432 |
+
width: 100% !important;
|
| 433 |
+
}
|
| 434 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 435 |
+
.mobile-button, .mobile-button:hover {
|
| 436 |
+
background-color: #3498db !important;
|
| 437 |
+
background-image: none !important;
|
| 438 |
+
color: white !important;
|
| 439 |
+
border: none !important;
|
| 440 |
+
}
|
| 441 |
+
.gr-textbox textarea {
|
| 442 |
+
font-size: 16px;
|
| 443 |
+
}
|
| 444 |
+
.gr-chatbot {
|
| 445 |
+
font-size: 15px;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 449 |
+
.slide-up {
|
| 450 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
@keyframes slideUpAnimation {
|
| 454 |
+
0% {
|
| 455 |
+
transform: translateY(0);
|
| 456 |
+
opacity: 1;
|
| 457 |
+
max-height: 1000px;
|
| 458 |
+
}
|
| 459 |
+
100% {
|
| 460 |
+
transform: translateY(-100%);
|
| 461 |
+
opacity: 0;
|
| 462 |
+
max-height: 0px;
|
| 463 |
+
overflow: hidden;
|
| 464 |
+
margin: 0 !important;
|
| 465 |
+
padding: 0 !important;
|
| 466 |
+
border: none !important;
|
| 467 |
+
}
|
| 468 |
+
}
|
| 469 |
+
</style>
|
| 470 |
+
""")
|
| 471 |
+
|
| 472 |
+
state = gr.State({
|
| 473 |
+
"history": [],
|
| 474 |
+
"user_name": None,
|
| 475 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 476 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 477 |
+
"service_context": service_context,
|
| 478 |
+
"api_keys": api_keys,
|
| 479 |
+
"api_index": 0,
|
| 480 |
+
"semantic_memory_text": "",
|
| 481 |
+
"new_conversation": True,
|
| 482 |
+
"initialized": False
|
| 483 |
+
})
|
| 484 |
+
|
| 485 |
+
# ==========================================
|
| 486 |
+
# 1. LOGIN PAGE
|
| 487 |
+
# ==========================================
|
| 488 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 489 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 490 |
+
|
| 491 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 492 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 493 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 494 |
+
|
| 495 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 496 |
+
|
| 497 |
+
with gr.Column(visible=False) as registration_fields:
|
| 498 |
+
gr.Markdown("### ✨ New User Registration")
|
| 499 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 500 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 501 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 502 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 503 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 504 |
+
|
| 505 |
+
# ==========================================
|
| 506 |
+
# 2. CHAT PAGE
|
| 507 |
+
# ==========================================
|
| 508 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 509 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 510 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 511 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 512 |
+
|
| 513 |
+
with gr.Group():
|
| 514 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 515 |
+
|
| 516 |
+
with gr.Row():
|
| 517 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 518 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 519 |
+
|
| 520 |
+
with gr.Row(equal_height=True):
|
| 521 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 522 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 523 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 524 |
+
|
| 525 |
+
# -------------------------------------------------------
|
| 526 |
+
# Internal Functions
|
| 527 |
+
# -------------------------------------------------------
|
| 528 |
+
def handle_login_check(name, state):
|
| 529 |
+
if not name.strip():
|
| 530 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 531 |
+
|
| 532 |
+
if name in memory:
|
| 533 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 534 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 535 |
+
|
| 536 |
+
new_state = state.copy()
|
| 537 |
+
new_state["user_name"] = name
|
| 538 |
+
new_state["memory"] = memory
|
| 539 |
+
new_state["initialized"] = True
|
| 540 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 541 |
+
new_state["history"] = []
|
| 542 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 543 |
+
|
| 544 |
+
# در handle_login_check و handle_register اضافه کنید:
|
| 545 |
+
print(f"[DEBUG] Login/Register for {name}")
|
| 546 |
+
print(f"[DEBUG] sessions_memory: {sessions_memory}")
|
| 547 |
+
print(f"[DEBUG] semantic_memory: {semantic_memory}")
|
| 548 |
+
print(f"[DEBUG] new_state: {new_state}")
|
| 549 |
+
|
| 550 |
+
|
| 551 |
+
|
| 552 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 553 |
+
|
| 554 |
+
return (
|
| 555 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 556 |
+
gr.update(visible=False),
|
| 557 |
+
gr.update(visible=True),
|
| 558 |
+
gr.update(visible=False, value=""),
|
| 559 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 560 |
+
gr.update(value=welcome_msg),
|
| 561 |
+
new_state
|
| 562 |
+
)
|
| 563 |
+
else:
|
| 564 |
+
return (
|
| 565 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 566 |
+
gr.update(visible=True),
|
| 567 |
+
gr.update(visible=False),
|
| 568 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 569 |
+
gr.update(),
|
| 570 |
+
gr.update(),
|
| 571 |
+
state
|
| 572 |
+
)
|
| 573 |
+
|
| 574 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 575 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 576 |
+
memory[name]["profile"] = {"age": age, "gender": gender, "occupation": occupation, "residence": residence}
|
| 577 |
+
|
| 578 |
+
new_state = state.copy()
|
| 579 |
+
new_state["user_name"] = name
|
| 580 |
+
new_state["memory"] = memory
|
| 581 |
+
new_state["initialized"] = True
|
| 582 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 583 |
+
new_state["history"] = []
|
| 584 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 585 |
+
|
| 586 |
+
|
| 587 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome {name}! Registration complete."
|
| 588 |
+
|
| 589 |
+
return (
|
| 590 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 3. افزودن کلاس انیمیشن
|
| 591 |
+
gr.update(visible=False),
|
| 592 |
+
gr.update(visible=True),
|
| 593 |
+
gr.update(visible=False, value=""),
|
| 594 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 595 |
+
gr.update(value=welcome_msg),
|
| 596 |
+
new_state
|
| 597 |
+
)
|
| 598 |
+
|
| 599 |
+
def switch_user(state):
|
| 600 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 601 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 602 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 603 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 604 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 605 |
+
# ==========================================
|
| 606 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 607 |
+
# ==========================================
|
| 608 |
+
try:
|
| 609 |
+
user_mem = state["memory"][state["user_name"]]
|
| 610 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 611 |
+
|
| 612 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 613 |
+
|
| 614 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 615 |
+
except Exception as e:
|
| 616 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 617 |
+
# ==========================================
|
| 618 |
+
|
| 619 |
+
new_state = state.copy()
|
| 620 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 621 |
+
|
| 622 |
+
return (
|
| 623 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 624 |
+
gr.update(visible=False),
|
| 625 |
+
gr.update(visible=False),
|
| 626 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 627 |
+
gr.update(value=""),
|
| 628 |
+
new_state,
|
| 629 |
+
gr.update(value=[])
|
| 630 |
+
)
|
| 631 |
+
|
| 632 |
+
def handle_chat(user_message, state):
|
| 633 |
+
if not user_message.strip():
|
| 634 |
+
print("[handle_chat] empty message")
|
| 635 |
+
print("[handle_chat] state =", state)
|
| 636 |
+
return gr.update(), state.get("history", []), state
|
| 637 |
+
|
| 638 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 639 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 640 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 641 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 642 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 643 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 644 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 645 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 646 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 647 |
+
|
| 648 |
+
user_name = state.get("user_name")
|
| 649 |
+
user_memory_index = state.get("user_memory_index")
|
| 650 |
+
user_memory = state.get("memory")
|
| 651 |
+
service_context = state.get("service_context")
|
| 652 |
+
api_index = state.get("api_index", 0)
|
| 653 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 654 |
+
|
| 655 |
+
query_category = classify_query_local(user_message)
|
| 656 |
+
print("[handle_chat] query_category =", query_category)
|
| 657 |
+
|
| 658 |
+
new_history, _, status_msg = predict_new(
|
| 659 |
+
text=user_message,
|
| 660 |
+
history=state.get("history", []),
|
| 661 |
+
top_p=0.95,
|
| 662 |
+
temperature=1.0,
|
| 663 |
+
max_length_tokens=1024,
|
| 664 |
+
max_context_length_tokens=4096,
|
| 665 |
+
user_name=user_name,
|
| 666 |
+
user_memory=user_memory,
|
| 667 |
+
user_memory_index=user_memory_index,
|
| 668 |
+
service_context=service_context,
|
| 669 |
+
api_index=api_index,
|
| 670 |
+
semantic_memory_text=semantic_memory_text,
|
| 671 |
+
query_category=query_category
|
| 672 |
+
)
|
| 673 |
+
|
| 674 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 675 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 676 |
+
|
| 677 |
+
state["history"] = new_history
|
| 678 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 679 |
+
|
| 680 |
+
return "", new_history, state
|
| 681 |
+
|
| 682 |
+
def clear_history(state):
|
| 683 |
+
state["history"] = []
|
| 684 |
+
return [], state
|
| 685 |
+
|
| 686 |
+
def handle_new_session(state):
|
| 687 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 688 |
+
user_name = state.get("user_name")
|
| 689 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 690 |
+
print("Error: User not logged in or memory missing.")
|
| 691 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 692 |
+
return [], state
|
| 693 |
+
|
| 694 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 695 |
+
user_data = state["memory"][user_name]
|
| 696 |
+
|
| 697 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 698 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 699 |
+
last_session = user_data["sessions"][-1]
|
| 700 |
+
|
| 701 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 702 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 703 |
+
session_date = last_session.get("date", "")
|
| 704 |
+
session_id = last_session.get("session_id", 0)
|
| 705 |
+
|
| 706 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 707 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 708 |
+
|
| 709 |
+
if "episodic_memory" not in user_data:
|
| 710 |
+
user_data["episodic_memory"] = []
|
| 711 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 712 |
+
|
| 713 |
+
# ==========================================
|
| 714 |
+
# بهروزرسانی حافظه سمانتیک
|
| 715 |
+
# ==========================================
|
| 716 |
+
try:
|
| 717 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 718 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 719 |
+
|
| 720 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 721 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 722 |
+
|
| 723 |
+
# ذخیره دیتای جدید
|
| 724 |
+
user_data["semantic_memory"] = updated_semantic
|
| 725 |
+
except Exception as e:
|
| 726 |
+
print(f"Error updating semantic memory: {e}")
|
| 727 |
+
# ==========================================
|
| 728 |
+
|
| 729 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 730 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 731 |
+
|
| 732 |
+
new_session = {
|
| 733 |
+
"session_id": new_session_id,
|
| 734 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 735 |
+
"conversation": []
|
| 736 |
+
}
|
| 737 |
+
|
| 738 |
+
if "sessions" not in user_data:
|
| 739 |
+
user_data["sessions"] = []
|
| 740 |
+
|
| 741 |
+
user_data["sessions"].append(new_session)
|
| 742 |
+
|
| 743 |
+
# پاک کردن تاریخچه چت در state
|
| 744 |
+
state["history"] = []
|
| 745 |
+
|
| 746 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 747 |
+
return [], state
|
| 748 |
+
|
| 749 |
+
check_user_btn.click(
|
| 750 |
+
handle_login_check,
|
| 751 |
+
inputs=[username_input, state],
|
| 752 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 753 |
+
)
|
| 754 |
+
|
| 755 |
+
register_btn.click(
|
| 756 |
+
handle_register,
|
| 757 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 758 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 759 |
+
)
|
| 760 |
+
|
| 761 |
+
switch_user_btn.click(
|
| 762 |
+
switch_user,
|
| 763 |
+
inputs=[state],
|
| 764 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
submit_btn.click(
|
| 768 |
+
handle_chat,
|
| 769 |
+
inputs=[user_input, state],
|
| 770 |
+
outputs=[user_input, chatbot, state]
|
| 771 |
+
)
|
| 772 |
+
|
| 773 |
+
user_input.submit(
|
| 774 |
+
handle_chat,
|
| 775 |
+
inputs=[user_input, state],
|
| 776 |
+
outputs=[user_input, chatbot, state]
|
| 777 |
+
)
|
| 778 |
+
|
| 779 |
+
clear_btn.click(
|
| 780 |
+
clear_history,
|
| 781 |
+
inputs=[state],
|
| 782 |
+
outputs=[chatbot, state]
|
| 783 |
+
)
|
| 784 |
+
|
| 785 |
+
# تغییر از clear_history به handle_new_session
|
| 786 |
+
new_session_btn.click(
|
| 787 |
+
handle_new_session,
|
| 788 |
+
inputs=[state],
|
| 789 |
+
outputs=[chatbot, state]
|
| 790 |
+
|
| 791 |
+
|
| 792 |
+
)
|
| 793 |
+
|
| 794 |
+
return demo
|
| 795 |
+
|
| 796 |
+
|
| 797 |
+
def main():
|
| 798 |
+
"""Main function to initialize and launch the interface."""
|
| 799 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 800 |
+
|
| 801 |
+
if not gapgpt_api_key:
|
| 802 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 803 |
+
else:
|
| 804 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 805 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 806 |
+
|
| 807 |
+
# تنظیم LLM (مدل زبانی)
|
| 808 |
+
llm = LlamaIndexOpenAI(
|
| 809 |
+
model="gpt-4o",
|
| 810 |
+
temperature=1,
|
| 811 |
+
max_tokens=1024,
|
| 812 |
+
top_p=0.95,
|
| 813 |
+
frequency_penalty=0.4,
|
| 814 |
+
presence_penalty=0.2,
|
| 815 |
+
api_key=gapgpt_api_key,
|
| 816 |
+
api_base=GAPGPT_BASE_URL,
|
| 817 |
+
)
|
| 818 |
+
|
| 819 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 820 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 821 |
+
embed_model = OpenAIEmbedding(
|
| 822 |
+
api_key=gapgpt_api_key,
|
| 823 |
+
api_base=GAPGPT_BASE_URL,
|
| 824 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 825 |
+
)
|
| 826 |
+
|
| 827 |
+
# اعمال تنظیمات سراسری
|
| 828 |
+
Settings.llm = llm
|
| 829 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 830 |
+
|
| 831 |
+
Settings.prompt_helper = PromptHelper(
|
| 832 |
+
context_window=4096,
|
| 833 |
+
num_output=256,
|
| 834 |
+
chunk_overlap_ratio=20 / 4096,
|
| 835 |
+
tokenizer=tokenizer,
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 839 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 840 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 841 |
+
if 'api_keys' not in locals():
|
| 842 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 843 |
+
|
| 844 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 845 |
+
demo.launch(
|
| 846 |
+
server_name="127.0.0.1",
|
| 847 |
+
server_port=7860,
|
| 848 |
+
share=True
|
| 849 |
+
)
|
| 850 |
+
|
| 851 |
+
|
| 852 |
+
if __name__ == "__main__":
|
| 853 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 854 |
+
main()
|
Backup code/app_V7.py
ADDED
|
@@ -0,0 +1,901 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
):
|
| 332 |
+
chatgpt_cfg = {
|
| 333 |
+
"model": "gpt-4o",
|
| 334 |
+
"temperature": temperature,
|
| 335 |
+
"max_tokens": max_length_tokens,
|
| 336 |
+
"top_p": top_p,
|
| 337 |
+
"frequency_penalty": 0.4,
|
| 338 |
+
"presence_penalty": 0.2,
|
| 339 |
+
"n": 1,
|
| 340 |
+
}
|
| 341 |
+
|
| 342 |
+
if text == "":
|
| 343 |
+
# Return same history if empty input
|
| 344 |
+
return history, history, "Empty context."
|
| 345 |
+
|
| 346 |
+
# Ensure history is initialized
|
| 347 |
+
if history is None:
|
| 348 |
+
history = []
|
| 349 |
+
|
| 350 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 351 |
+
history=history,
|
| 352 |
+
query=text, # Changed name to match prompt_utils
|
| 353 |
+
user_memory=user_memory,
|
| 354 |
+
user_name=user_name,
|
| 355 |
+
user_memory_index=user_memory_index,
|
| 356 |
+
service_context=service_context,
|
| 357 |
+
api_keys=api_keys,
|
| 358 |
+
api_index=api_index,
|
| 359 |
+
meta_prompt=meta_prompt,
|
| 360 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 361 |
+
data_args=data_args,
|
| 362 |
+
boot_actual_name=boot_actual_name,
|
| 363 |
+
semantic_memory_text=semantic_memory_text,
|
| 364 |
+
query_category=query_category,
|
| 365 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 366 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
# Handle context window slicing manually if needed,
|
| 370 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 371 |
+
current_history_for_llm = history
|
| 372 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 373 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 374 |
+
|
| 375 |
+
response = chatgpt_chat(
|
| 376 |
+
prompt=text,
|
| 377 |
+
system=system_prompt,
|
| 378 |
+
history=current_history_for_llm,
|
| 379 |
+
gpt_config=chatgpt_cfg,
|
| 380 |
+
api_index=api_index,
|
| 381 |
+
)
|
| 382 |
+
|
| 383 |
+
torch.cuda.empty_cache()
|
| 384 |
+
|
| 385 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 386 |
+
new_history = history + [
|
| 387 |
+
{"role": "user", "content": text},
|
| 388 |
+
{"role": "assistant", "content": response}
|
| 389 |
+
]
|
| 390 |
+
|
| 391 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 392 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 393 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 394 |
+
if user_name:
|
| 395 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 396 |
+
# or pass a converted version. Let's try passing the new format.
|
| 397 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 398 |
+
|
| 399 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 400 |
+
return new_history, new_history, "Generating..."
|
| 401 |
+
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def create_gradio_interface(service_context, api_keys):
|
| 405 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 406 |
+
|
| 407 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 408 |
+
gr.HTML("""
|
| 409 |
+
<style>
|
| 410 |
+
.center-content {
|
| 411 |
+
display: flex;
|
| 412 |
+
flex-direction: column;
|
| 413 |
+
align-items: center;
|
| 414 |
+
justify-content: center;
|
| 415 |
+
}
|
| 416 |
+
/* -- استایلهای فرم ورود -- */
|
| 417 |
+
.login-box {
|
| 418 |
+
max-width: 400px !important;
|
| 419 |
+
margin: 0 auto !important;
|
| 420 |
+
width: 100% !important;
|
| 421 |
+
}
|
| 422 |
+
.login-btn, .login-btn:hover {
|
| 423 |
+
background-color: #3498db !important;
|
| 424 |
+
background-image: none !important;
|
| 425 |
+
color: white !important;
|
| 426 |
+
border: none !important;
|
| 427 |
+
}
|
| 428 |
+
/* -- استایلهای محیط چت -- */
|
| 429 |
+
.chat-box {
|
| 430 |
+
max-width: 800px !important;
|
| 431 |
+
margin: 0 auto !important;
|
| 432 |
+
width: 100% !important;
|
| 433 |
+
}
|
| 434 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 435 |
+
.mobile-button, .mobile-button:hover {
|
| 436 |
+
background-color: #3498db !important;
|
| 437 |
+
background-image: none !important;
|
| 438 |
+
color: white !important;
|
| 439 |
+
border: none !important;
|
| 440 |
+
}
|
| 441 |
+
.gr-textbox textarea {
|
| 442 |
+
font-size: 16px;
|
| 443 |
+
}
|
| 444 |
+
.gr-chatbot {
|
| 445 |
+
font-size: 15px;
|
| 446 |
+
}
|
| 447 |
+
|
| 448 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 449 |
+
.slide-up {
|
| 450 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 451 |
+
}
|
| 452 |
+
|
| 453 |
+
@keyframes slideUpAnimation {
|
| 454 |
+
0% {
|
| 455 |
+
transform: translateY(0);
|
| 456 |
+
opacity: 1;
|
| 457 |
+
max-height: 1000px;
|
| 458 |
+
}
|
| 459 |
+
100% {
|
| 460 |
+
transform: translateY(-100%);
|
| 461 |
+
opacity: 0;
|
| 462 |
+
max-height: 0px;
|
| 463 |
+
overflow: hidden;
|
| 464 |
+
margin: 0 !important;
|
| 465 |
+
padding: 0 !important;
|
| 466 |
+
border: none !important;
|
| 467 |
+
}
|
| 468 |
+
}
|
| 469 |
+
</style>
|
| 470 |
+
""")
|
| 471 |
+
|
| 472 |
+
state = gr.State({
|
| 473 |
+
"history": [],
|
| 474 |
+
"user_name": None,
|
| 475 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 476 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 477 |
+
"service_context": service_context,
|
| 478 |
+
"api_keys": api_keys,
|
| 479 |
+
"api_index": 0,
|
| 480 |
+
"semantic_memory_text": "",
|
| 481 |
+
"new_conversation": True,
|
| 482 |
+
"initialized": False
|
| 483 |
+
})
|
| 484 |
+
|
| 485 |
+
# ==========================================
|
| 486 |
+
# 1. LOGIN PAGE
|
| 487 |
+
# ==========================================
|
| 488 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 489 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 490 |
+
|
| 491 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 492 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 493 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 494 |
+
|
| 495 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 496 |
+
|
| 497 |
+
with gr.Column(visible=False) as registration_fields:
|
| 498 |
+
gr.Markdown("### ✨ New User Registration")
|
| 499 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 500 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 501 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 502 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 503 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 504 |
+
|
| 505 |
+
# ==========================================
|
| 506 |
+
# 2. CHAT PAGE
|
| 507 |
+
# ==========================================
|
| 508 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 509 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 510 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 511 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 512 |
+
|
| 513 |
+
with gr.Group():
|
| 514 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 515 |
+
|
| 516 |
+
with gr.Row():
|
| 517 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 518 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 519 |
+
|
| 520 |
+
with gr.Row(equal_height=True):
|
| 521 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 522 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 523 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 524 |
+
|
| 525 |
+
# -------------------------------------------------------
|
| 526 |
+
# Internal Functions
|
| 527 |
+
# -------------------------------------------------------
|
| 528 |
+
def handle_login_check(name, state):
|
| 529 |
+
if not name.strip():
|
| 530 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 531 |
+
|
| 532 |
+
if name in memory:
|
| 533 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 534 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 535 |
+
|
| 536 |
+
new_state = state.copy()
|
| 537 |
+
new_state["user_name"] = name
|
| 538 |
+
new_state["memory"] = memory
|
| 539 |
+
new_state["initialized"] = True
|
| 540 |
+
new_state["semantic_memory_text"] = semantic_memory
|
| 541 |
+
new_state["history"] = []
|
| 542 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
|
| 546 |
+
|
| 547 |
+
|
| 548 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 549 |
+
|
| 550 |
+
return (
|
| 551 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 552 |
+
gr.update(visible=False),
|
| 553 |
+
gr.update(visible=True),
|
| 554 |
+
gr.update(visible=False, value=""),
|
| 555 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 556 |
+
gr.update(value=welcome_msg),
|
| 557 |
+
new_state
|
| 558 |
+
)
|
| 559 |
+
else:
|
| 560 |
+
return (
|
| 561 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 562 |
+
gr.update(visible=True),
|
| 563 |
+
gr.update(visible=False),
|
| 564 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 565 |
+
gr.update(),
|
| 566 |
+
gr.update(),
|
| 567 |
+
state
|
| 568 |
+
)
|
| 569 |
+
|
| 570 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 571 |
+
name = str(name).strip()
|
| 572 |
+
|
| 573 |
+
if not name:
|
| 574 |
+
raise gr.Error("Please enter a valid user name.")
|
| 575 |
+
|
| 576 |
+
# Registration is only for new users.
|
| 577 |
+
if name in memory:
|
| 578 |
+
raise gr.Error(
|
| 579 |
+
f"User '{name}' already exists. Please use the login form."
|
| 580 |
+
)
|
| 581 |
+
|
| 582 |
+
# Create the user before trying to build or load their indices.
|
| 583 |
+
memory[name] = {
|
| 584 |
+
"profile": {
|
| 585 |
+
"age": age,
|
| 586 |
+
"gender": gender,
|
| 587 |
+
"occupation": occupation,
|
| 588 |
+
"residence": residence,
|
| 589 |
+
},
|
| 590 |
+
"sessions": [],
|
| 591 |
+
"episodic_memory": [],
|
| 592 |
+
"semantic_memory": {},
|
| 593 |
+
}
|
| 594 |
+
|
| 595 |
+
try:
|
| 596 |
+
(
|
| 597 |
+
_,
|
| 598 |
+
user_memory,
|
| 599 |
+
sessions_memory,
|
| 600 |
+
episodic_memory,
|
| 601 |
+
semantic_memory,
|
| 602 |
+
) = enter_name_llamaindex(
|
| 603 |
+
name=name,
|
| 604 |
+
memory=memory,
|
| 605 |
+
data_args=data_args,
|
| 606 |
+
update_memory_index=True,
|
| 607 |
+
)
|
| 608 |
+
except Exception:
|
| 609 |
+
# Avoid leaving a partially registered user in memory.
|
| 610 |
+
memory.pop(name, None)
|
| 611 |
+
raise
|
| 612 |
+
|
| 613 |
+
new_state = dict(state or {})
|
| 614 |
+
new_state.update(
|
| 615 |
+
{
|
| 616 |
+
"user_name": name,
|
| 617 |
+
"memory": memory,
|
| 618 |
+
"initialized": True,
|
| 619 |
+
"history": [],
|
| 620 |
+
"semantic_memory_text": semantic_memory,
|
| 621 |
+
"user_memory_index": sessions_memory,
|
| 622 |
+
"episodic_memory_index": episodic_memory,
|
| 623 |
+
"semantic_memory_index": semantic_memory,
|
| 624 |
+
}
|
| 625 |
+
)
|
| 626 |
+
|
| 627 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 628 |
+
|
| 629 |
+
return (
|
| 630 |
+
gr.update(
|
| 631 |
+
elem_classes=["center-content", "slide-up"]
|
| 632 |
+
),
|
| 633 |
+
gr.update(visible=False),
|
| 634 |
+
gr.update(visible=True),
|
| 635 |
+
gr.update(visible=False, value=""),
|
| 636 |
+
gr.update(
|
| 637 |
+
value=(
|
| 638 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 639 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 640 |
+
)
|
| 641 |
+
),
|
| 642 |
+
gr.update(value=welcome_msg),
|
| 643 |
+
new_state,
|
| 644 |
+
)
|
| 645 |
+
|
| 646 |
+
def switch_user(state):
|
| 647 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 648 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 649 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 650 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 651 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 652 |
+
# ==========================================
|
| 653 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 654 |
+
# ==========================================
|
| 655 |
+
try:
|
| 656 |
+
user_mem = state["memory"][state["user_name"]]
|
| 657 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 658 |
+
|
| 659 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 660 |
+
|
| 661 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 662 |
+
except Exception as e:
|
| 663 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 664 |
+
# ==========================================
|
| 665 |
+
|
| 666 |
+
new_state = state.copy()
|
| 667 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 668 |
+
|
| 669 |
+
return (
|
| 670 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 671 |
+
gr.update(visible=False),
|
| 672 |
+
gr.update(visible=False),
|
| 673 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 674 |
+
gr.update(value=""),
|
| 675 |
+
new_state,
|
| 676 |
+
gr.update(value=[])
|
| 677 |
+
)
|
| 678 |
+
|
| 679 |
+
def handle_chat(user_message, state):
|
| 680 |
+
if not user_message.strip():
|
| 681 |
+
print("[handle_chat] empty message")
|
| 682 |
+
print("[handle_chat] state =", state)
|
| 683 |
+
return gr.update(), state.get("history", []), state
|
| 684 |
+
|
| 685 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 686 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 687 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 688 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 689 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 690 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 691 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 692 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 693 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 694 |
+
|
| 695 |
+
user_name = state.get("user_name")
|
| 696 |
+
user_memory_index = state.get("user_memory_index")
|
| 697 |
+
user_memory = state.get("memory")
|
| 698 |
+
service_context = state.get("service_context")
|
| 699 |
+
api_index = state.get("api_index", 0)
|
| 700 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 701 |
+
|
| 702 |
+
query_category = classify_query_local(user_message)
|
| 703 |
+
print("[handle_chat] query_category =", query_category)
|
| 704 |
+
|
| 705 |
+
new_history, _, status_msg = predict_new(
|
| 706 |
+
text=user_message,
|
| 707 |
+
history=state.get("history", []),
|
| 708 |
+
top_p=0.95,
|
| 709 |
+
temperature=1.0,
|
| 710 |
+
max_length_tokens=1024,
|
| 711 |
+
max_context_length_tokens=4096,
|
| 712 |
+
user_name=user_name,
|
| 713 |
+
user_memory=user_memory,
|
| 714 |
+
user_memory_index=user_memory_index,
|
| 715 |
+
service_context=service_context,
|
| 716 |
+
api_index=api_index,
|
| 717 |
+
semantic_memory_text=semantic_memory_text,
|
| 718 |
+
query_category=query_category
|
| 719 |
+
)
|
| 720 |
+
|
| 721 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 722 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 723 |
+
|
| 724 |
+
state["history"] = new_history
|
| 725 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 726 |
+
|
| 727 |
+
return "", new_history, state
|
| 728 |
+
|
| 729 |
+
def clear_history(state):
|
| 730 |
+
state["history"] = []
|
| 731 |
+
return [], state
|
| 732 |
+
|
| 733 |
+
def handle_new_session(state):
|
| 734 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 735 |
+
user_name = state.get("user_name")
|
| 736 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 737 |
+
print("Error: User not logged in or memory missing.")
|
| 738 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 739 |
+
return [], state
|
| 740 |
+
|
| 741 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 742 |
+
user_data = state["memory"][user_name]
|
| 743 |
+
|
| 744 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 745 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 746 |
+
last_session = user_data["sessions"][-1]
|
| 747 |
+
|
| 748 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 749 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 750 |
+
session_date = last_session.get("date", "")
|
| 751 |
+
session_id = last_session.get("session_id", 0)
|
| 752 |
+
|
| 753 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 754 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 755 |
+
|
| 756 |
+
if "episodic_memory" not in user_data:
|
| 757 |
+
user_data["episodic_memory"] = []
|
| 758 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 759 |
+
|
| 760 |
+
# ==========================================
|
| 761 |
+
# بهروزرسانی حافظه سمانتیک
|
| 762 |
+
# ==========================================
|
| 763 |
+
try:
|
| 764 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 765 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 766 |
+
|
| 767 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 768 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 769 |
+
|
| 770 |
+
# ذخیره دیتای جدید
|
| 771 |
+
user_data["semantic_memory"] = updated_semantic
|
| 772 |
+
except Exception as e:
|
| 773 |
+
print(f"Error updating semantic memory: {e}")
|
| 774 |
+
# ==========================================
|
| 775 |
+
|
| 776 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 777 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 778 |
+
|
| 779 |
+
new_session = {
|
| 780 |
+
"session_id": new_session_id,
|
| 781 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 782 |
+
"conversation": []
|
| 783 |
+
}
|
| 784 |
+
|
| 785 |
+
if "sessions" not in user_data:
|
| 786 |
+
user_data["sessions"] = []
|
| 787 |
+
|
| 788 |
+
user_data["sessions"].append(new_session)
|
| 789 |
+
|
| 790 |
+
# پاک کردن تاریخچه چت در state
|
| 791 |
+
state["history"] = []
|
| 792 |
+
|
| 793 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 794 |
+
return [], state
|
| 795 |
+
|
| 796 |
+
check_user_btn.click(
|
| 797 |
+
handle_login_check,
|
| 798 |
+
inputs=[username_input, state],
|
| 799 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 800 |
+
)
|
| 801 |
+
|
| 802 |
+
register_btn.click(
|
| 803 |
+
handle_register,
|
| 804 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 805 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 806 |
+
)
|
| 807 |
+
|
| 808 |
+
switch_user_btn.click(
|
| 809 |
+
switch_user,
|
| 810 |
+
inputs=[state],
|
| 811 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 812 |
+
)
|
| 813 |
+
|
| 814 |
+
submit_btn.click(
|
| 815 |
+
handle_chat,
|
| 816 |
+
inputs=[user_input, state],
|
| 817 |
+
outputs=[user_input, chatbot, state]
|
| 818 |
+
)
|
| 819 |
+
|
| 820 |
+
user_input.submit(
|
| 821 |
+
handle_chat,
|
| 822 |
+
inputs=[user_input, state],
|
| 823 |
+
outputs=[user_input, chatbot, state]
|
| 824 |
+
)
|
| 825 |
+
|
| 826 |
+
clear_btn.click(
|
| 827 |
+
clear_history,
|
| 828 |
+
inputs=[state],
|
| 829 |
+
outputs=[chatbot, state]
|
| 830 |
+
)
|
| 831 |
+
|
| 832 |
+
# تغییر از clear_history به handle_new_session
|
| 833 |
+
new_session_btn.click(
|
| 834 |
+
handle_new_session,
|
| 835 |
+
inputs=[state],
|
| 836 |
+
outputs=[chatbot, state]
|
| 837 |
+
|
| 838 |
+
|
| 839 |
+
)
|
| 840 |
+
|
| 841 |
+
return demo
|
| 842 |
+
|
| 843 |
+
|
| 844 |
+
def main():
|
| 845 |
+
"""Main function to initialize and launch the interface."""
|
| 846 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 847 |
+
|
| 848 |
+
if not gapgpt_api_key:
|
| 849 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 850 |
+
else:
|
| 851 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 852 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 853 |
+
|
| 854 |
+
# تنظیم LLM (مدل زبانی)
|
| 855 |
+
llm = LlamaIndexOpenAI(
|
| 856 |
+
model="gpt-4o",
|
| 857 |
+
temperature=1,
|
| 858 |
+
max_tokens=1024,
|
| 859 |
+
top_p=0.95,
|
| 860 |
+
frequency_penalty=0.4,
|
| 861 |
+
presence_penalty=0.2,
|
| 862 |
+
api_key=gapgpt_api_key,
|
| 863 |
+
api_base=GAPGPT_BASE_URL,
|
| 864 |
+
)
|
| 865 |
+
|
| 866 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 867 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 868 |
+
embed_model = OpenAIEmbedding(
|
| 869 |
+
api_key=gapgpt_api_key,
|
| 870 |
+
api_base=GAPGPT_BASE_URL,
|
| 871 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 872 |
+
)
|
| 873 |
+
|
| 874 |
+
# اعمال تنظیمات سراسری
|
| 875 |
+
Settings.llm = llm
|
| 876 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 877 |
+
|
| 878 |
+
Settings.prompt_helper = PromptHelper(
|
| 879 |
+
context_window=4096,
|
| 880 |
+
num_output=256,
|
| 881 |
+
chunk_overlap_ratio=20 / 4096,
|
| 882 |
+
tokenizer=tokenizer,
|
| 883 |
+
)
|
| 884 |
+
|
| 885 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 886 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 887 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 888 |
+
if 'api_keys' not in locals():
|
| 889 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 890 |
+
|
| 891 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 892 |
+
demo.launch(
|
| 893 |
+
server_name="127.0.0.1",
|
| 894 |
+
server_port=7860,
|
| 895 |
+
share=True
|
| 896 |
+
)
|
| 897 |
+
|
| 898 |
+
|
| 899 |
+
if __name__ == "__main__":
|
| 900 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 901 |
+
main()
|
Backup code/app_V8.py
ADDED
|
@@ -0,0 +1,907 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
):
|
| 334 |
+
chatgpt_cfg = {
|
| 335 |
+
"model": "gpt-4o",
|
| 336 |
+
"temperature": temperature,
|
| 337 |
+
"max_tokens": max_length_tokens,
|
| 338 |
+
"top_p": top_p,
|
| 339 |
+
"frequency_penalty": 0.4,
|
| 340 |
+
"presence_penalty": 0.2,
|
| 341 |
+
"n": 1,
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
if text == "":
|
| 345 |
+
# Return same history if empty input
|
| 346 |
+
return history, history, "Empty context."
|
| 347 |
+
|
| 348 |
+
# Ensure history is initialized
|
| 349 |
+
if history is None:
|
| 350 |
+
history = []
|
| 351 |
+
|
| 352 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 353 |
+
history=history,
|
| 354 |
+
query=text, # Changed name to match prompt_utils
|
| 355 |
+
user_memory=user_memory,
|
| 356 |
+
user_name=user_name,
|
| 357 |
+
user_memory_index=user_memory_index,
|
| 358 |
+
service_context=service_context,
|
| 359 |
+
api_keys=api_keys,
|
| 360 |
+
api_index=api_index,
|
| 361 |
+
meta_prompt=meta_prompt,
|
| 362 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 363 |
+
data_args=data_args,
|
| 364 |
+
boot_actual_name=boot_actual_name,
|
| 365 |
+
semantic_memory_text=semantic_memory_text,
|
| 366 |
+
query_category=query_category,
|
| 367 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 368 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
# Handle context window slicing manually if needed,
|
| 372 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 373 |
+
current_history_for_llm = history
|
| 374 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 375 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 376 |
+
|
| 377 |
+
response = chatgpt_chat(
|
| 378 |
+
prompt=text,
|
| 379 |
+
system=system_prompt,
|
| 380 |
+
history=current_history_for_llm,
|
| 381 |
+
gpt_config=chatgpt_cfg,
|
| 382 |
+
api_index=api_index,
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
torch.cuda.empty_cache()
|
| 386 |
+
|
| 387 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 388 |
+
new_history = history + [
|
| 389 |
+
{"role": "user", "content": text},
|
| 390 |
+
{"role": "assistant", "content": response}
|
| 391 |
+
]
|
| 392 |
+
|
| 393 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 394 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 395 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 396 |
+
if user_name:
|
| 397 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 398 |
+
# or pass a converted version. Let's try passing the new format.
|
| 399 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 400 |
+
|
| 401 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 402 |
+
return new_history, new_history, "Generating..."
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
def create_gradio_interface(service_context, api_keys):
|
| 407 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 408 |
+
|
| 409 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 410 |
+
gr.HTML("""
|
| 411 |
+
<style>
|
| 412 |
+
.center-content {
|
| 413 |
+
display: flex;
|
| 414 |
+
flex-direction: column;
|
| 415 |
+
align-items: center;
|
| 416 |
+
justify-content: center;
|
| 417 |
+
}
|
| 418 |
+
/* -- استایلهای فرم ورود -- */
|
| 419 |
+
.login-box {
|
| 420 |
+
max-width: 400px !important;
|
| 421 |
+
margin: 0 auto !important;
|
| 422 |
+
width: 100% !important;
|
| 423 |
+
}
|
| 424 |
+
.login-btn, .login-btn:hover {
|
| 425 |
+
background-color: #3498db !important;
|
| 426 |
+
background-image: none !important;
|
| 427 |
+
color: white !important;
|
| 428 |
+
border: none !important;
|
| 429 |
+
}
|
| 430 |
+
/* -- استایلهای محیط چت -- */
|
| 431 |
+
.chat-box {
|
| 432 |
+
max-width: 800px !important;
|
| 433 |
+
margin: 0 auto !important;
|
| 434 |
+
width: 100% !important;
|
| 435 |
+
}
|
| 436 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 437 |
+
.mobile-button, .mobile-button:hover {
|
| 438 |
+
background-color: #3498db !important;
|
| 439 |
+
background-image: none !important;
|
| 440 |
+
color: white !important;
|
| 441 |
+
border: none !important;
|
| 442 |
+
}
|
| 443 |
+
.gr-textbox textarea {
|
| 444 |
+
font-size: 16px;
|
| 445 |
+
}
|
| 446 |
+
.gr-chatbot {
|
| 447 |
+
font-size: 15px;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 451 |
+
.slide-up {
|
| 452 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
@keyframes slideUpAnimation {
|
| 456 |
+
0% {
|
| 457 |
+
transform: translateY(0);
|
| 458 |
+
opacity: 1;
|
| 459 |
+
max-height: 1000px;
|
| 460 |
+
}
|
| 461 |
+
100% {
|
| 462 |
+
transform: translateY(-100%);
|
| 463 |
+
opacity: 0;
|
| 464 |
+
max-height: 0px;
|
| 465 |
+
overflow: hidden;
|
| 466 |
+
margin: 0 !important;
|
| 467 |
+
padding: 0 !important;
|
| 468 |
+
border: none !important;
|
| 469 |
+
}
|
| 470 |
+
}
|
| 471 |
+
</style>
|
| 472 |
+
""")
|
| 473 |
+
|
| 474 |
+
state = gr.State({
|
| 475 |
+
"history": [],
|
| 476 |
+
"user_name": None,
|
| 477 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 478 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 479 |
+
"service_context": service_context,
|
| 480 |
+
"api_keys": api_keys,
|
| 481 |
+
"api_index": 0,
|
| 482 |
+
"semantic_memory_text": "",
|
| 483 |
+
"new_conversation": True,
|
| 484 |
+
"initialized": False
|
| 485 |
+
})
|
| 486 |
+
|
| 487 |
+
# ==========================================
|
| 488 |
+
# 1. LOGIN PAGE
|
| 489 |
+
# ==========================================
|
| 490 |
+
with gr.Column(visible=True, elem_classes=["center-content"]) as login_page:
|
| 491 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 492 |
+
|
| 493 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]):
|
| 494 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 495 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 496 |
+
|
| 497 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 498 |
+
|
| 499 |
+
with gr.Column(visible=False) as registration_fields:
|
| 500 |
+
gr.Markdown("### ✨ New User Registration")
|
| 501 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 502 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 503 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 504 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 505 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 506 |
+
|
| 507 |
+
# ==========================================
|
| 508 |
+
# 2. CHAT PAGE
|
| 509 |
+
# ==========================================
|
| 510 |
+
with gr.Column(visible=False, elem_classes=["center-content"]) as chat_page:
|
| 511 |
+
with gr.Column(elem_classes=["chat-box"]):
|
| 512 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 513 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 514 |
+
|
| 515 |
+
with gr.Group():
|
| 516 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 517 |
+
|
| 518 |
+
with gr.Row():
|
| 519 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 520 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 521 |
+
|
| 522 |
+
with gr.Row(equal_height=True):
|
| 523 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 524 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 525 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 526 |
+
|
| 527 |
+
# -------------------------------------------------------
|
| 528 |
+
# Internal Functions
|
| 529 |
+
# -------------------------------------------------------
|
| 530 |
+
def handle_login_check(name, state):
|
| 531 |
+
if not name.strip():
|
| 532 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 533 |
+
|
| 534 |
+
if name in memory:
|
| 535 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 536 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 537 |
+
|
| 538 |
+
new_state = state.copy()
|
| 539 |
+
new_state["user_name"] = name
|
| 540 |
+
new_state["memory"] = memory
|
| 541 |
+
new_state["initialized"] = True
|
| 542 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 543 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 544 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 545 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 546 |
+
new_state["history"] = []
|
| 547 |
+
|
| 548 |
+
|
| 549 |
+
|
| 550 |
+
|
| 551 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 552 |
+
|
| 553 |
+
return (
|
| 554 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 555 |
+
gr.update(visible=False),
|
| 556 |
+
gr.update(visible=True),
|
| 557 |
+
gr.update(visible=False, value=""),
|
| 558 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 559 |
+
gr.update(value=welcome_msg),
|
| 560 |
+
new_state
|
| 561 |
+
)
|
| 562 |
+
else:
|
| 563 |
+
return (
|
| 564 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 565 |
+
gr.update(visible=True),
|
| 566 |
+
gr.update(visible=False),
|
| 567 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 568 |
+
gr.update(),
|
| 569 |
+
gr.update(),
|
| 570 |
+
state
|
| 571 |
+
)
|
| 572 |
+
|
| 573 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 574 |
+
name = str(name).strip()
|
| 575 |
+
|
| 576 |
+
if not name:
|
| 577 |
+
raise gr.Error("Please enter a valid user name.")
|
| 578 |
+
|
| 579 |
+
# Registration is only for new users.
|
| 580 |
+
if name in memory:
|
| 581 |
+
raise gr.Error(
|
| 582 |
+
f"User '{name}' already exists. Please use the login form."
|
| 583 |
+
)
|
| 584 |
+
|
| 585 |
+
# Create the user before trying to build or load their indices.
|
| 586 |
+
memory[name] = {
|
| 587 |
+
"profile": {
|
| 588 |
+
"age": age,
|
| 589 |
+
"gender": gender,
|
| 590 |
+
"occupation": occupation,
|
| 591 |
+
"residence": residence,
|
| 592 |
+
},
|
| 593 |
+
"sessions": [],
|
| 594 |
+
"episodic_memory": [],
|
| 595 |
+
"semantic_memory": {},
|
| 596 |
+
}
|
| 597 |
+
|
| 598 |
+
try:
|
| 599 |
+
(
|
| 600 |
+
_,
|
| 601 |
+
user_memory,
|
| 602 |
+
sessions_memory,
|
| 603 |
+
episodic_memory,
|
| 604 |
+
semantic_memory,
|
| 605 |
+
) = enter_name_llamaindex(
|
| 606 |
+
name=name,
|
| 607 |
+
memory=memory,
|
| 608 |
+
data_args=data_args,
|
| 609 |
+
update_memory_index=True,
|
| 610 |
+
)
|
| 611 |
+
except Exception:
|
| 612 |
+
# Avoid leaving a partially registered user in memory.
|
| 613 |
+
memory.pop(name, None)
|
| 614 |
+
raise
|
| 615 |
+
|
| 616 |
+
new_state = dict(state or {})
|
| 617 |
+
new_state.update(
|
| 618 |
+
{
|
| 619 |
+
"user_name": name,
|
| 620 |
+
"memory": memory,
|
| 621 |
+
"initialized": True,
|
| 622 |
+
"history": [],
|
| 623 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 624 |
+
"user_memory_index": sessions_memory,
|
| 625 |
+
"episodic_memory_index": episodic_memory,
|
| 626 |
+
"semantic_memory_index": semantic_memory,
|
| 627 |
+
}
|
| 628 |
+
)
|
| 629 |
+
|
| 630 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 631 |
+
|
| 632 |
+
return (
|
| 633 |
+
gr.update(
|
| 634 |
+
elem_classes=["center-content", "slide-up"]
|
| 635 |
+
),
|
| 636 |
+
gr.update(visible=False),
|
| 637 |
+
gr.update(visible=True),
|
| 638 |
+
gr.update(visible=False, value=""),
|
| 639 |
+
gr.update(
|
| 640 |
+
value=(
|
| 641 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 642 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 643 |
+
)
|
| 644 |
+
),
|
| 645 |
+
gr.update(value=welcome_msg),
|
| 646 |
+
new_state,
|
| 647 |
+
)
|
| 648 |
+
|
| 649 |
+
def switch_user(state):
|
| 650 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 651 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 652 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 653 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 654 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 655 |
+
# ==========================================
|
| 656 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 657 |
+
# ==========================================
|
| 658 |
+
try:
|
| 659 |
+
user_mem = state["memory"][state["user_name"]]
|
| 660 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 661 |
+
|
| 662 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 663 |
+
|
| 664 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 665 |
+
except Exception as e:
|
| 666 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 667 |
+
# ==========================================
|
| 668 |
+
|
| 669 |
+
new_state = state.copy()
|
| 670 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 671 |
+
|
| 672 |
+
return (
|
| 673 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 674 |
+
gr.update(visible=False),
|
| 675 |
+
gr.update(visible=False),
|
| 676 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 677 |
+
gr.update(value=""),
|
| 678 |
+
new_state,
|
| 679 |
+
gr.update(value=[])
|
| 680 |
+
)
|
| 681 |
+
|
| 682 |
+
def handle_chat(user_message, state):
|
| 683 |
+
if not user_message.strip():
|
| 684 |
+
print("[handle_chat] empty message")
|
| 685 |
+
print("[handle_chat] state =", state)
|
| 686 |
+
return gr.update(), state.get("history", []), state
|
| 687 |
+
|
| 688 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 689 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 690 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 691 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 692 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 693 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 694 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 695 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 696 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 697 |
+
|
| 698 |
+
user_name = state.get("user_name")
|
| 699 |
+
user_memory_index = state.get("user_memory_index")
|
| 700 |
+
user_memory = state.get("user_memory", {})
|
| 701 |
+
user_memory_index = state.get("user_memory_index")
|
| 702 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 703 |
+
service_context = state.get("service_context")
|
| 704 |
+
api_index = state.get("api_index", 0)
|
| 705 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 706 |
+
|
| 707 |
+
query_category = classify_query_local(user_message)
|
| 708 |
+
print("[handle_chat] query_category =", query_category)
|
| 709 |
+
|
| 710 |
+
new_history, _, status_msg = predict_new(
|
| 711 |
+
text=user_message,
|
| 712 |
+
history=state.get("history", []),
|
| 713 |
+
top_p=0.95,
|
| 714 |
+
temperature=1.0,
|
| 715 |
+
max_length_tokens=1024,
|
| 716 |
+
max_context_length_tokens=4096,
|
| 717 |
+
user_name=user_name,
|
| 718 |
+
user_memory=user_memory,
|
| 719 |
+
user_memory_index=user_memory_index,
|
| 720 |
+
service_context=service_context,
|
| 721 |
+
api_index=api_index,
|
| 722 |
+
semantic_memory_text=semantic_memory_text,
|
| 723 |
+
query_category=query_category,
|
| 724 |
+
|
| 725 |
+
)
|
| 726 |
+
|
| 727 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 728 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 729 |
+
|
| 730 |
+
state["history"] = new_history
|
| 731 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 732 |
+
|
| 733 |
+
return "", new_history, state
|
| 734 |
+
|
| 735 |
+
def clear_history(state):
|
| 736 |
+
state["history"] = []
|
| 737 |
+
return [], state
|
| 738 |
+
|
| 739 |
+
def handle_new_session(state):
|
| 740 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 741 |
+
user_name = state.get("user_name")
|
| 742 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 743 |
+
print("Error: User not logged in or memory missing.")
|
| 744 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 745 |
+
return [], state
|
| 746 |
+
|
| 747 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 748 |
+
user_data = state["memory"][user_name]
|
| 749 |
+
|
| 750 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 751 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 752 |
+
last_session = user_data["sessions"][-1]
|
| 753 |
+
|
| 754 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 755 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 756 |
+
session_date = last_session.get("date", "")
|
| 757 |
+
session_id = last_session.get("session_id", 0)
|
| 758 |
+
|
| 759 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 760 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 761 |
+
|
| 762 |
+
if "episodic_memory" not in user_data:
|
| 763 |
+
user_data["episodic_memory"] = []
|
| 764 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 765 |
+
|
| 766 |
+
# ==========================================
|
| 767 |
+
# بهروزرسانی حافظه سمانتیک
|
| 768 |
+
# ==========================================
|
| 769 |
+
try:
|
| 770 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 771 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 772 |
+
|
| 773 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 774 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 775 |
+
|
| 776 |
+
# ذخیره دیتای جدید
|
| 777 |
+
user_data["semantic_memory"] = updated_semantic
|
| 778 |
+
except Exception as e:
|
| 779 |
+
print(f"Error updating semantic memory: {e}")
|
| 780 |
+
# ==========================================
|
| 781 |
+
|
| 782 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 783 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 784 |
+
|
| 785 |
+
new_session = {
|
| 786 |
+
"session_id": new_session_id,
|
| 787 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 788 |
+
"conversation": []
|
| 789 |
+
}
|
| 790 |
+
|
| 791 |
+
if "sessions" not in user_data:
|
| 792 |
+
user_data["sessions"] = []
|
| 793 |
+
|
| 794 |
+
user_data["sessions"].append(new_session)
|
| 795 |
+
|
| 796 |
+
# پاک کردن تاریخچه چت در state
|
| 797 |
+
state["history"] = []
|
| 798 |
+
|
| 799 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 800 |
+
return [], state
|
| 801 |
+
|
| 802 |
+
check_user_btn.click(
|
| 803 |
+
handle_login_check,
|
| 804 |
+
inputs=[username_input, state],
|
| 805 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 806 |
+
)
|
| 807 |
+
|
| 808 |
+
register_btn.click(
|
| 809 |
+
handle_register,
|
| 810 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 811 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 812 |
+
)
|
| 813 |
+
|
| 814 |
+
switch_user_btn.click(
|
| 815 |
+
switch_user,
|
| 816 |
+
inputs=[state],
|
| 817 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 818 |
+
)
|
| 819 |
+
|
| 820 |
+
submit_btn.click(
|
| 821 |
+
handle_chat,
|
| 822 |
+
inputs=[user_input, state],
|
| 823 |
+
outputs=[user_input, chatbot, state]
|
| 824 |
+
)
|
| 825 |
+
|
| 826 |
+
user_input.submit(
|
| 827 |
+
handle_chat,
|
| 828 |
+
inputs=[user_input, state],
|
| 829 |
+
outputs=[user_input, chatbot, state]
|
| 830 |
+
)
|
| 831 |
+
|
| 832 |
+
clear_btn.click(
|
| 833 |
+
clear_history,
|
| 834 |
+
inputs=[state],
|
| 835 |
+
outputs=[chatbot, state]
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
# تغییر از clear_history به handle_new_session
|
| 839 |
+
new_session_btn.click(
|
| 840 |
+
handle_new_session,
|
| 841 |
+
inputs=[state],
|
| 842 |
+
outputs=[chatbot, state]
|
| 843 |
+
|
| 844 |
+
|
| 845 |
+
)
|
| 846 |
+
|
| 847 |
+
return demo
|
| 848 |
+
|
| 849 |
+
|
| 850 |
+
def main():
|
| 851 |
+
"""Main function to initialize and launch the interface."""
|
| 852 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 853 |
+
|
| 854 |
+
if not gapgpt_api_key:
|
| 855 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 856 |
+
else:
|
| 857 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 858 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 859 |
+
|
| 860 |
+
# تنظیم LLM (مدل زبانی)
|
| 861 |
+
llm = LlamaIndexOpenAI(
|
| 862 |
+
model="gpt-4o",
|
| 863 |
+
temperature=1,
|
| 864 |
+
max_tokens=1024,
|
| 865 |
+
top_p=0.95,
|
| 866 |
+
frequency_penalty=0.4,
|
| 867 |
+
presence_penalty=0.2,
|
| 868 |
+
api_key=gapgpt_api_key,
|
| 869 |
+
api_base=GAPGPT_BASE_URL,
|
| 870 |
+
)
|
| 871 |
+
|
| 872 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 873 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 874 |
+
embed_model = OpenAIEmbedding(
|
| 875 |
+
api_key=gapgpt_api_key,
|
| 876 |
+
api_base=GAPGPT_BASE_URL,
|
| 877 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 878 |
+
)
|
| 879 |
+
|
| 880 |
+
# اعمال تنظیمات سراسری
|
| 881 |
+
Settings.llm = llm
|
| 882 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 883 |
+
|
| 884 |
+
Settings.prompt_helper = PromptHelper(
|
| 885 |
+
context_window=4096,
|
| 886 |
+
num_output=256,
|
| 887 |
+
chunk_overlap_ratio=20 / 4096,
|
| 888 |
+
tokenizer=tokenizer,
|
| 889 |
+
)
|
| 890 |
+
|
| 891 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 892 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 893 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 894 |
+
if 'api_keys' not in locals():
|
| 895 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 896 |
+
|
| 897 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 898 |
+
demo.launch(
|
| 899 |
+
server_name="127.0.0.1",
|
| 900 |
+
server_port=7860,
|
| 901 |
+
share=True
|
| 902 |
+
)
|
| 903 |
+
|
| 904 |
+
|
| 905 |
+
if __name__ == "__main__":
|
| 906 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 907 |
+
main()
|
Backup code/app_V9.py
ADDED
|
@@ -0,0 +1,934 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
):
|
| 334 |
+
chatgpt_cfg = {
|
| 335 |
+
"model": "gpt-4o",
|
| 336 |
+
"temperature": temperature,
|
| 337 |
+
"max_tokens": max_length_tokens,
|
| 338 |
+
"top_p": top_p,
|
| 339 |
+
"frequency_penalty": 0.4,
|
| 340 |
+
"presence_penalty": 0.2,
|
| 341 |
+
"n": 1,
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
if text == "":
|
| 345 |
+
# Return same history if empty input
|
| 346 |
+
return history, history, "Empty context."
|
| 347 |
+
|
| 348 |
+
# Ensure history is initialized
|
| 349 |
+
if history is None:
|
| 350 |
+
history = []
|
| 351 |
+
|
| 352 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 353 |
+
history=history,
|
| 354 |
+
query=text, # Changed name to match prompt_utils
|
| 355 |
+
user_memory=user_memory,
|
| 356 |
+
user_name=user_name,
|
| 357 |
+
user_memory_index=user_memory_index,
|
| 358 |
+
service_context=service_context,
|
| 359 |
+
api_keys=api_keys,
|
| 360 |
+
api_index=api_index,
|
| 361 |
+
meta_prompt=meta_prompt,
|
| 362 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 363 |
+
data_args=data_args,
|
| 364 |
+
boot_actual_name=boot_actual_name,
|
| 365 |
+
semantic_memory_text=semantic_memory_text,
|
| 366 |
+
query_category=query_category,
|
| 367 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 368 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
# Handle context window slicing manually if needed,
|
| 372 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 373 |
+
current_history_for_llm = history
|
| 374 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 375 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 376 |
+
|
| 377 |
+
response = chatgpt_chat(
|
| 378 |
+
prompt=text,
|
| 379 |
+
system=system_prompt,
|
| 380 |
+
history=current_history_for_llm,
|
| 381 |
+
gpt_config=chatgpt_cfg,
|
| 382 |
+
api_index=api_index,
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
torch.cuda.empty_cache()
|
| 386 |
+
|
| 387 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 388 |
+
new_history = history + [
|
| 389 |
+
{"role": "user", "content": text},
|
| 390 |
+
{"role": "assistant", "content": response}
|
| 391 |
+
]
|
| 392 |
+
|
| 393 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 394 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 395 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 396 |
+
if user_name:
|
| 397 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 398 |
+
# or pass a converted version. Let's try passing the new format.
|
| 399 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 400 |
+
|
| 401 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 402 |
+
return new_history, new_history, "Generating..."
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
def create_gradio_interface(service_context, api_keys):
|
| 407 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 408 |
+
|
| 409 |
+
# 1. اضافه شدن CSS انیمیشن کشویی (Slide Up)
|
| 410 |
+
gr.HTML("""
|
| 411 |
+
<style>
|
| 412 |
+
.center-content {
|
| 413 |
+
display: flex;
|
| 414 |
+
flex-direction: column;
|
| 415 |
+
align-items: center;
|
| 416 |
+
justify-content: center;
|
| 417 |
+
}
|
| 418 |
+
/* -- استایلهای فرم ورود -- */
|
| 419 |
+
.login-box {
|
| 420 |
+
max-width: 400px !important;
|
| 421 |
+
margin: 0 auto !important;
|
| 422 |
+
width: 100% !important;
|
| 423 |
+
}
|
| 424 |
+
.login-btn, .login-btn:hover {
|
| 425 |
+
background-color: #3498db !important;
|
| 426 |
+
background-image: none !important;
|
| 427 |
+
color: white !important;
|
| 428 |
+
border: none !important;
|
| 429 |
+
}
|
| 430 |
+
/* -- استایلهای محیط چت -- */
|
| 431 |
+
.chat-box {
|
| 432 |
+
max-width: 800px !important;
|
| 433 |
+
margin: 0 auto !important;
|
| 434 |
+
width: 100% !important;
|
| 435 |
+
}
|
| 436 |
+
/* -- دکمههای محیط چت (آبی رنگ) -- */
|
| 437 |
+
.mobile-button, .mobile-button:hover {
|
| 438 |
+
background-color: #3498db !important;
|
| 439 |
+
background-image: none !important;
|
| 440 |
+
color: white !important;
|
| 441 |
+
border: none !important;
|
| 442 |
+
}
|
| 443 |
+
.gr-textbox textarea {
|
| 444 |
+
font-size: 16px;
|
| 445 |
+
}
|
| 446 |
+
.gr-chatbot {
|
| 447 |
+
font-size: 15px;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
/* --- انیمیشن کشویی لاگین --- */
|
| 451 |
+
.slide-up {
|
| 452 |
+
animation: slideUpAnimation 0.8s ease-in-out forwards !important;
|
| 453 |
+
}
|
| 454 |
+
|
| 455 |
+
@keyframes slideUpAnimation {
|
| 456 |
+
0% {
|
| 457 |
+
transform: translateY(0);
|
| 458 |
+
opacity: 1;
|
| 459 |
+
max-height: 1000px;
|
| 460 |
+
}
|
| 461 |
+
100% {
|
| 462 |
+
transform: translateY(-100%);
|
| 463 |
+
opacity: 0;
|
| 464 |
+
max-height: 0px;
|
| 465 |
+
overflow: hidden;
|
| 466 |
+
margin: 0 !important;
|
| 467 |
+
padding: 0 !important;
|
| 468 |
+
border: none !important;
|
| 469 |
+
}
|
| 470 |
+
}
|
| 471 |
+
</style>
|
| 472 |
+
""")
|
| 473 |
+
|
| 474 |
+
state = gr.State({
|
| 475 |
+
"history": [],
|
| 476 |
+
"user_name": None,
|
| 477 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 478 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 479 |
+
"service_context": service_context,
|
| 480 |
+
"api_keys": api_keys,
|
| 481 |
+
"api_index": 0,
|
| 482 |
+
"semantic_memory_text": "",
|
| 483 |
+
"new_conversation": True,
|
| 484 |
+
"initialized": False
|
| 485 |
+
})
|
| 486 |
+
|
| 487 |
+
|
| 488 |
+
|
| 489 |
+
# تابعی برای مدیریت کلیک دکمه ثبت نام
|
| 490 |
+
def handle_registration():
|
| 491 |
+
# کدهای مربوط به ذخیره کاربر در دیتابیس را اینجا قرار میدهید
|
| 492 |
+
# سپس پنل ثبتنام را مخفی میکنیم و یک پیام به سیستم میفرستیم
|
| 493 |
+
return gr.update(visible=False), "Registration successful!"
|
| 494 |
+
|
| 495 |
+
with gr.Blocks() as demo:
|
| 496 |
+
with gr.Row():
|
| 497 |
+
|
| 498 |
+
# ==========================================
|
| 499 |
+
# 1. LOGIN PAGE (ستون سمت چپ)
|
| 500 |
+
# ==========================================
|
| 501 |
+
with gr.Column(scale=1, min_width=300, elem_classes=["login-box"]) as login_page:
|
| 502 |
+
|
| 503 |
+
# استفاده از Accordion برای ایجاد حالت کشویی
|
| 504 |
+
with gr.Accordion("🔐 Login & Registration Menu", open=True) as login_accordion:
|
| 505 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 506 |
+
|
| 507 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 508 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 509 |
+
|
| 510 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 511 |
+
|
| 512 |
+
with gr.Column(visible=False) as registration_fields:
|
| 513 |
+
gr.Markdown("### ✨ New User Registration")
|
| 514 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 515 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 516 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 517 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 518 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 519 |
+
|
| 520 |
+
# ==========================================
|
| 521 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 522 |
+
# ==========================================
|
| 523 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 524 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 525 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 526 |
+
|
| 527 |
+
with gr.Group():
|
| 528 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 529 |
+
|
| 530 |
+
with gr.Row():
|
| 531 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 532 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 533 |
+
|
| 534 |
+
with gr.Row(equal_height=True):
|
| 535 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 536 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 537 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 538 |
+
|
| 539 |
+
# ==========================================
|
| 540 |
+
# رویدادها (Events)
|
| 541 |
+
# ==========================================
|
| 542 |
+
|
| 543 |
+
# 1. محو کردن بخش ثبت نام بعد از کلیک
|
| 544 |
+
register_btn.click(
|
| 545 |
+
fn=handle_registration,
|
| 546 |
+
inputs=[], # فیلدهای ورودی مثل نام و سن را اینجا اضافه کنید
|
| 547 |
+
outputs=[registration_fields, system_msg] # فرم ثبتنام را آپدیت (مخفی) میکند
|
| 548 |
+
)
|
| 549 |
+
|
| 550 |
+
# نکته: برای نمایش اولیه بخش ثبت نام، باید دکمه check_user_btn اینطور عمل کند:
|
| 551 |
+
# check_user_btn.click(fn=check_user, inputs=username_input, outputs=registration_fields)
|
| 552 |
+
# تا خروجی gr.update(visible=True) بدهد.
|
| 553 |
+
|
| 554 |
+
# -------------------------------------------------------
|
| 555 |
+
# Internal Functions
|
| 556 |
+
# -------------------------------------------------------
|
| 557 |
+
def handle_login_check(name, state):
|
| 558 |
+
if not name.strip():
|
| 559 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 560 |
+
|
| 561 |
+
if name in memory:
|
| 562 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 563 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 564 |
+
|
| 565 |
+
new_state = state.copy()
|
| 566 |
+
new_state["user_name"] = name
|
| 567 |
+
new_state["memory"] = memory
|
| 568 |
+
new_state["initialized"] = True
|
| 569 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 570 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 571 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 572 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 573 |
+
new_state["history"] = []
|
| 574 |
+
|
| 575 |
+
|
| 576 |
+
|
| 577 |
+
|
| 578 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 579 |
+
|
| 580 |
+
return (
|
| 581 |
+
gr.update(elem_classes=["center-content", "slide-up"]), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 582 |
+
gr.update(visible=False),
|
| 583 |
+
gr.update(visible=True),
|
| 584 |
+
gr.update(visible=False, value=""),
|
| 585 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 586 |
+
gr.update(value=welcome_msg),
|
| 587 |
+
new_state
|
| 588 |
+
)
|
| 589 |
+
else:
|
| 590 |
+
return (
|
| 591 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 592 |
+
gr.update(visible=True),
|
| 593 |
+
gr.update(visible=False),
|
| 594 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 595 |
+
gr.update(),
|
| 596 |
+
gr.update(),
|
| 597 |
+
state
|
| 598 |
+
)
|
| 599 |
+
|
| 600 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 601 |
+
name = str(name).strip()
|
| 602 |
+
|
| 603 |
+
if not name:
|
| 604 |
+
raise gr.Error("Please enter a valid user name.")
|
| 605 |
+
|
| 606 |
+
# Registration is only for new users.
|
| 607 |
+
if name in memory:
|
| 608 |
+
raise gr.Error(
|
| 609 |
+
f"User '{name}' already exists. Please use the login form."
|
| 610 |
+
)
|
| 611 |
+
|
| 612 |
+
# Create the user before trying to build or load their indices.
|
| 613 |
+
memory[name] = {
|
| 614 |
+
"profile": {
|
| 615 |
+
"age": age,
|
| 616 |
+
"gender": gender,
|
| 617 |
+
"occupation": occupation,
|
| 618 |
+
"residence": residence,
|
| 619 |
+
},
|
| 620 |
+
"sessions": [],
|
| 621 |
+
"episodic_memory": [],
|
| 622 |
+
"semantic_memory": {},
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
try:
|
| 626 |
+
(
|
| 627 |
+
_,
|
| 628 |
+
user_memory,
|
| 629 |
+
sessions_memory,
|
| 630 |
+
episodic_memory,
|
| 631 |
+
semantic_memory,
|
| 632 |
+
) = enter_name_llamaindex(
|
| 633 |
+
name=name,
|
| 634 |
+
memory=memory,
|
| 635 |
+
data_args=data_args,
|
| 636 |
+
update_memory_index=True,
|
| 637 |
+
)
|
| 638 |
+
except Exception:
|
| 639 |
+
# Avoid leaving a partially registered user in memory.
|
| 640 |
+
memory.pop(name, None)
|
| 641 |
+
raise
|
| 642 |
+
|
| 643 |
+
new_state = dict(state or {})
|
| 644 |
+
new_state.update(
|
| 645 |
+
{
|
| 646 |
+
"user_name": name,
|
| 647 |
+
"memory": memory,
|
| 648 |
+
"initialized": True,
|
| 649 |
+
"history": [],
|
| 650 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 651 |
+
"user_memory_index": sessions_memory,
|
| 652 |
+
"episodic_memory_index": episodic_memory,
|
| 653 |
+
"semantic_memory_index": semantic_memory,
|
| 654 |
+
}
|
| 655 |
+
)
|
| 656 |
+
|
| 657 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 658 |
+
|
| 659 |
+
return (
|
| 660 |
+
gr.update(
|
| 661 |
+
elem_classes=["center-content", "slide-up"]
|
| 662 |
+
),
|
| 663 |
+
gr.update(visible=False),
|
| 664 |
+
gr.update(visible=True),
|
| 665 |
+
gr.update(visible=False, value=""),
|
| 666 |
+
gr.update(
|
| 667 |
+
value=(
|
| 668 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 669 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 670 |
+
)
|
| 671 |
+
),
|
| 672 |
+
gr.update(value=welcome_msg),
|
| 673 |
+
new_state,
|
| 674 |
+
)
|
| 675 |
+
|
| 676 |
+
def switch_user(state):
|
| 677 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 678 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 679 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 680 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 681 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 682 |
+
# ==========================================
|
| 683 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 684 |
+
# ==========================================
|
| 685 |
+
try:
|
| 686 |
+
user_mem = state["memory"][state["user_name"]]
|
| 687 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 688 |
+
|
| 689 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 690 |
+
|
| 691 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 692 |
+
except Exception as e:
|
| 693 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 694 |
+
# ==========================================
|
| 695 |
+
|
| 696 |
+
new_state = state.copy()
|
| 697 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 698 |
+
|
| 699 |
+
return (
|
| 700 |
+
gr.update(visible=True, elem_classes=["center-content"]), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 701 |
+
gr.update(visible=False),
|
| 702 |
+
gr.update(visible=False),
|
| 703 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 704 |
+
gr.update(value=""),
|
| 705 |
+
new_state,
|
| 706 |
+
gr.update(value=[])
|
| 707 |
+
)
|
| 708 |
+
|
| 709 |
+
def handle_chat(user_message, state):
|
| 710 |
+
if not user_message.strip():
|
| 711 |
+
print("[handle_chat] empty message")
|
| 712 |
+
print("[handle_chat] state =", state)
|
| 713 |
+
return gr.update(), state.get("history", []), state
|
| 714 |
+
|
| 715 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 716 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 717 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 718 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 719 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 720 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 721 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 722 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 723 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 724 |
+
|
| 725 |
+
user_name = state.get("user_name")
|
| 726 |
+
user_memory_index = state.get("user_memory_index")
|
| 727 |
+
user_memory = state.get("user_memory", {})
|
| 728 |
+
user_memory_index = state.get("user_memory_index")
|
| 729 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 730 |
+
service_context = state.get("service_context")
|
| 731 |
+
api_index = state.get("api_index", 0)
|
| 732 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 733 |
+
|
| 734 |
+
query_category = classify_query_local(user_message)
|
| 735 |
+
print("[handle_chat] query_category =", query_category)
|
| 736 |
+
|
| 737 |
+
new_history, _, status_msg = predict_new(
|
| 738 |
+
text=user_message,
|
| 739 |
+
history=state.get("history", []),
|
| 740 |
+
top_p=0.95,
|
| 741 |
+
temperature=1.0,
|
| 742 |
+
max_length_tokens=1024,
|
| 743 |
+
max_context_length_tokens=4096,
|
| 744 |
+
user_name=user_name,
|
| 745 |
+
user_memory=user_memory,
|
| 746 |
+
user_memory_index=user_memory_index,
|
| 747 |
+
service_context=service_context,
|
| 748 |
+
api_index=api_index,
|
| 749 |
+
semantic_memory_text=semantic_memory_text,
|
| 750 |
+
query_category=query_category,
|
| 751 |
+
|
| 752 |
+
)
|
| 753 |
+
|
| 754 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 755 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 756 |
+
|
| 757 |
+
state["history"] = new_history
|
| 758 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 759 |
+
|
| 760 |
+
return "", new_history, state
|
| 761 |
+
|
| 762 |
+
def clear_history(state):
|
| 763 |
+
state["history"] = []
|
| 764 |
+
return [], state
|
| 765 |
+
|
| 766 |
+
def handle_new_session(state):
|
| 767 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 768 |
+
user_name = state.get("user_name")
|
| 769 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 770 |
+
print("Error: User not logged in or memory missing.")
|
| 771 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 772 |
+
return [], state
|
| 773 |
+
|
| 774 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 775 |
+
user_data = state["memory"][user_name]
|
| 776 |
+
|
| 777 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 778 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 779 |
+
last_session = user_data["sessions"][-1]
|
| 780 |
+
|
| 781 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 782 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 783 |
+
session_date = last_session.get("date", "")
|
| 784 |
+
session_id = last_session.get("session_id", 0)
|
| 785 |
+
|
| 786 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 787 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 788 |
+
|
| 789 |
+
if "episodic_memory" not in user_data:
|
| 790 |
+
user_data["episodic_memory"] = []
|
| 791 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 792 |
+
|
| 793 |
+
# ==========================================
|
| 794 |
+
# بهروزرسانی حافظه سمانتیک
|
| 795 |
+
# ==========================================
|
| 796 |
+
try:
|
| 797 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 798 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 799 |
+
|
| 800 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 801 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 802 |
+
|
| 803 |
+
# ذخیره دیتای جدید
|
| 804 |
+
user_data["semantic_memory"] = updated_semantic
|
| 805 |
+
except Exception as e:
|
| 806 |
+
print(f"Error updating semantic memory: {e}")
|
| 807 |
+
# ==========================================
|
| 808 |
+
|
| 809 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 810 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 811 |
+
|
| 812 |
+
new_session = {
|
| 813 |
+
"session_id": new_session_id,
|
| 814 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 815 |
+
"conversation": []
|
| 816 |
+
}
|
| 817 |
+
|
| 818 |
+
if "sessions" not in user_data:
|
| 819 |
+
user_data["sessions"] = []
|
| 820 |
+
|
| 821 |
+
user_data["sessions"].append(new_session)
|
| 822 |
+
|
| 823 |
+
# پاک کردن تاریخچه چت در state
|
| 824 |
+
state["history"] = []
|
| 825 |
+
|
| 826 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 827 |
+
return [], state
|
| 828 |
+
|
| 829 |
+
check_user_btn.click(
|
| 830 |
+
handle_login_check,
|
| 831 |
+
inputs=[username_input, state],
|
| 832 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 833 |
+
)
|
| 834 |
+
|
| 835 |
+
register_btn.click(
|
| 836 |
+
handle_register,
|
| 837 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 838 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 839 |
+
)
|
| 840 |
+
|
| 841 |
+
switch_user_btn.click(
|
| 842 |
+
switch_user,
|
| 843 |
+
inputs=[state],
|
| 844 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 845 |
+
)
|
| 846 |
+
|
| 847 |
+
submit_btn.click(
|
| 848 |
+
handle_chat,
|
| 849 |
+
inputs=[user_input, state],
|
| 850 |
+
outputs=[user_input, chatbot, state]
|
| 851 |
+
)
|
| 852 |
+
|
| 853 |
+
user_input.submit(
|
| 854 |
+
handle_chat,
|
| 855 |
+
inputs=[user_input, state],
|
| 856 |
+
outputs=[user_input, chatbot, state]
|
| 857 |
+
)
|
| 858 |
+
|
| 859 |
+
clear_btn.click(
|
| 860 |
+
clear_history,
|
| 861 |
+
inputs=[state],
|
| 862 |
+
outputs=[chatbot, state]
|
| 863 |
+
)
|
| 864 |
+
|
| 865 |
+
# تغییر از clear_history به handle_new_session
|
| 866 |
+
new_session_btn.click(
|
| 867 |
+
handle_new_session,
|
| 868 |
+
inputs=[state],
|
| 869 |
+
outputs=[chatbot, state]
|
| 870 |
+
|
| 871 |
+
|
| 872 |
+
)
|
| 873 |
+
|
| 874 |
+
return demo
|
| 875 |
+
|
| 876 |
+
|
| 877 |
+
def main():
|
| 878 |
+
"""Main function to initialize and launch the interface."""
|
| 879 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 880 |
+
|
| 881 |
+
if not gapgpt_api_key:
|
| 882 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 883 |
+
else:
|
| 884 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 885 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 886 |
+
|
| 887 |
+
# تنظیم LLM (مدل زبانی)
|
| 888 |
+
llm = LlamaIndexOpenAI(
|
| 889 |
+
model="gpt-4o",
|
| 890 |
+
temperature=1,
|
| 891 |
+
max_tokens=1024,
|
| 892 |
+
top_p=0.95,
|
| 893 |
+
frequency_penalty=0.4,
|
| 894 |
+
presence_penalty=0.2,
|
| 895 |
+
api_key=gapgpt_api_key,
|
| 896 |
+
api_base=GAPGPT_BASE_URL,
|
| 897 |
+
)
|
| 898 |
+
|
| 899 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 900 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 901 |
+
embed_model = OpenAIEmbedding(
|
| 902 |
+
api_key=gapgpt_api_key,
|
| 903 |
+
api_base=GAPGPT_BASE_URL,
|
| 904 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 905 |
+
)
|
| 906 |
+
|
| 907 |
+
# اعمال تنظیمات سراسری
|
| 908 |
+
Settings.llm = llm
|
| 909 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 910 |
+
|
| 911 |
+
Settings.prompt_helper = PromptHelper(
|
| 912 |
+
context_window=4096,
|
| 913 |
+
num_output=256,
|
| 914 |
+
chunk_overlap_ratio=20 / 4096,
|
| 915 |
+
tokenizer=tokenizer,
|
| 916 |
+
)
|
| 917 |
+
|
| 918 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 919 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 920 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 921 |
+
if 'api_keys' not in locals():
|
| 922 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 923 |
+
|
| 924 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 925 |
+
demo.launch(
|
| 926 |
+
server_name="127.0.0.1",
|
| 927 |
+
server_port=7860,
|
| 928 |
+
share=True
|
| 929 |
+
)
|
| 930 |
+
|
| 931 |
+
|
| 932 |
+
if __name__ == "__main__":
|
| 933 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 934 |
+
main()
|
Backup code/app_v10.py
ADDED
|
@@ -0,0 +1,848 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = r"C:\Users\keyva\MMPL_gpt\Classification Model\final_xlm_r_model_router"
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = 'C:\\Users\\keyva\\MMPL_gpt\\api_key_list.txt'
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
):
|
| 334 |
+
chatgpt_cfg = {
|
| 335 |
+
"model": "gpt-4o",
|
| 336 |
+
"temperature": temperature,
|
| 337 |
+
"max_tokens": max_length_tokens,
|
| 338 |
+
"top_p": top_p,
|
| 339 |
+
"frequency_penalty": 0.4,
|
| 340 |
+
"presence_penalty": 0.2,
|
| 341 |
+
"n": 1,
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
if text == "":
|
| 345 |
+
# Return same history if empty input
|
| 346 |
+
return history, history, "Empty context."
|
| 347 |
+
|
| 348 |
+
# Ensure history is initialized
|
| 349 |
+
if history is None:
|
| 350 |
+
history = []
|
| 351 |
+
|
| 352 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 353 |
+
history=history,
|
| 354 |
+
query=text, # Changed name to match prompt_utils
|
| 355 |
+
user_memory=user_memory,
|
| 356 |
+
user_name=user_name,
|
| 357 |
+
user_memory_index=user_memory_index,
|
| 358 |
+
service_context=service_context,
|
| 359 |
+
api_keys=api_keys,
|
| 360 |
+
api_index=api_index,
|
| 361 |
+
meta_prompt=meta_prompt,
|
| 362 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 363 |
+
data_args=data_args,
|
| 364 |
+
boot_actual_name=boot_actual_name,
|
| 365 |
+
semantic_memory_text=semantic_memory_text,
|
| 366 |
+
query_category=query_category,
|
| 367 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 368 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 369 |
+
)
|
| 370 |
+
|
| 371 |
+
# Handle context window slicing manually if needed,
|
| 372 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 373 |
+
current_history_for_llm = history
|
| 374 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 375 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 376 |
+
|
| 377 |
+
response = chatgpt_chat(
|
| 378 |
+
prompt=text,
|
| 379 |
+
system=system_prompt,
|
| 380 |
+
history=current_history_for_llm,
|
| 381 |
+
gpt_config=chatgpt_cfg,
|
| 382 |
+
api_index=api_index,
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
+
torch.cuda.empty_cache()
|
| 386 |
+
|
| 387 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 388 |
+
new_history = history + [
|
| 389 |
+
{"role": "user", "content": text},
|
| 390 |
+
{"role": "assistant", "content": response}
|
| 391 |
+
]
|
| 392 |
+
|
| 393 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 394 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 395 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 396 |
+
if user_name:
|
| 397 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 398 |
+
# or pass a converted version. Let's try passing the new format.
|
| 399 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 400 |
+
|
| 401 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 402 |
+
return new_history, new_history, "Generating..."
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
|
| 406 |
+
def create_gradio_interface(service_context, api_keys):
|
| 407 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 408 |
+
|
| 409 |
+
|
| 410 |
+
state = gr.State({
|
| 411 |
+
"history": [],
|
| 412 |
+
"user_name": None,
|
| 413 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 414 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 415 |
+
"service_context": service_context,
|
| 416 |
+
"api_keys": api_keys,
|
| 417 |
+
"api_index": 0,
|
| 418 |
+
"semantic_memory_text": "",
|
| 419 |
+
"new_conversation": True,
|
| 420 |
+
"initialized": False
|
| 421 |
+
})
|
| 422 |
+
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 426 |
+
with gr.Row():
|
| 427 |
+
|
| 428 |
+
# ==========================================
|
| 429 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 430 |
+
# ==========================================
|
| 431 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 432 |
+
with gr.Sidebar(open=True) as login_page:
|
| 433 |
+
|
| 434 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 435 |
+
|
| 436 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 437 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 438 |
+
|
| 439 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 440 |
+
|
| 441 |
+
with gr.Column(visible=False) as registration_fields:
|
| 442 |
+
gr.Markdown("### ✨ New User Registration")
|
| 443 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 444 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 445 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 446 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 447 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 448 |
+
|
| 449 |
+
|
| 450 |
+
# ==========================================
|
| 451 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 452 |
+
# ==========================================
|
| 453 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 454 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 455 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 456 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 457 |
+
|
| 458 |
+
with gr.Group():
|
| 459 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=450)
|
| 460 |
+
|
| 461 |
+
with gr.Row():
|
| 462 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=4)
|
| 463 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["mobile-button"], scale=1)
|
| 464 |
+
|
| 465 |
+
with gr.Row(equal_height=True):
|
| 466 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["mobile-button"])
|
| 467 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["mobile-button"])
|
| 468 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["mobile-button"])
|
| 469 |
+
|
| 470 |
+
# -------------------------------------------------------
|
| 471 |
+
# Internal Functions
|
| 472 |
+
# -------------------------------------------------------
|
| 473 |
+
def handle_login_check(name, state):
|
| 474 |
+
if not name.strip():
|
| 475 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 476 |
+
|
| 477 |
+
if name in memory:
|
| 478 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 479 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 480 |
+
|
| 481 |
+
new_state = state.copy()
|
| 482 |
+
new_state["user_name"] = name
|
| 483 |
+
new_state["memory"] = memory
|
| 484 |
+
new_state["initialized"] = True
|
| 485 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 486 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 487 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 488 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 489 |
+
new_state["history"] = []
|
| 490 |
+
|
| 491 |
+
|
| 492 |
+
|
| 493 |
+
|
| 494 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 495 |
+
|
| 496 |
+
return (
|
| 497 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 498 |
+
gr.update(visible=False),
|
| 499 |
+
gr.update(visible=True),
|
| 500 |
+
gr.update(visible=False, value=""),
|
| 501 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 502 |
+
gr.update(value=welcome_msg),
|
| 503 |
+
new_state
|
| 504 |
+
)
|
| 505 |
+
else:
|
| 506 |
+
return (
|
| 507 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 508 |
+
gr.update(visible=True),
|
| 509 |
+
gr.update(visible=False),
|
| 510 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 511 |
+
gr.update(),
|
| 512 |
+
gr.update(),
|
| 513 |
+
state
|
| 514 |
+
)
|
| 515 |
+
|
| 516 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 517 |
+
name = str(name).strip()
|
| 518 |
+
|
| 519 |
+
if not name:
|
| 520 |
+
raise gr.Error("Please enter a valid user name.")
|
| 521 |
+
|
| 522 |
+
# Registration is only for new users.
|
| 523 |
+
if name in memory:
|
| 524 |
+
raise gr.Error(
|
| 525 |
+
f"User '{name}' already exists. Please use the login form."
|
| 526 |
+
)
|
| 527 |
+
|
| 528 |
+
# Create the user before trying to build or load their indices.
|
| 529 |
+
memory[name] = {
|
| 530 |
+
"profile": {
|
| 531 |
+
"age": age,
|
| 532 |
+
"gender": gender,
|
| 533 |
+
"occupation": occupation,
|
| 534 |
+
"residence": residence,
|
| 535 |
+
},
|
| 536 |
+
"sessions": [],
|
| 537 |
+
"episodic_memory": [],
|
| 538 |
+
"semantic_memory": {},
|
| 539 |
+
}
|
| 540 |
+
|
| 541 |
+
try:
|
| 542 |
+
(
|
| 543 |
+
_,
|
| 544 |
+
user_memory,
|
| 545 |
+
sessions_memory,
|
| 546 |
+
episodic_memory,
|
| 547 |
+
semantic_memory,
|
| 548 |
+
) = enter_name_llamaindex(
|
| 549 |
+
name=name,
|
| 550 |
+
memory=memory,
|
| 551 |
+
data_args=data_args,
|
| 552 |
+
update_memory_index=True,
|
| 553 |
+
)
|
| 554 |
+
except Exception:
|
| 555 |
+
# Avoid leaving a partially registered user in memory.
|
| 556 |
+
memory.pop(name, None)
|
| 557 |
+
raise
|
| 558 |
+
|
| 559 |
+
new_state = dict(state or {})
|
| 560 |
+
new_state.update(
|
| 561 |
+
{
|
| 562 |
+
"user_name": name,
|
| 563 |
+
"memory": memory,
|
| 564 |
+
"initialized": True,
|
| 565 |
+
"history": [],
|
| 566 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 567 |
+
"user_memory_index": sessions_memory,
|
| 568 |
+
"episodic_memory_index": episodic_memory,
|
| 569 |
+
"semantic_memory_index": semantic_memory,
|
| 570 |
+
}
|
| 571 |
+
)
|
| 572 |
+
|
| 573 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 574 |
+
|
| 575 |
+
return (
|
| 576 |
+
gr.update(open=False),
|
| 577 |
+
gr.update(visible=False),
|
| 578 |
+
gr.update(visible=True),
|
| 579 |
+
gr.update(visible=False, value=""),
|
| 580 |
+
gr.update(
|
| 581 |
+
value=(
|
| 582 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 583 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 584 |
+
)
|
| 585 |
+
),
|
| 586 |
+
gr.update(value=welcome_msg),
|
| 587 |
+
new_state,
|
| 588 |
+
)
|
| 589 |
+
|
| 590 |
+
def switch_user(state):
|
| 591 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 592 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 593 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 594 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 595 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 596 |
+
# ==========================================
|
| 597 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 598 |
+
# ==========================================
|
| 599 |
+
try:
|
| 600 |
+
user_mem = state["memory"][state["user_name"]]
|
| 601 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 602 |
+
|
| 603 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 604 |
+
|
| 605 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 606 |
+
except Exception as e:
|
| 607 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 608 |
+
# ==========================================
|
| 609 |
+
|
| 610 |
+
new_state = state.copy()
|
| 611 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 612 |
+
|
| 613 |
+
return (
|
| 614 |
+
gr.update(open=True), # 4. برداشتن کلاس انیمیشن تا در خروج، فرم لاگین دوباره دیده شود
|
| 615 |
+
gr.update(visible=False),
|
| 616 |
+
gr.update(visible=False),
|
| 617 |
+
gr.update(value="Logged out successfully.", visible=True),
|
| 618 |
+
gr.update(value=""),
|
| 619 |
+
new_state,
|
| 620 |
+
gr.update(value=[])
|
| 621 |
+
)
|
| 622 |
+
|
| 623 |
+
def handle_chat(user_message, state):
|
| 624 |
+
if not user_message.strip():
|
| 625 |
+
print("[handle_chat] empty message")
|
| 626 |
+
print("[handle_chat] state =", state)
|
| 627 |
+
return gr.update(), state.get("history", []), state
|
| 628 |
+
|
| 629 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 630 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 631 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 632 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 633 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 634 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 635 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 636 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 637 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 638 |
+
|
| 639 |
+
user_name = state.get("user_name")
|
| 640 |
+
user_memory_index = state.get("user_memory_index")
|
| 641 |
+
user_memory = state.get("user_memory", {})
|
| 642 |
+
user_memory_index = state.get("user_memory_index")
|
| 643 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 644 |
+
service_context = state.get("service_context")
|
| 645 |
+
api_index = state.get("api_index", 0)
|
| 646 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 647 |
+
|
| 648 |
+
query_category = classify_query_local(user_message)
|
| 649 |
+
print("[handle_chat] query_category =", query_category)
|
| 650 |
+
|
| 651 |
+
new_history, _, status_msg = predict_new(
|
| 652 |
+
text=user_message,
|
| 653 |
+
history=state.get("history", []),
|
| 654 |
+
top_p=0.95,
|
| 655 |
+
temperature=1.0,
|
| 656 |
+
max_length_tokens=1024,
|
| 657 |
+
max_context_length_tokens=4096,
|
| 658 |
+
user_name=user_name,
|
| 659 |
+
user_memory=user_memory,
|
| 660 |
+
user_memory_index=user_memory_index,
|
| 661 |
+
service_context=service_context,
|
| 662 |
+
api_index=api_index,
|
| 663 |
+
semantic_memory_text=semantic_memory_text,
|
| 664 |
+
query_category=query_category,
|
| 665 |
+
|
| 666 |
+
)
|
| 667 |
+
|
| 668 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 669 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 670 |
+
|
| 671 |
+
state["history"] = new_history
|
| 672 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 673 |
+
|
| 674 |
+
return "", new_history, state
|
| 675 |
+
|
| 676 |
+
def clear_history(state):
|
| 677 |
+
state["history"] = []
|
| 678 |
+
return [], state
|
| 679 |
+
|
| 680 |
+
def handle_new_session(state):
|
| 681 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 682 |
+
user_name = state.get("user_name")
|
| 683 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 684 |
+
print("Error: User not logged in or memory missing.")
|
| 685 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 686 |
+
return [], state
|
| 687 |
+
|
| 688 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 689 |
+
user_data = state["memory"][user_name]
|
| 690 |
+
|
| 691 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 692 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 693 |
+
last_session = user_data["sessions"][-1]
|
| 694 |
+
|
| 695 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 696 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 697 |
+
session_date = last_session.get("date", "")
|
| 698 |
+
session_id = last_session.get("session_id", 0)
|
| 699 |
+
|
| 700 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 701 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 702 |
+
|
| 703 |
+
if "episodic_memory" not in user_data:
|
| 704 |
+
user_data["episodic_memory"] = []
|
| 705 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 706 |
+
|
| 707 |
+
# ==========================================
|
| 708 |
+
# بهروزرسانی حافظه سمانتیک
|
| 709 |
+
# ==========================================
|
| 710 |
+
try:
|
| 711 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 712 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 713 |
+
|
| 714 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 715 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 716 |
+
|
| 717 |
+
# ذخیره دیتای جدید
|
| 718 |
+
user_data["semantic_memory"] = updated_semantic
|
| 719 |
+
except Exception as e:
|
| 720 |
+
print(f"Error updating semantic memory: {e}")
|
| 721 |
+
# ==========================================
|
| 722 |
+
|
| 723 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 724 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 725 |
+
|
| 726 |
+
new_session = {
|
| 727 |
+
"session_id": new_session_id,
|
| 728 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 729 |
+
"conversation": []
|
| 730 |
+
}
|
| 731 |
+
|
| 732 |
+
if "sessions" not in user_data:
|
| 733 |
+
user_data["sessions"] = []
|
| 734 |
+
|
| 735 |
+
user_data["sessions"].append(new_session)
|
| 736 |
+
|
| 737 |
+
# پاک کردن تاریخچه چت در state
|
| 738 |
+
state["history"] = []
|
| 739 |
+
|
| 740 |
+
# برگرداندن مقادیر با ترتیب درست برای خروجیهای Gradio: [chatbot, state]
|
| 741 |
+
return [], state
|
| 742 |
+
|
| 743 |
+
check_user_btn.click(
|
| 744 |
+
handle_login_check,
|
| 745 |
+
inputs=[username_input, state],
|
| 746 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 747 |
+
)
|
| 748 |
+
|
| 749 |
+
register_btn.click(
|
| 750 |
+
handle_register,
|
| 751 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 752 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state]
|
| 753 |
+
)
|
| 754 |
+
|
| 755 |
+
switch_user_btn.click(
|
| 756 |
+
switch_user,
|
| 757 |
+
inputs=[state],
|
| 758 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot]
|
| 759 |
+
)
|
| 760 |
+
|
| 761 |
+
submit_btn.click(
|
| 762 |
+
handle_chat,
|
| 763 |
+
inputs=[user_input, state],
|
| 764 |
+
outputs=[user_input, chatbot, state]
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
user_input.submit(
|
| 768 |
+
handle_chat,
|
| 769 |
+
inputs=[user_input, state],
|
| 770 |
+
outputs=[user_input, chatbot, state]
|
| 771 |
+
)
|
| 772 |
+
|
| 773 |
+
clear_btn.click(
|
| 774 |
+
clear_history,
|
| 775 |
+
inputs=[state],
|
| 776 |
+
outputs=[chatbot, state]
|
| 777 |
+
)
|
| 778 |
+
|
| 779 |
+
# تغییر از clear_history به handle_new_session
|
| 780 |
+
new_session_btn.click(
|
| 781 |
+
handle_new_session,
|
| 782 |
+
inputs=[state],
|
| 783 |
+
outputs=[chatbot, state]
|
| 784 |
+
|
| 785 |
+
|
| 786 |
+
)
|
| 787 |
+
|
| 788 |
+
return demo
|
| 789 |
+
|
| 790 |
+
|
| 791 |
+
def main():
|
| 792 |
+
"""Main function to initialize and launch the interface."""
|
| 793 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 794 |
+
|
| 795 |
+
if not gapgpt_api_key:
|
| 796 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 797 |
+
else:
|
| 798 |
+
# تغییر مهم ۱: ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 799 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 800 |
+
|
| 801 |
+
# تنظیم LLM (مدل زبانی)
|
| 802 |
+
llm = LlamaIndexOpenAI(
|
| 803 |
+
model="gpt-4o",
|
| 804 |
+
temperature=1,
|
| 805 |
+
max_tokens=1024,
|
| 806 |
+
top_p=0.95,
|
| 807 |
+
frequency_penalty=0.4,
|
| 808 |
+
presence_penalty=0.2,
|
| 809 |
+
api_key=gapgpt_api_key,
|
| 810 |
+
api_base=GAPGPT_BASE_URL,
|
| 811 |
+
)
|
| 812 |
+
|
| 813 |
+
# تغییر مهم ۲: تنظیم مدل Embedding با همان کلید و آدرس GapGPT
|
| 814 |
+
# اگر سرویس دهنده شما از امبدینگ پشتیبانی نمیکند، این بخش نیاز به تغییر به مدل لوکال دارد
|
| 815 |
+
embed_model = OpenAIEmbedding(
|
| 816 |
+
api_key=gapgpt_api_key,
|
| 817 |
+
api_base=GAPGPT_BASE_URL,
|
| 818 |
+
model="text-embedding-3-small" # یا هر مدلی که سرویس شما پشتیبانی میکند
|
| 819 |
+
)
|
| 820 |
+
|
| 821 |
+
# اعمال تنظیمات سراسری
|
| 822 |
+
Settings.llm = llm
|
| 823 |
+
Settings.embed_model = embed_model # <--- این خط جلوی خطای فعلی را میگیرد
|
| 824 |
+
|
| 825 |
+
Settings.prompt_helper = PromptHelper(
|
| 826 |
+
context_window=4096,
|
| 827 |
+
num_output=256,
|
| 828 |
+
chunk_overlap_ratio=20 / 4096,
|
| 829 |
+
tokenizer=tokenizer,
|
| 830 |
+
)
|
| 831 |
+
|
| 832 |
+
# توجه: مطمئن شوید متغیر api_keys در اینجا تعریف شده باشد یا از args خوانده شود
|
| 833 |
+
# اگر api_keys در کد شما تعریف نشده، احتمالاً باید آن را بارگذاری کنید یا اگر استفاده نمیشود حذف کنید.
|
| 834 |
+
# فرض بر این است که api_keys قبلاً در کد شما تعریف شده است:
|
| 835 |
+
if 'api_keys' not in locals():
|
| 836 |
+
api_keys = {} # یا هر مقداری که کد شما انتظار دارد
|
| 837 |
+
|
| 838 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 839 |
+
demo.launch(
|
| 840 |
+
server_name="127.0.0.1",
|
| 841 |
+
server_port=7860,
|
| 842 |
+
share=True
|
| 843 |
+
)
|
| 844 |
+
|
| 845 |
+
|
| 846 |
+
if __name__ == "__main__":
|
| 847 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 848 |
+
main()
|
Backup code/app_v17.py
ADDED
|
@@ -0,0 +1,1031 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding:utf-8 -*-
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
+
import sys
|
| 5 |
+
import json
|
| 6 |
+
import time
|
| 7 |
+
import copy
|
| 8 |
+
import shutil
|
| 9 |
+
import signal
|
| 10 |
+
import logging
|
| 11 |
+
import platform
|
| 12 |
+
import re
|
| 13 |
+
|
| 14 |
+
import gradio as gr
|
| 15 |
+
import nltk
|
| 16 |
+
import torch
|
| 17 |
+
import tiktoken
|
| 18 |
+
|
| 19 |
+
from openai import OpenAI as OpenAIClient
|
| 20 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 21 |
+
|
| 22 |
+
# from langchain_openai import ChatOpenAI, OpenAI as LangChainOpenAI # (If not used, can be commented out)
|
| 23 |
+
from llama_index.llms.openai import OpenAI as LlamaIndexOpenAI
|
| 24 |
+
from llama_index.core import Settings
|
| 25 |
+
from llama_index.core.indices.prompt_helper import PromptHelper
|
| 26 |
+
|
| 27 |
+
prompt_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../')
|
| 28 |
+
sys.path.append(prompt_path)
|
| 29 |
+
|
| 30 |
+
# Assuming these imports exist in your local environment
|
| 31 |
+
from utils.sys_args import data_args, model_args
|
| 32 |
+
from utils.app_modules.utils import *
|
| 33 |
+
from utils.app_modules.presets import *
|
| 34 |
+
from utils.app_modules.overwrites import *
|
| 35 |
+
from utils.prompt_utils import *
|
| 36 |
+
from utils.memory_utils import (
|
| 37 |
+
enter_name_llamaindex,
|
| 38 |
+
summarize_memory_event_personality,
|
| 39 |
+
save_local_memory,
|
| 40 |
+
extract_session_summary,
|
| 41 |
+
extract_semantic_memory,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
# Ensure NLTK data path
|
| 45 |
+
nltk.data.path = [os.path.join(os.path.dirname(__file__), "nltk_data")] + nltk.data.path
|
| 46 |
+
|
| 47 |
+
tokenizer = tiktoken.get_encoding("cl100k_base")
|
| 48 |
+
|
| 49 |
+
GAPGPT_BASE_URL = os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 50 |
+
openai_client_cache = {}
|
| 51 |
+
|
| 52 |
+
import torch
|
| 53 |
+
import torch.nn.functional as F
|
| 54 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
LOCAL_MODEL_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "Classification_Model", "final_xlm_r_model_router")
|
| 58 |
+
|
| 59 |
+
print(f"Loading model from: {LOCAL_MODEL_PATH}")
|
| 60 |
+
|
| 61 |
+
try:
|
| 62 |
+
_tokenizer = AutoTokenizer.from_pretrained(LOCAL_MODEL_PATH)
|
| 63 |
+
_classifier_model = AutoModelForSequenceClassification.from_pretrained(LOCAL_MODEL_PATH)
|
| 64 |
+
_classifier_model.eval()
|
| 65 |
+
print("Local classifier loaded successfully.")
|
| 66 |
+
except Exception as e:
|
| 67 |
+
print(f"Error loading local classifier: {e}")
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def get_gapgpt_client(api_key: str) -> OpenAIClient:
|
| 71 |
+
if not api_key:
|
| 72 |
+
raise ValueError("API key is missing while attempting to create a GapGPT client.")
|
| 73 |
+
if api_key not in openai_client_cache:
|
| 74 |
+
openai_client_cache[api_key] = OpenAIClient(api_key=api_key, base_url=GAPGPT_BASE_URL)
|
| 75 |
+
return openai_client_cache[api_key]
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
os_name = platform.system()
|
| 79 |
+
clear_command = 'cls' if os_name == 'Windows' else 'clear'
|
| 80 |
+
stop_stream = False
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
def signal_handler(signal_number, frame):
|
| 84 |
+
global stop_stream
|
| 85 |
+
stop_stream = True
|
| 86 |
+
|
| 87 |
+
|
| 88 |
+
VECTOR_SEARCH_TOP_K = 2
|
| 89 |
+
|
| 90 |
+
# Update this path to your actual file location
|
| 91 |
+
api_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "api_key_list.txt")
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def read_apis(path):
|
| 95 |
+
api_keys_local = []
|
| 96 |
+
if os.path.exists(path):
|
| 97 |
+
with open(path, 'r', encoding='utf8') as f:
|
| 98 |
+
for line in f:
|
| 99 |
+
line = line.strip()
|
| 100 |
+
if line:
|
| 101 |
+
api_keys_local.append(line)
|
| 102 |
+
return api_keys_local
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
memory_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data", "memories", "update_memory_0512_eng.json")
|
| 106 |
+
|
| 107 |
+
# Ensure directory exists
|
| 108 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 109 |
+
|
| 110 |
+
if not os.path.exists(memory_dir):
|
| 111 |
+
json.dump({}, open(memory_dir, "w", encoding="utf-8"))
|
| 112 |
+
|
| 113 |
+
global memory
|
| 114 |
+
memory = json.load(open(memory_dir, "r", encoding="utf-8"))
|
| 115 |
+
language = 'en'
|
| 116 |
+
user_keyword = generate_user_keyword()[language]
|
| 117 |
+
ai_keyword = generate_ai_keyword()[language]
|
| 118 |
+
boot_name = boot_name_dict[language]
|
| 119 |
+
boot_actual_name = boot_actual_name_dict[language]
|
| 120 |
+
meta_prompt = generate_meta_prompt_dict_chatgpt()[language]
|
| 121 |
+
meta_prompt_semantic = generate_meta_prompt_dict_semantic_chatgpt()[language]
|
| 122 |
+
meta_prompt_semantic_episodic = generate_meta_prompt_dict_semantic_episodic_chatgpt()[language]
|
| 123 |
+
new_user_meta_prompt = generate_new_user_meta_prompt_dict_chatgpt()[language]
|
| 124 |
+
|
| 125 |
+
api_keys = read_apis(api_path)
|
| 126 |
+
# Fallback if file is empty or missing for testing purposes
|
| 127 |
+
if not api_keys:
|
| 128 |
+
print(f"Warning: No API keys found in {api_path}.")
|
| 129 |
+
|
| 130 |
+
new_conversation = False
|
| 131 |
+
chatgpt_config = {
|
| 132 |
+
"model": "gpt-4o",
|
| 133 |
+
"temperature": 1,
|
| 134 |
+
"max_tokens": 1024,
|
| 135 |
+
"top_p": 0.95,
|
| 136 |
+
"frequency_penalty": 0.4,
|
| 137 |
+
"presence_penalty": 0.2,
|
| 138 |
+
"n": 1,
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
deactivated_keys = []
|
| 142 |
+
logging.basicConfig(
|
| 143 |
+
level=logging.DEBUG,
|
| 144 |
+
format="%(asctime)s [%(levelname)s] [%(filename)s:%(lineno)d] %(message)s",
|
| 145 |
+
)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def chatgpt_chat(prompt, system, history, gpt_config, api_index=0):
|
| 149 |
+
"""
|
| 150 |
+
Handles the chat request to OpenAI.
|
| 151 |
+
History is expected to be a list of dictionaries: [{'role': 'user', 'content': '...'}, ...]
|
| 152 |
+
"""
|
| 153 |
+
retry_times, count = 5, 0
|
| 154 |
+
response = None
|
| 155 |
+
|
| 156 |
+
while response is None and count < retry_times:
|
| 157 |
+
try:
|
| 158 |
+
request = copy.deepcopy(gpt_config)
|
| 159 |
+
|
| 160 |
+
# Initial system and greeting messages
|
| 161 |
+
if data_args.language == 'en':
|
| 162 |
+
message = [
|
| 163 |
+
{"role": "system", "content": system.strip()},
|
| 164 |
+
{"role": "user", "content": "Hi!"},
|
| 165 |
+
{"role": "assistant",
|
| 166 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 167 |
+
]
|
| 168 |
+
else:
|
| 169 |
+
message = [
|
| 170 |
+
{"role": "system", "content": system.strip()},
|
| 171 |
+
{"role": "user", "content": "Hi"},
|
| 172 |
+
{"role": "assistant",
|
| 173 |
+
"content": f"Hi! I'm {boot_actual_name}! I will give you warm companion!"},
|
| 174 |
+
]
|
| 175 |
+
|
| 176 |
+
# --- FIX: Handle History as List of Dicts ---
|
| 177 |
+
if history:
|
| 178 |
+
# Verify if history is old format (list of lists) or new (list of dicts)
|
| 179 |
+
if isinstance(history[0], list):
|
| 180 |
+
# Convert old format temporarily if encountered
|
| 181 |
+
for q, a in history:
|
| 182 |
+
message.append({"role": "user", "content": str(q)})
|
| 183 |
+
message.append({"role": "assistant", "content": str(a)})
|
| 184 |
+
elif isinstance(history[0], dict):
|
| 185 |
+
# New format
|
| 186 |
+
for msg in history:
|
| 187 |
+
if msg.get('role') in ['user', 'assistant']:
|
| 188 |
+
message.append(msg)
|
| 189 |
+
|
| 190 |
+
# Add the current prompt
|
| 191 |
+
message.append({"role": "user", "content": f"{prompt}"})
|
| 192 |
+
|
| 193 |
+
if not api_keys:
|
| 194 |
+
return "Error: No API Keys available."
|
| 195 |
+
|
| 196 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 197 |
+
|
| 198 |
+
# New OpenAI 1.x Syntax
|
| 199 |
+
response = client.chat.completions.create(messages=message, **request)
|
| 200 |
+
|
| 201 |
+
except Exception as e:
|
| 202 |
+
print(f"Chat Error: {e}")
|
| 203 |
+
if 'This key is associated with a deactivated account' in str(e):
|
| 204 |
+
deactivated_keys.append(api_keys[api_index])
|
| 205 |
+
|
| 206 |
+
if api_keys:
|
| 207 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 208 |
+
loop_check = 0
|
| 209 |
+
while api_keys[api_index] in deactivated_keys and loop_check < len(api_keys):
|
| 210 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 211 |
+
loop_check += 1
|
| 212 |
+
count += 1
|
| 213 |
+
|
| 214 |
+
if response:
|
| 215 |
+
response = response.choices[0].message.content
|
| 216 |
+
else:
|
| 217 |
+
response = ''
|
| 218 |
+
return response
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
def classify_query_local(text):
|
| 222 |
+
|
| 223 |
+
|
| 224 |
+
# 0: episodic, 1: semantic, 2: semantic_episodic, 3: unrelated
|
| 225 |
+
id2label_map = {
|
| 226 |
+
0: "episodic_memory",
|
| 227 |
+
1: "semantic_memory",
|
| 228 |
+
2: "semantic-episodic",
|
| 229 |
+
3: "unknown"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
try:
|
| 233 |
+
|
| 234 |
+
inputs = _tokenizer(
|
| 235 |
+
text,
|
| 236 |
+
return_tensors="pt",
|
| 237 |
+
truncation=True,
|
| 238 |
+
padding=True,
|
| 239 |
+
max_length=512
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
with torch.no_grad():
|
| 245 |
+
outputs = _classifier_model(**inputs)
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
logits = outputs.logits
|
| 249 |
+
probabilities = F.softmax(logits, dim=-1)
|
| 250 |
+
predicted_class_id = torch.argmax(probabilities, dim=-1).item()
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
category = id2label_map.get(predicted_class_id, "unknown")
|
| 254 |
+
|
| 255 |
+
print(f"Local Classifier: '{text}' -> {category} (Class ID: {predicted_class_id})")
|
| 256 |
+
return category
|
| 257 |
+
|
| 258 |
+
except Exception as e:
|
| 259 |
+
print(f"Error in local classification: {e}")
|
| 260 |
+
return "unknown"
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
|
| 264 |
+
def classify_query_openai(text, gpt_config, api_index=0, retry_times=5):
|
| 265 |
+
response = None
|
| 266 |
+
count = 0
|
| 267 |
+
local_deactivated = []
|
| 268 |
+
print("text********:", text)
|
| 269 |
+
|
| 270 |
+
system_prompt = """
|
| 271 |
+
You are an AI that classifies user queries into one of the following memory types:
|
| 272 |
+
- 'episodic_memory': Queries about past personal events, daily life logs, or specific experiences the user has shared (e.g., "What did I eat yesterday?", "Tell me about my trip").
|
| 273 |
+
- 'semantic_memory': Queries about facts, preferences, general knowledge the user has taught you, or summaries of their personality (e.g., "What is my favorite color?", "Do I like sci-fi movies?").
|
| 274 |
+
- 'semantic-episodic': Complex queries requiring both specific past events and general facts/preferences (e.g., "Based on my food preferences, did I enjoy the dinner last night?").
|
| 275 |
+
|
| 276 |
+
Output ONLY one of these three strings: 'episodic_memory', 'semantic_memory', or 'semantic-episodic'. If unsure, output 'episodic_memory'.
|
| 277 |
+
""".strip()
|
| 278 |
+
|
| 279 |
+
if not api_keys:
|
| 280 |
+
return "unknown"
|
| 281 |
+
|
| 282 |
+
while response is None and count < retry_times:
|
| 283 |
+
try:
|
| 284 |
+
client = get_gapgpt_client(api_keys[api_index])
|
| 285 |
+
|
| 286 |
+
# New OpenAI 1.x Syntax
|
| 287 |
+
response = client.chat.completions.create(
|
| 288 |
+
messages=[
|
| 289 |
+
{"role": "system", "content": system_prompt},
|
| 290 |
+
{"role": "user", "content": text.strip()},
|
| 291 |
+
],
|
| 292 |
+
**copy.deepcopy(gpt_config),
|
| 293 |
+
)
|
| 294 |
+
except Exception as e:
|
| 295 |
+
print(f"Classify Error: {e}")
|
| 296 |
+
if "This key is associated with a deactivated account" in str(e):
|
| 297 |
+
local_deactivated.append(api_keys[api_index])
|
| 298 |
+
|
| 299 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 300 |
+
while api_keys[api_index] in local_deactivated:
|
| 301 |
+
api_index = api_index + 1 if api_index < len(api_keys) - 1 else 0
|
| 302 |
+
count += 1
|
| 303 |
+
|
| 304 |
+
if response:
|
| 305 |
+
category = response.choices[0].message.content.strip().lower()
|
| 306 |
+
# Basic cleanup
|
| 307 |
+
if "semantic_memory" in category: category = "semantic_memory"
|
| 308 |
+
elif "semantic-episodic" in category: category = "semantic-episodic"
|
| 309 |
+
elif "episodic_memory" in category: category = "episodic_memory"
|
| 310 |
+
else: category = "unknown"
|
| 311 |
+
else:
|
| 312 |
+
category = "unknown"
|
| 313 |
+
|
| 314 |
+
return category
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
def predict_new(
|
| 318 |
+
text,
|
| 319 |
+
history,
|
| 320 |
+
top_p,
|
| 321 |
+
temperature,
|
| 322 |
+
max_length_tokens,
|
| 323 |
+
max_context_length_tokens,
|
| 324 |
+
user_name,
|
| 325 |
+
user_memory,
|
| 326 |
+
user_memory_index,
|
| 327 |
+
service_context,
|
| 328 |
+
api_index,
|
| 329 |
+
semantic_memory_text,
|
| 330 |
+
query_category,
|
| 331 |
+
user_profile=None
|
| 332 |
+
|
| 333 |
+
|
| 334 |
+
):
|
| 335 |
+
chatgpt_cfg = {
|
| 336 |
+
"model": "gpt-4o",
|
| 337 |
+
"temperature": temperature,
|
| 338 |
+
"max_tokens": max_length_tokens,
|
| 339 |
+
"top_p": top_p,
|
| 340 |
+
"frequency_penalty": 0.4,
|
| 341 |
+
"presence_penalty": 0.2,
|
| 342 |
+
"n": 1,
|
| 343 |
+
}
|
| 344 |
+
|
| 345 |
+
if text == "":
|
| 346 |
+
# Return same history if empty input
|
| 347 |
+
return history, history, "Empty context."
|
| 348 |
+
|
| 349 |
+
# Ensure history is initialized
|
| 350 |
+
if history is None:
|
| 351 |
+
history = []
|
| 352 |
+
|
| 353 |
+
system_prompt, related_memos = build_prompt_with_search_memory_llamaindex(
|
| 354 |
+
history=history,
|
| 355 |
+
query=text, # Changed name to match prompt_utils
|
| 356 |
+
user_memory=user_memory,
|
| 357 |
+
user_name=user_name,
|
| 358 |
+
user_memory_index=user_memory_index,
|
| 359 |
+
service_context=service_context,
|
| 360 |
+
api_keys=api_keys,
|
| 361 |
+
api_index=api_index,
|
| 362 |
+
meta_prompt=meta_prompt,
|
| 363 |
+
new_user_meta_prompt=new_user_meta_prompt,
|
| 364 |
+
data_args=data_args,
|
| 365 |
+
boot_actual_name=boot_actual_name,
|
| 366 |
+
semantic_memory_text=semantic_memory_text,
|
| 367 |
+
query_category=query_category,
|
| 368 |
+
meta_prompt_semantic=meta_prompt_semantic,
|
| 369 |
+
meta_prompt_semantic_episodic=meta_prompt_semantic_episodic,
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ==========================================
|
| 373 |
+
# اضافه کردن پروفایل به System Prompt
|
| 374 |
+
# ==========================================
|
| 375 |
+
if user_profile:
|
| 376 |
+
profile_str = (
|
| 377 |
+
f"\n\n[User Profile Information]:\n"
|
| 378 |
+
f"- Age: {user_profile.get('age', 'Unknown')}\n"
|
| 379 |
+
f"- Gender: {user_profile.get('gender', 'Unknown')}\n"
|
| 380 |
+
f"- Occupation: {user_profile.get('occupation', 'Unknown')}\n"
|
| 381 |
+
f"- Residence: {user_profile.get('residence', 'Unknown')}\n"
|
| 382 |
+
f"Use this context subtly when talking to the user."
|
| 383 |
+
)
|
| 384 |
+
system_prompt += profile_str
|
| 385 |
+
# ==========================================
|
| 386 |
+
|
| 387 |
+
# Handle context window slicing manually if needed,
|
| 388 |
+
# though usually OpenAI manages this, or we slice the list of dicts.
|
| 389 |
+
current_history_for_llm = history
|
| 390 |
+
if len(history) > data_args.max_history * 2: # *2 because 1 user + 1 bot
|
| 391 |
+
current_history_for_llm = history[-(data_args.max_history * 2):]
|
| 392 |
+
|
| 393 |
+
response = chatgpt_chat(
|
| 394 |
+
prompt=text,
|
| 395 |
+
system=system_prompt,
|
| 396 |
+
history=current_history_for_llm,
|
| 397 |
+
gpt_config=chatgpt_cfg,
|
| 398 |
+
api_index=api_index,
|
| 399 |
+
)
|
| 400 |
+
|
| 401 |
+
torch.cuda.empty_cache()
|
| 402 |
+
|
| 403 |
+
# --- FIX: Update History with Dictionaries (Gradio Chatbot format) ---
|
| 404 |
+
new_history = history + [
|
| 405 |
+
{"role": "user", "content": text},
|
| 406 |
+
{"role": "assistant", "content": response}
|
| 407 |
+
]
|
| 408 |
+
|
| 409 |
+
# Save memory logic (Needs to handle dict format, assuming save_local_memory can handle it
|
| 410 |
+
# OR we convert strictly for saving if your legacy code needs it.
|
| 411 |
+
# For now, assuming we pass the object as is or convert for save)
|
| 412 |
+
if user_name:
|
| 413 |
+
# If save_local_memory expects list of lists, we might need to adapt it inside that function
|
| 414 |
+
# or pass a converted version. Let's try passing the new format.
|
| 415 |
+
save_local_memory(memory, new_history, user_name, data_args)
|
| 416 |
+
|
| 417 |
+
# Return: (Chatbot View, State History, Textbox Reset)
|
| 418 |
+
return new_history, new_history, "Generating..."
|
| 419 |
+
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
def create_gradio_interface(service_context, api_keys):
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
# ابتدا متغیر CSS را تعریف کنید
|
| 426 |
+
custom_css = """
|
| 427 |
+
/* استایل دکمه ارسال (Send) */
|
| 428 |
+
.send-btn {
|
| 429 |
+
border: 3px solid #0066cc !important;
|
| 430 |
+
border-radius: 12px !important;
|
| 431 |
+
background-color: white !important;
|
| 432 |
+
color: black !important;
|
| 433 |
+
font-weight: bold !important;
|
| 434 |
+
font-size: 16px !important;
|
| 435 |
+
transition: all 0.3s ease !important;
|
| 436 |
+
}
|
| 437 |
+
.send-btn:hover {
|
| 438 |
+
background-color: #0066cc !important;
|
| 439 |
+
color: white !important;
|
| 440 |
+
}
|
| 441 |
+
|
| 442 |
+
/* استایل نوار پایین و دکمههای آن */
|
| 443 |
+
.bottom-actions-row {
|
| 444 |
+
background-color: #e5e7eb !important; /* رنگ خاکستری پسزمینه */
|
| 445 |
+
border-radius: 8px !important;
|
| 446 |
+
padding: 5px !important;
|
| 447 |
+
margin-top: 10px !important;
|
| 448 |
+
}
|
| 449 |
+
|
| 450 |
+
.action-btn {
|
| 451 |
+
border: none !important;
|
| 452 |
+
background: transparent !important;
|
| 453 |
+
color: black !important;
|
| 454 |
+
font-weight: bold !important;
|
| 455 |
+
box-shadow: none !important;
|
| 456 |
+
transition: all 0.3s ease !important;
|
| 457 |
+
}
|
| 458 |
+
|
| 459 |
+
.action-btn:hover {
|
| 460 |
+
background-color: #d1d5db !important; /* تغییر رنگ ملایم هنگام هاور */
|
| 461 |
+
border-radius: 8px !important;
|
| 462 |
+
}
|
| 463 |
+
/* ========================================== */
|
| 464 |
+
/* لودینگ تمامصفحه و غیرفعالسازی تعاملات */
|
| 465 |
+
/* ========================================== */
|
| 466 |
+
|
| 467 |
+
/* مخفی کردن نوار پیشرفت پیشفرض Gradio */
|
| 468 |
+
.progress-level, .progress-text, .progress-level svg, .progress-level img {
|
| 469 |
+
display: none !important;
|
| 470 |
+
}
|
| 471 |
+
|
| 472 |
+
/* وقتی کلاسی به نام progress-level در صفحه ایجاد شود، این استایلها روی body اعمال میشود */
|
| 473 |
+
body:has(.progress-level) {
|
| 474 |
+
pointer-events: none !important; /* غیرفعال کردن تمام کلیکها */
|
| 475 |
+
}
|
| 476 |
+
|
| 477 |
+
/* ایجاد هاله نیمهشفاف روی کل صفحه */
|
| 478 |
+
body:has(.progress-level)::after {
|
| 479 |
+
content: "";
|
| 480 |
+
position: fixed;
|
| 481 |
+
top: 0; left: 0;
|
| 482 |
+
width: 100vw; height: 100vh;
|
| 483 |
+
background-color: rgba(255, 255, 255, 0.7); /* رنگ سفید نیمهشفاف */
|
| 484 |
+
z-index: 9998;
|
| 485 |
+
pointer-events: all; /* برای گرفتن کلیکها و جلوگیری از عبور آنها */
|
| 486 |
+
cursor: wait;
|
| 487 |
+
}
|
| 488 |
+
|
| 489 |
+
/* ایجاد اسپینر لودینگ در مرکز صفحه */
|
| 490 |
+
body:has(.progress-level)::before {
|
| 491 |
+
content: "";
|
| 492 |
+
position: fixed;
|
| 493 |
+
top: 50%; left: 50%;
|
| 494 |
+
transform: translate(-50%, -50%);
|
| 495 |
+
width: 60px; height: 60px;
|
| 496 |
+
border: 6px solid #e5e7eb;
|
| 497 |
+
border-top-color: #0066cc;
|
| 498 |
+
border-radius: 50%;
|
| 499 |
+
animation: spin 1s linear infinite;
|
| 500 |
+
z-index: 9999;
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
@keyframes spin {
|
| 504 |
+
0% { transform: translate(-50%, -50%) rotate(0deg); }
|
| 505 |
+
100% { transform: translate(-50%, -50%) rotate(360deg); }
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
|
| 509 |
+
/* انیمیشن چرخش */
|
| 510 |
+
@keyframes spin {
|
| 511 |
+
0% { transform: rotate(0deg); }
|
| 512 |
+
100% { transform: rotate(360deg); }
|
| 513 |
+
}
|
| 514 |
+
|
| 515 |
+
/* تغییر کلمه Processing (اختیاری) - مخفی کردن متن پیش فرض */
|
| 516 |
+
/* اگر میخواهید کلا متنی نباشد و فقط دایره بچرخد، کد زیر را از کامنت در بیاورید */
|
| 517 |
+
/*
|
| 518 |
+
.progress-text {
|
| 519 |
+
display: none !important;
|
| 520 |
+
}
|
| 521 |
+
*/
|
| 522 |
+
/* انیمیشن سه نقطه در حال تایپ */
|
| 523 |
+
.typing-dots::after {
|
| 524 |
+
content: '';
|
| 525 |
+
animation: typing 1.5s infinite;
|
| 526 |
+
}
|
| 527 |
+
@keyframes typing {
|
| 528 |
+
0% { content: ''; }
|
| 529 |
+
25% { content: ' .'; }
|
| 530 |
+
50% { content: ' . .'; }
|
| 531 |
+
75% { content: ' . . .'; }
|
| 532 |
+
100% { content: ''; }
|
| 533 |
+
}
|
| 534 |
+
|
| 535 |
+
|
| 536 |
+
"""
|
| 537 |
+
|
| 538 |
+
with gr.Blocks(title="EMMA") as demo:
|
| 539 |
+
# حالا متغیر را به HTML پاس دهید (بدون علامت مساوی)
|
| 540 |
+
gr.HTML(f"<style>{custom_css}</style>")
|
| 541 |
+
|
| 542 |
+
# بقیه کدهای شما...
|
| 543 |
+
|
| 544 |
+
|
| 545 |
+
state = gr.State({
|
| 546 |
+
"history": [],
|
| 547 |
+
"user_name": None,
|
| 548 |
+
"memory": memory, # فرض بر این است که متغیر memory خارج از تابع تعریف شده
|
| 549 |
+
"data_args": data_args, # فرض بر این است که data_args خارج از تابع تعریف شده
|
| 550 |
+
"service_context": service_context,
|
| 551 |
+
"api_keys": api_keys,
|
| 552 |
+
"api_index": 0,
|
| 553 |
+
"semantic_memory_text": "",
|
| 554 |
+
"new_conversation": True,
|
| 555 |
+
"initialized": False
|
| 556 |
+
})
|
| 557 |
+
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
# فرض بر این است که این کد داخل with gr.Blocks() قرار دارد
|
| 561 |
+
with gr.Row():
|
| 562 |
+
|
| 563 |
+
# ==========================================
|
| 564 |
+
# 1. LOGIN PAGE (سایدبار سمت چپ)
|
| 565 |
+
# ==========================================
|
| 566 |
+
# استفاده از gr.Sidebar به جای gr.Column و gr.Accordion
|
| 567 |
+
with gr.Sidebar(open=True) as login_page:
|
| 568 |
+
|
| 569 |
+
gr.Markdown("<h1 style='text-align: center;'>🧠 EMMA</h1><h3 style='text-align: center;'>Your Empathetic Mental Health Assistant</h3><br><p style='text-align: center;'>Please login or register to begin.</p>")
|
| 570 |
+
|
| 571 |
+
username_input = gr.Textbox(label="Your Name (Required)", placeholder="e.g., Alex")
|
| 572 |
+
login_status = gr.Textbox(visible=False, label="Status")
|
| 573 |
+
|
| 574 |
+
check_user_btn = gr.Button("🔍 Login / Check", variant="primary", elem_classes=["login-btn"])
|
| 575 |
+
|
| 576 |
+
with gr.Column(visible=False) as registration_fields:
|
| 577 |
+
gr.Markdown("### ✨ New User Registration")
|
| 578 |
+
age_input = gr.Textbox(label="Age", placeholder="e.g., 28")
|
| 579 |
+
gender_input = gr.Dropdown(label="Gender", choices=["Male", "Female", "Other"])
|
| 580 |
+
occupation_input = gr.Textbox(label="Occupation", placeholder="e.g., Student...")
|
| 581 |
+
residence_input = gr.Textbox(label="Place of Residence", placeholder="e.g., Berlin")
|
| 582 |
+
register_btn = gr.Button("🎯 Complete Registration", variant="primary", elem_classes=["login-btn"])
|
| 583 |
+
|
| 584 |
+
|
| 585 |
+
# ==========================================
|
| 586 |
+
# 2. CHAT PAGE (ستون سمت راست)
|
| 587 |
+
# ==========================================
|
| 588 |
+
# مقدار visible=False حذف شده و scale=3 اضافه شده است تا بخش چت بزرگتر باشد
|
| 589 |
+
with gr.Column(scale=3, elem_classes=["chat-box"]) as chat_page:
|
| 590 |
+
active_header = gr.Markdown("<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session</h2>")
|
| 591 |
+
#system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 592 |
+
|
| 593 |
+
with gr.Group():
|
| 594 |
+
chatbot = gr.Chatbot(label="💬 EMMA Conversation", height=350)
|
| 595 |
+
|
| 596 |
+
with gr.Row():
|
| 597 |
+
user_input = gr.Textbox(placeholder="Type your message here...", show_label=False, scale=6)
|
| 598 |
+
# اختصاص کلاس send-btn به دکمه Send
|
| 599 |
+
submit_btn = gr.Button("📤 Send", elem_classes=["send-btn"], scale=1)
|
| 600 |
+
|
| 601 |
+
# اختصاص کلاس bottom-actions-row به ردیف دکمههای پایین
|
| 602 |
+
with gr.Row(equal_height=True, elem_classes=["bottom-actions-row"]):
|
| 603 |
+
# اختصاص کلاس action-btn به دکمههای عملیاتی
|
| 604 |
+
clear_btn = gr.Button("🧹 Clear", elem_classes=["action-btn"])
|
| 605 |
+
new_session_btn = gr.Button("🔄 New Session", elem_classes=["action-btn"])
|
| 606 |
+
switch_user_btn = gr.Button("👥 Logout", elem_classes=["action-btn"])
|
| 607 |
+
system_msg = gr.Textbox(label="🔔 System Messages", interactive=False, max_lines=2)
|
| 608 |
+
|
| 609 |
+
# -------------------------------------------------------
|
| 610 |
+
# Internal Functions
|
| 611 |
+
# -------------------------------------------------------
|
| 612 |
+
def handle_login_check(name, state):
|
| 613 |
+
if not name.strip():
|
| 614 |
+
return (gr.update(), gr.update(), gr.update(), gr.update(visible=True, value="⚠️ Please enter a valid name."), gr.update(), gr.update(), state)
|
| 615 |
+
|
| 616 |
+
if name in memory:
|
| 617 |
+
hello_msg, user_memory, sessions_memory, episodic_memory, semantic_memory = enter_name_llamaindex(name, memory, data_args)
|
| 618 |
+
user_memory = summarize_memory_event_personality(data_args, memory, name)
|
| 619 |
+
|
| 620 |
+
new_state = state.copy()
|
| 621 |
+
new_state["user_name"] = name
|
| 622 |
+
new_state["memory"] = memory
|
| 623 |
+
new_state["initialized"] = True
|
| 624 |
+
new_state["semantic_memory_text"] = user_memory.get("semantic_memory", {})
|
| 625 |
+
new_state["semantic_memory_index"] = semantic_memory
|
| 626 |
+
new_state["user_memory_index"] = sessions_memory # یا هر نامی که ایندکس در آن است
|
| 627 |
+
new_state["episodic_memory_index"] = episodic_memory
|
| 628 |
+
new_state["history"] = []
|
| 629 |
+
|
| 630 |
+
|
| 631 |
+
|
| 632 |
+
|
| 633 |
+
welcome_msg = hello_msg if hello_msg else f"Welcome back, {name}!"
|
| 634 |
+
|
| 635 |
+
return (
|
| 636 |
+
gr.update(open=False), # 2. افزودن کلاس انیمیشن به جای visible=False
|
| 637 |
+
gr.update(visible=False),
|
| 638 |
+
gr.update(visible=True),
|
| 639 |
+
gr.update(visible=False, value=""),
|
| 640 |
+
gr.update(value=f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session for {name}</h2>"),
|
| 641 |
+
gr.update(value=welcome_msg),
|
| 642 |
+
new_state
|
| 643 |
+
)
|
| 644 |
+
else:
|
| 645 |
+
return (
|
| 646 |
+
gr.update(), # تغییری در صفحه اصلی لاگین ایجاد نمیشود
|
| 647 |
+
gr.update(visible=True),
|
| 648 |
+
gr.update(visible=False),
|
| 649 |
+
gr.update(visible=True, value="📝 New user detected. Please fill the details below."),
|
| 650 |
+
gr.update(),
|
| 651 |
+
gr.update(),
|
| 652 |
+
state
|
| 653 |
+
)
|
| 654 |
+
|
| 655 |
+
def handle_register(name, age, gender, occupation, residence, state):
|
| 656 |
+
name = str(name).strip()
|
| 657 |
+
|
| 658 |
+
if not name:
|
| 659 |
+
raise gr.Error("Please enter a valid user name.")
|
| 660 |
+
|
| 661 |
+
# Registration is only for new users.
|
| 662 |
+
if name in memory:
|
| 663 |
+
raise gr.Error(
|
| 664 |
+
f"User '{name}' already exists. Please use the login form."
|
| 665 |
+
)
|
| 666 |
+
|
| 667 |
+
# Create the user before trying to build or load their indices.
|
| 668 |
+
memory[name] = {
|
| 669 |
+
"profile": {
|
| 670 |
+
"age": age,
|
| 671 |
+
"gender": gender,
|
| 672 |
+
"occupation": occupation,
|
| 673 |
+
"residence": residence,
|
| 674 |
+
},
|
| 675 |
+
"sessions": [],
|
| 676 |
+
"episodic_memory": [],
|
| 677 |
+
"semantic_memory": {},
|
| 678 |
+
}
|
| 679 |
+
|
| 680 |
+
try:
|
| 681 |
+
(
|
| 682 |
+
_,
|
| 683 |
+
user_memory,
|
| 684 |
+
sessions_memory,
|
| 685 |
+
episodic_memory,
|
| 686 |
+
semantic_memory,
|
| 687 |
+
) = enter_name_llamaindex(
|
| 688 |
+
name=name,
|
| 689 |
+
memory=memory,
|
| 690 |
+
data_args=data_args,
|
| 691 |
+
update_memory_index=True,
|
| 692 |
+
)
|
| 693 |
+
except Exception:
|
| 694 |
+
# Avoid leaving a partially registered user in memory.
|
| 695 |
+
memory.pop(name, None)
|
| 696 |
+
raise
|
| 697 |
+
|
| 698 |
+
new_state = dict(state or {})
|
| 699 |
+
new_state.update(
|
| 700 |
+
{
|
| 701 |
+
"user_name": name,
|
| 702 |
+
"memory": memory,
|
| 703 |
+
"initialized": True,
|
| 704 |
+
"history": [],
|
| 705 |
+
"semantic_memory_text": user_memory.get("semantic_memory", {}),
|
| 706 |
+
"user_memory_index": sessions_memory,
|
| 707 |
+
"episodic_memory_index": episodic_memory,
|
| 708 |
+
"semantic_memory_index": semantic_memory,
|
| 709 |
+
}
|
| 710 |
+
)
|
| 711 |
+
|
| 712 |
+
welcome_msg = f"Welcome {name}! Registration complete."
|
| 713 |
+
|
| 714 |
+
return (
|
| 715 |
+
gr.update(open=False),
|
| 716 |
+
gr.update(visible=False),
|
| 717 |
+
gr.update(visible=True),
|
| 718 |
+
gr.update(visible=False, value=""),
|
| 719 |
+
gr.update(
|
| 720 |
+
value=(
|
| 721 |
+
"<h2 style='text-align: center; color: #333;'>"
|
| 722 |
+
f"🧠 EMMA: Session for {name}</h2>"
|
| 723 |
+
)
|
| 724 |
+
),
|
| 725 |
+
gr.update(value=welcome_msg),
|
| 726 |
+
new_state,
|
| 727 |
+
)
|
| 728 |
+
|
| 729 |
+
def switch_user(state):
|
| 730 |
+
if state["initialized"] and state["user_name"] in state["memory"]:
|
| 731 |
+
if state["memory"][state["user_name"]]["sessions"]:
|
| 732 |
+
previous_session = state["memory"][state["user_name"]]["sessions"][-1]
|
| 733 |
+
summary = extract_session_summary(previous_session["conversation"], previous_session["date"], len(state["memory"][state["user_name"]]["sessions"]) - 1)
|
| 734 |
+
state["memory"][state["user_name"]]["episodic_memory"].append(summary)
|
| 735 |
+
# ==========================================
|
| 736 |
+
# بهروزرسانی حافظه سمانتیک زمان خروج
|
| 737 |
+
# ==========================================
|
| 738 |
+
try:
|
| 739 |
+
user_mem = state["memory"][state["user_name"]]
|
| 740 |
+
existing_semantic = user_mem.get("semantic_memory", {})
|
| 741 |
+
|
| 742 |
+
updated_semantic = extract_semantic_memory(summary, existing_semantic)
|
| 743 |
+
|
| 744 |
+
state["memory"][state["user_name"]]["semantic_memory"] = updated_semantic
|
| 745 |
+
except Exception as e:
|
| 746 |
+
print(f"Error updating semantic memory on logout: {e}")
|
| 747 |
+
# ==========================================
|
| 748 |
+
|
| 749 |
+
new_state = state.copy()
|
| 750 |
+
new_state.update({"history": [], "user_name": None, "semantic_memory_text": "", "initialized": False})
|
| 751 |
+
|
| 752 |
+
return (
|
| 753 |
+
gr.update(open=True), # 1. باز شدن سایدبار
|
| 754 |
+
gr.update(visible=False), # 2. بسته شدن فرم ثبتنام
|
| 755 |
+
gr.update(visible=False), # 3. مخفی شدن صفحه چت
|
| 756 |
+
gr.update(value="Logged out successfully.", visible=True), # 4. پیام خروج
|
| 757 |
+
gr.update(value=""), # 5. پاک کردن نام کاربری
|
| 758 |
+
new_state, # 6. استیت جدید
|
| 759 |
+
gr.update(value=[]), # 7. پاک کردن چتبات
|
| 760 |
+
gr.update(value=""), # 8. پاک کردن age_input
|
| 761 |
+
gr.update(value=""), # 9. پاک کردن gender_input
|
| 762 |
+
gr.update(value=""), # 10. پاک کردن occupation_input
|
| 763 |
+
gr.update(value=""), # 11. پاک کردن residence_input
|
| 764 |
+
gr.update(value="") # 12. پاک کردن پیام سیستم (system_msg) اضافه شد
|
| 765 |
+
)
|
| 766 |
+
|
| 767 |
+
|
| 768 |
+
def handle_chat(user_message, state):
|
| 769 |
+
if not user_message.strip():
|
| 770 |
+
print("[handle_chat] empty message")
|
| 771 |
+
print("[handle_chat] state =", state)
|
| 772 |
+
# تبدیل return به yield
|
| 773 |
+
yield gr.update(), state.get("history", []), state
|
| 774 |
+
return
|
| 775 |
+
|
| 776 |
+
print("[handle_chat] user_message =", repr(user_message))
|
| 777 |
+
print("[handle_chat] state keys =", list(state.keys()) if isinstance(state, dict) else type(state))
|
| 778 |
+
print("[handle_chat] user_name =", state.get("user_name"))
|
| 779 |
+
print("[handle_chat] user_memory_index =", state.get("user_memory_index"))
|
| 780 |
+
print("[handle_chat] memory exists =", state.get("memory") is not None)
|
| 781 |
+
print("[handle_chat] service_context exists =", state.get("service_context") is not None)
|
| 782 |
+
print("[handle_chat] api_index =", state.get("api_index", 0))
|
| 783 |
+
print("[handle_chat] semantic_memory_text =", repr(state.get("semantic_memory_text", "")))
|
| 784 |
+
print("[handle_chat] history len =", len(state.get("history", [])))
|
| 785 |
+
|
| 786 |
+
# ==========================================
|
| 787 |
+
# ۱. نمایش فوری پیام کاربر و انیمیشن لودینگ
|
| 788 |
+
# ==========================================
|
| 789 |
+
current_history = state.get("history", [])
|
| 790 |
+
temp_history = current_history + [
|
| 791 |
+
{"role": "user", "content": user_message},
|
| 792 |
+
{"role": "assistant", "content": "<span class='typing-dots'>Generating</span>"}
|
| 793 |
+
]
|
| 794 |
+
|
| 795 |
+
# باکس متنی را پاک کرده و وضعیت موقت را بلافاصله به UI میفرستیم
|
| 796 |
+
yield gr.update(value=""), temp_history, state
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
# ادامه پردازشهای اصلی تابع شما
|
| 800 |
+
user_name = state.get("user_name")
|
| 801 |
+
user_memory_index = state.get("user_memory_index")
|
| 802 |
+
user_memory = state.get("user_memory", {})
|
| 803 |
+
user_memory_index = state.get("user_memory_index")
|
| 804 |
+
semantic_memory_text = state.get("semantic_memory_text", {})
|
| 805 |
+
service_context = state.get("service_context")
|
| 806 |
+
api_index = state.get("api_index", 0)
|
| 807 |
+
semantic_memory_text = state.get("semantic_memory_text", "")
|
| 808 |
+
|
| 809 |
+
# ==========================================
|
| 810 |
+
# استخراج پروفایل کاربر از حافظه
|
| 811 |
+
# ==========================================
|
| 812 |
+
user_profile = {}
|
| 813 |
+
if user_name and state.get("memory") and user_name in state["memory"]:
|
| 814 |
+
user_profile = state["memory"][user_name].get("profile", {})
|
| 815 |
+
# ==========================================
|
| 816 |
+
|
| 817 |
+
query_category = classify_query_local(user_message)
|
| 818 |
+
print("[handle_chat] query_category =", query_category)
|
| 819 |
+
|
| 820 |
+
# ارسال current_history به مدل (بدون انیمیشن موقت)
|
| 821 |
+
new_history, _, status_msg = predict_new(
|
| 822 |
+
text=user_message,
|
| 823 |
+
history=current_history,
|
| 824 |
+
top_p=0.95,
|
| 825 |
+
temperature=1.0,
|
| 826 |
+
max_length_tokens=1024,
|
| 827 |
+
max_context_length_tokens=4096,
|
| 828 |
+
user_name=user_name,
|
| 829 |
+
user_memory=user_memory,
|
| 830 |
+
user_memory_index=user_memory_index,
|
| 831 |
+
service_context=service_context,
|
| 832 |
+
api_index=api_index,
|
| 833 |
+
semantic_memory_text=semantic_memory_text,
|
| 834 |
+
query_category=query_category,
|
| 835 |
+
user_profile=user_profile
|
| 836 |
+
)
|
| 837 |
+
|
| 838 |
+
print("[handle_chat] status_msg =", status_msg)
|
| 839 |
+
print("[handle_chat] new_history len =", len(new_history))
|
| 840 |
+
|
| 841 |
+
state["history"] = new_history
|
| 842 |
+
print("[handle_chat] updated state history len =", len(state.get("history", [])))
|
| 843 |
+
|
| 844 |
+
# ==========================================
|
| 845 |
+
# ۳. جایگزینی پیام لودینگ با پاسخ نهایی
|
| 846 |
+
# ==========================================
|
| 847 |
+
yield gr.update(), new_history, state
|
| 848 |
+
|
| 849 |
+
def clear_history(state):
|
| 850 |
+
state["history"] = []
|
| 851 |
+
return [], state
|
| 852 |
+
|
| 853 |
+
def handle_new_session(state):
|
| 854 |
+
# بررسی اینکه آیا کاربر لاگین کرده است یا خیر
|
| 855 |
+
user_name = state.get("user_name")
|
| 856 |
+
if not user_name or "memory" not in state or user_name not in state["memory"]:
|
| 857 |
+
print("Error: User not logged in or memory missing.")
|
| 858 |
+
# خروجی اول برای chatbot (خالی) و خروجی دوم برای state
|
| 859 |
+
return [], state, gr.update() # خروجی سوم اضافه شد
|
| 860 |
+
|
| 861 |
+
# دریافت اطلاعات کاربر فعلی از داخل حافظه کلی
|
| 862 |
+
user_data = state["memory"][user_name]
|
| 863 |
+
|
| 864 |
+
# --- بخش اول: استخراج حافظه از جلسه قبلی ---
|
| 865 |
+
if user_data.get("sessions") and len(user_data["sessions"]) > 0:
|
| 866 |
+
last_session = user_data["sessions"][-1]
|
| 867 |
+
|
| 868 |
+
# فقط در صورتی حافظه را استخراج کن که جلسه قبلی خالی نباشد
|
| 869 |
+
if len(last_session.get("conversation", [])) > 0:
|
| 870 |
+
session_date = last_session.get("date", "")
|
| 871 |
+
session_id = last_session.get("session_id", 0)
|
| 872 |
+
|
| 873 |
+
# پاس دادن هر ۳ آرگومان به تابع
|
| 874 |
+
ep_summary = extract_session_summary(last_session["conversation"], session_date, session_id)
|
| 875 |
+
|
| 876 |
+
if "episodic_memory" not in user_data:
|
| 877 |
+
user_data["episodic_memory"] = []
|
| 878 |
+
user_data["episodic_memory"].append(ep_summary)
|
| 879 |
+
|
| 880 |
+
# ==========================================
|
| 881 |
+
# بهروزرسانی حافظه سمانتیک
|
| 882 |
+
# ==========================================
|
| 883 |
+
try:
|
| 884 |
+
# دریافت حافظه سمانتیک قبلی کاربر (اگر نداشت، یک دیکشنری خالی میدهیم)
|
| 885 |
+
existing_semantic = user_data.get("semantic_memory", {})
|
| 886 |
+
|
| 887 |
+
# فراخوانی تابع با هر دو آرگومان
|
| 888 |
+
updated_semantic = extract_semantic_memory(ep_summary, existing_semantic)
|
| 889 |
+
|
| 890 |
+
# ذخیره دیتای جدید
|
| 891 |
+
user_data["semantic_memory"] = updated_semantic
|
| 892 |
+
except Exception as e:
|
| 893 |
+
print(f"Error updating semantic memory: {e}")
|
| 894 |
+
# ==========================================
|
| 895 |
+
|
| 896 |
+
# --- بخش دوم: ایجاد جلسه جدید با اختصاص ID ---
|
| 897 |
+
new_session_id = len(user_data.get("sessions", []))
|
| 898 |
+
|
| 899 |
+
new_session = {
|
| 900 |
+
"session_id": new_session_id,
|
| 901 |
+
"date": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
| 902 |
+
"conversation": []
|
| 903 |
+
}
|
| 904 |
+
|
| 905 |
+
if "sessions" not in user_data:
|
| 906 |
+
user_data["sessions"] = []
|
| 907 |
+
|
| 908 |
+
user_data["sessions"].append(new_session)
|
| 909 |
+
|
| 910 |
+
# پاک کردن تاریخچه چت در state
|
| 911 |
+
state["history"] = []
|
| 912 |
+
|
| 913 |
+
# محاسبه شماره جلسه فعلی (چون از 0 شروع میشود، +1 میکنیم)
|
| 914 |
+
session_number = len(user_data["sessions"])
|
| 915 |
+
new_header_text = f"<h2 style='text-align: center; color: #333;'>🧠 EMMA: Session {session_number} for {user_name}</h2>"
|
| 916 |
+
|
| 917 |
+
# بازگرداندن خروجی جدید برای active_header
|
| 918 |
+
return [], state, gr.update(value=new_header_text)
|
| 919 |
+
|
| 920 |
+
check_user_btn.click(
|
| 921 |
+
handle_login_check,
|
| 922 |
+
inputs=[username_input, state],
|
| 923 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 924 |
+
# show_progress="hidden"
|
| 925 |
+
)
|
| 926 |
+
|
| 927 |
+
register_btn.click(
|
| 928 |
+
handle_register,
|
| 929 |
+
inputs=[username_input, age_input, gender_input, occupation_input, residence_input, state],
|
| 930 |
+
outputs=[login_page, registration_fields, chat_page, login_status, active_header, system_msg, state],
|
| 931 |
+
# show_progress="hidden"
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
switch_user_btn.click(
|
| 935 |
+
switch_user,
|
| 936 |
+
inputs=[state],
|
| 937 |
+
# system_msg به انتهای لیست خروجیها اضافه شد
|
| 938 |
+
outputs=[login_page, registration_fields, chat_page, login_status, username_input, state, chatbot, age_input, gender_input, occupation_input, residence_input, system_msg],
|
| 939 |
+
# show_progress="hidden"
|
| 940 |
+
)
|
| 941 |
+
|
| 942 |
+
|
| 943 |
+
submit_btn.click(
|
| 944 |
+
handle_chat,
|
| 945 |
+
inputs=[user_input, state],
|
| 946 |
+
outputs=[user_input, chatbot, state],
|
| 947 |
+
# show_progress="hidden"
|
| 948 |
+
)
|
| 949 |
+
|
| 950 |
+
user_input.submit(
|
| 951 |
+
handle_chat,
|
| 952 |
+
inputs=[user_input, state],
|
| 953 |
+
outputs=[user_input, chatbot, state],
|
| 954 |
+
# show_progress="hidden"
|
| 955 |
+
)
|
| 956 |
+
|
| 957 |
+
clear_btn.click(
|
| 958 |
+
clear_history,
|
| 959 |
+
inputs=[state],
|
| 960 |
+
outputs=[chatbot, state],
|
| 961 |
+
# show_progress="hidden"
|
| 962 |
+
)
|
| 963 |
+
|
| 964 |
+
# تغییر از clear_history به handle_new_session
|
| 965 |
+
new_session_btn.click(
|
| 966 |
+
handle_new_session,
|
| 967 |
+
inputs=[state],
|
| 968 |
+
outputs=[chatbot, state, active_header], # active_header به خروجی اضافه شد
|
| 969 |
+
# show_progress="hidden"
|
| 970 |
+
)
|
| 971 |
+
|
| 972 |
+
return demo
|
| 973 |
+
|
| 974 |
+
|
| 975 |
+
def main():
|
| 976 |
+
"""Main function to initialize and launch the interface."""
|
| 977 |
+
global api_keys
|
| 978 |
+
gapgpt_api_key = os.getenv("GAPGPT_API_KEY")
|
| 979 |
+
|
| 980 |
+
if not gapgpt_api_key:
|
| 981 |
+
print("Warning: GAPGPT_API_KEY environment variable is not set. Proceeding with keys from file.")
|
| 982 |
+
else:
|
| 983 |
+
# ست کردن متغیر محیطی برای جلوگیری از خطاهای ناگهانی کتابخانههای وابسته
|
| 984 |
+
os.environ["OPENAI_API_KEY"] = gapgpt_api_key
|
| 985 |
+
# حتماً Base URL را هم به متغیرهای محیطی اضافه کنید
|
| 986 |
+
os.environ["OPENAI_API_BASE"] = GAPGPT_BASE_URL
|
| 987 |
+
os.environ["OPENAI_BASE_URL"] = GAPGPT_BASE_URL
|
| 988 |
+
|
| 989 |
+
if gapgpt_api_key not in api_keys:
|
| 990 |
+
api_keys.insert(0, gapgpt_api_key)
|
| 991 |
+
|
| 992 |
+
# تنظیم LLM (مدل زبانی) - این بخش برای چت است و درست کار میکند
|
| 993 |
+
llm = LlamaIndexOpenAI(
|
| 994 |
+
model="gpt-4o",
|
| 995 |
+
temperature=1,
|
| 996 |
+
max_tokens=1024,
|
| 997 |
+
top_p=0.95,
|
| 998 |
+
frequency_penalty=0.4,
|
| 999 |
+
presence_penalty=0.2,
|
| 1000 |
+
api_key=gapgpt_api_key,
|
| 1001 |
+
api_base=GAPGPT_BASE_URL,
|
| 1002 |
+
)
|
| 1003 |
+
|
| 1004 |
+
# تغییر بسیار مهم: مدل را به ada-002 تغییر دهید تا ثبت نام کاربر جدید کار کند
|
| 1005 |
+
embed_model = OpenAIEmbedding(
|
| 1006 |
+
api_key=gapgpt_api_key,
|
| 1007 |
+
api_base=GAPGPT_BASE_URL,
|
| 1008 |
+
model="text-embedding-ada-002" # <--- این خط تغییر کرد
|
| 1009 |
+
)
|
| 1010 |
+
|
| 1011 |
+
# اعمال تنظیمات سراسری
|
| 1012 |
+
Settings.llm = llm
|
| 1013 |
+
Settings.embed_model = embed_model
|
| 1014 |
+
|
| 1015 |
+
Settings.prompt_helper = PromptHelper(
|
| 1016 |
+
context_window=4096,
|
| 1017 |
+
num_output=256,
|
| 1018 |
+
chunk_overlap_ratio=20 / 4096,
|
| 1019 |
+
tokenizer=tokenizer,
|
| 1020 |
+
)
|
| 1021 |
+
|
| 1022 |
+
demo = create_gradio_interface(Settings, api_keys)
|
| 1023 |
+
demo.launch(
|
| 1024 |
+
server_name="0.0.0.0",
|
| 1025 |
+
server_port=7860,
|
| 1026 |
+
share=False
|
| 1027 |
+
)
|
| 1028 |
+
|
| 1029 |
+
if __name__ == "__main__":
|
| 1030 |
+
signal.signal(signal.SIGINT, signal_handler)
|
| 1031 |
+
main()
|
Backup code/memory_utils copy 2.py
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import json
|
| 4 |
+
import time
|
| 5 |
+
import datetime
|
| 6 |
+
import shutil
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from pprint import pprint
|
| 9 |
+
import traceback
|
| 10 |
+
|
| 11 |
+
# LlamaIndex Imports
|
| 12 |
+
from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
|
| 13 |
+
|
| 14 |
+
# Local Imports setup
|
| 15 |
+
# Assuming this file is in 'utils/', we step back to find 'memory_bank'
|
| 16 |
+
bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
|
| 17 |
+
sys.path.append(bank_path)
|
| 18 |
+
|
| 19 |
+
# Import functions from sibling/child modules
|
| 20 |
+
# Ensure these files exist in the appended path
|
| 21 |
+
try:
|
| 22 |
+
from build_memory_index import build_memory_index
|
| 23 |
+
from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
|
| 24 |
+
except ImportError:
|
| 25 |
+
# Fallback or placeholder if running independently for testing
|
| 26 |
+
print("Warning: Could not import memory build/summary modules.")
|
| 27 |
+
def build_memory_index(*args, **kwargs): pass
|
| 28 |
+
def summarize_memory(*args, **kwargs): return {}
|
| 29 |
+
def extract_session_summary(*args, **kwargs): return {}
|
| 30 |
+
def extract_semantic_memory(*args, **kwargs): return {}
|
| 31 |
+
|
| 32 |
+
# --- Global Config for Paths ---
|
| 33 |
+
# Keeping the specific path requested by user
|
| 34 |
+
MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
|
| 38 |
+
"""
|
| 39 |
+
Legacy/Basic function to load user memory and initialize vector store.
|
| 40 |
+
"""
|
| 41 |
+
cur_date = datetime.date.today().strftime("%Y-%m-%d")
|
| 42 |
+
user_memory_index = None
|
| 43 |
+
|
| 44 |
+
# Handle Gradio States
|
| 45 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 46 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 47 |
+
if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
|
| 48 |
+
|
| 49 |
+
memory_dir = MEMORY_FILE_PATH
|
| 50 |
+
|
| 51 |
+
if name in memory.keys():
|
| 52 |
+
user_memory = memory[name]
|
| 53 |
+
memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
|
| 54 |
+
os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
|
| 55 |
+
|
| 56 |
+
if (not os.path.exists(memory_index_path)) or update_memory_index:
|
| 57 |
+
print(f'Initializing memory index {memory_index_path}...')
|
| 58 |
+
|
| 59 |
+
if os.path.exists(memory_index_path):
|
| 60 |
+
shutil.rmtree(memory_index_path)
|
| 61 |
+
# Initialize using the local QA object
|
| 62 |
+
memory_index_path, _ = local_memory_qa.init_memory_vector_store(
|
| 63 |
+
filepath=memory_dir,
|
| 64 |
+
vs_path=memory_index_path,
|
| 65 |
+
user_name=name,
|
| 66 |
+
cur_date=cur_date
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
|
| 70 |
+
msg = f"Welcome back, {name}!"
|
| 71 |
+
return msg, user_memory, memory, name, user_memory_index
|
| 72 |
+
else:
|
| 73 |
+
memory[name] = {}
|
| 74 |
+
memory[name].update({"name": name})
|
| 75 |
+
msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
|
| 76 |
+
return msg, memory[name], memory, name, user_memory_index
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
|
| 80 |
+
"""
|
| 81 |
+
Load the user's session, episodic, and semantic memory indices.
|
| 82 |
+
Compatible with LlamaIndex v0.10+.
|
| 83 |
+
"""
|
| 84 |
+
sessions_memory = None
|
| 85 |
+
episodic_memory = None
|
| 86 |
+
semantic_memory = None
|
| 87 |
+
|
| 88 |
+
print(f"[DEBUG] enter_name_llamaindex called with name={name!r}")
|
| 89 |
+
|
| 90 |
+
if name not in memory:
|
| 91 |
+
print(f"[DEBUG] user {name!r} not found in memory")
|
| 92 |
+
return "User not found.", None, None, None, None
|
| 93 |
+
|
| 94 |
+
user_memory = memory[name]
|
| 95 |
+
|
| 96 |
+
# Build one canonical absolute base path so build/load use the same location.
|
| 97 |
+
base_path = os.path.abspath(
|
| 98 |
+
os.path.join(
|
| 99 |
+
data_args.memory_basic_dir,
|
| 100 |
+
"..",
|
| 101 |
+
"memories",
|
| 102 |
+
"memory_index",
|
| 103 |
+
"llamaindex",
|
| 104 |
+
name,
|
| 105 |
+
)
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
sessions_path = os.path.join(base_path, "sessions")
|
| 109 |
+
episodic_path = os.path.join(base_path, "episodic_memory")
|
| 110 |
+
semantic_path = os.path.join(base_path, "semantic_memory")
|
| 111 |
+
|
| 112 |
+
print(f"[DEBUG] base_path: {base_path}")
|
| 113 |
+
print(f"[DEBUG] sessions_path: {sessions_path}")
|
| 114 |
+
print(f"[DEBUG] episodic_path: {episodic_path}")
|
| 115 |
+
print(f"[DEBUG] semantic_path: {semantic_path}")
|
| 116 |
+
|
| 117 |
+
indices_exist = (
|
| 118 |
+
os.path.isdir(sessions_path)
|
| 119 |
+
and os.path.isdir(episodic_path)
|
| 120 |
+
and os.path.isdir(semantic_path)
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
print(f"[DEBUG] indices_exist: {indices_exist}")
|
| 124 |
+
print(f"[DEBUG] update_memory_index: {update_memory_index}")
|
| 125 |
+
|
| 126 |
+
if update_memory_index or not indices_exist:
|
| 127 |
+
print(f"[DEBUG] Initializing memory indices for {name}...")
|
| 128 |
+
|
| 129 |
+
# Important: build_memory_index must persist to these same absolute paths.
|
| 130 |
+
build_memory_index(memory, data_args, name=name)
|
| 131 |
+
|
| 132 |
+
print("[DEBUG] After build:")
|
| 133 |
+
print(f"[DEBUG] sessions_path exists: {os.path.isdir(sessions_path)}")
|
| 134 |
+
print(f"[DEBUG] episodic_path exists: {os.path.isdir(episodic_path)}")
|
| 135 |
+
print(f"[DEBUG] semantic_path exists: {os.path.isdir(semantic_path)}")
|
| 136 |
+
|
| 137 |
+
def load_index_safe(index_name, index_path):
|
| 138 |
+
if not os.path.isdir(index_path):
|
| 139 |
+
print(f"[DEBUG] {index_name} path does not exist: {index_path}")
|
| 140 |
+
return None
|
| 141 |
+
|
| 142 |
+
try:
|
| 143 |
+
storage_context = StorageContext.from_defaults(
|
| 144 |
+
persist_dir=index_path
|
| 145 |
+
)
|
| 146 |
+
index = load_index_from_storage(storage_context)
|
| 147 |
+
print(
|
| 148 |
+
f"[DEBUG] {index_name} loaded: "
|
| 149 |
+
f"{type(index).__name__}, is_none={index is None}"
|
| 150 |
+
)
|
| 151 |
+
return index
|
| 152 |
+
except Exception as exc:
|
| 153 |
+
print(f"[ERROR] Could not load {index_name}: {exc}")
|
| 154 |
+
traceback.print_exc()
|
| 155 |
+
return None
|
| 156 |
+
|
| 157 |
+
sessions_memory = load_index_safe("sessions_memory", sessions_path)
|
| 158 |
+
episodic_memory = load_index_safe("episodic_memory", episodic_path)
|
| 159 |
+
semantic_memory = load_index_safe("semantic_memory", semantic_path)
|
| 160 |
+
|
| 161 |
+
print("[DEBUG] RETURN VALUES:")
|
| 162 |
+
print(f" hello_msg: Welcome back, {name}!")
|
| 163 |
+
print(f" user_memory type: {type(user_memory).__name__}")
|
| 164 |
+
print(f" sessions_memory type: {type(sessions_memory).__name__}")
|
| 165 |
+
print(f" episodic_memory type: {type(episodic_memory).__name__}")
|
| 166 |
+
print(f" semantic_memory type: {type(semantic_memory).__name__}")
|
| 167 |
+
|
| 168 |
+
return (
|
| 169 |
+
f"Welcome back, {name}!",
|
| 170 |
+
user_memory,
|
| 171 |
+
sessions_memory,
|
| 172 |
+
episodic_memory,
|
| 173 |
+
semantic_memory,
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def summarize_memory_event_personality(data_args, memory, user_name):
|
| 178 |
+
"""
|
| 179 |
+
Summarizes the memory and returns the user-specific memory dict.
|
| 180 |
+
"""
|
| 181 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 182 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 183 |
+
|
| 184 |
+
memory_dir = MEMORY_FILE_PATH
|
| 185 |
+
|
| 186 |
+
# Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
|
| 187 |
+
memory = summarize_memory(memory_dir, user_name, language=data_args.language)
|
| 188 |
+
user_memory = memory[user_name] if user_name in memory.keys() else {}
|
| 189 |
+
return user_memory
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
|
| 193 |
+
"""
|
| 194 |
+
Saves user-model conversations into memory and adds episodic memory for each session.
|
| 195 |
+
Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
|
| 196 |
+
"""
|
| 197 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 198 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 199 |
+
|
| 200 |
+
memory_dir = MEMORY_FILE_PATH
|
| 201 |
+
|
| 202 |
+
# 1. Initialize user memory with ALL required structures FIRST
|
| 203 |
+
if user_name not in memory:
|
| 204 |
+
memory[user_name] = {
|
| 205 |
+
"sessions": [],
|
| 206 |
+
"episodic_memory": [],
|
| 207 |
+
"semantic_memory": {}
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
# 2. Ensure all sub-structures exist and are correct type
|
| 211 |
+
memory[user_name].setdefault("sessions", [])
|
| 212 |
+
memory[user_name].setdefault("episodic_memory", [])
|
| 213 |
+
memory[user_name].setdefault("semantic_memory", {})
|
| 214 |
+
|
| 215 |
+
# 3. Now safely check types
|
| 216 |
+
if not isinstance(memory[user_name]["semantic_memory"], dict):
|
| 217 |
+
memory[user_name]["semantic_memory"] = {}
|
| 218 |
+
|
| 219 |
+
# Create new session or update existing one
|
| 220 |
+
if new_conversation or not memory[user_name]["sessions"]:
|
| 221 |
+
if new_conversation and memory[user_name]["sessions"]:
|
| 222 |
+
# Logic to summarize previous session before starting new one could go here
|
| 223 |
+
pass
|
| 224 |
+
|
| 225 |
+
# Create new session
|
| 226 |
+
session = {
|
| 227 |
+
"session_id": len(memory[user_name]["sessions"]),
|
| 228 |
+
"date": time.strftime("%Y-%m-%d", time.localtime()),
|
| 229 |
+
"conversation": []
|
| 230 |
+
}
|
| 231 |
+
memory[user_name]["sessions"].append(session)
|
| 232 |
+
|
| 233 |
+
current_session = memory[user_name]["sessions"][-1]
|
| 234 |
+
|
| 235 |
+
# --- Modified section to fix KeyError: 0 and handle History formats ---
|
| 236 |
+
if not new_conversation and history:
|
| 237 |
+
last_item = history[-1]
|
| 238 |
+
|
| 239 |
+
# Case 1: New Format (List of Dicts)
|
| 240 |
+
# In this format, history is linear. The last item is bot response, second to last is user query.
|
| 241 |
+
if isinstance(last_item, dict):
|
| 242 |
+
if len(history) >= 2:
|
| 243 |
+
user_query = history[-2].get('content', '')
|
| 244 |
+
bot_response = history[-1].get('content', '')
|
| 245 |
+
|
| 246 |
+
# Verify roles to ensure correct pairing
|
| 247 |
+
if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
|
| 248 |
+
current_session["conversation"].append({
|
| 249 |
+
'query': user_query,
|
| 250 |
+
'response': bot_response
|
| 251 |
+
})
|
| 252 |
+
|
| 253 |
+
# Case 2: Old Format (List of Lists/Tuples)
|
| 254 |
+
elif isinstance(last_item, (list, tuple)):
|
| 255 |
+
current_session["conversation"].append({
|
| 256 |
+
'query': last_item[0],
|
| 257 |
+
'response': last_item[1]
|
| 258 |
+
})
|
| 259 |
+
# ----------------------------------------------------------------------
|
| 260 |
+
|
| 261 |
+
# Optional: Update semantic memory in real-time
|
| 262 |
+
memory[user_name]["semantic_memory"] = extract_semantic_memory(
|
| 263 |
+
memory[user_name]["semantic_memory"],
|
| 264 |
+
current_session["conversation"]
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
semantic_memory_text = memory[user_name]["semantic_memory"]
|
| 268 |
+
|
| 269 |
+
# Save to file
|
| 270 |
+
# Ensure memory directory exists
|
| 271 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 272 |
+
|
| 273 |
+
with open(memory_dir, "w", encoding="utf-8") as f:
|
| 274 |
+
json.dump(memory, f, ensure_ascii=False, indent=4)
|
| 275 |
+
|
| 276 |
+
return memory, semantic_memory_text
|
Backup code/memory_utils copy.py
ADDED
|
@@ -0,0 +1,276 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import json
|
| 4 |
+
import time
|
| 5 |
+
import datetime
|
| 6 |
+
import shutil
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from pprint import pprint
|
| 9 |
+
import traceback
|
| 10 |
+
|
| 11 |
+
# LlamaIndex Imports
|
| 12 |
+
from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
|
| 13 |
+
|
| 14 |
+
# Local Imports setup
|
| 15 |
+
# Assuming this file is in 'utils/', we step back to find 'memory_bank'
|
| 16 |
+
bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
|
| 17 |
+
sys.path.append(bank_path)
|
| 18 |
+
|
| 19 |
+
# Import functions from sibling/child modules
|
| 20 |
+
# Ensure these files exist in the appended path
|
| 21 |
+
try:
|
| 22 |
+
from build_memory_index import build_memory_index
|
| 23 |
+
from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
|
| 24 |
+
except ImportError:
|
| 25 |
+
# Fallback or placeholder if running independently for testing
|
| 26 |
+
print("Warning: Could not import memory build/summary modules.")
|
| 27 |
+
def build_memory_index(*args, **kwargs): pass
|
| 28 |
+
def summarize_memory(*args, **kwargs): return {}
|
| 29 |
+
def extract_session_summary(*args, **kwargs): return {}
|
| 30 |
+
def extract_semantic_memory(*args, **kwargs): return {}
|
| 31 |
+
|
| 32 |
+
# --- Global Config for Paths ---
|
| 33 |
+
# Keeping the specific path requested by user
|
| 34 |
+
MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
|
| 38 |
+
"""
|
| 39 |
+
Legacy/Basic function to load user memory and initialize vector store.
|
| 40 |
+
"""
|
| 41 |
+
cur_date = datetime.date.today().strftime("%Y-%m-%d")
|
| 42 |
+
user_memory_index = None
|
| 43 |
+
|
| 44 |
+
# Handle Gradio States
|
| 45 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 46 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 47 |
+
if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
|
| 48 |
+
|
| 49 |
+
memory_dir = MEMORY_FILE_PATH
|
| 50 |
+
|
| 51 |
+
if name in memory.keys():
|
| 52 |
+
user_memory = memory[name]
|
| 53 |
+
memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
|
| 54 |
+
os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
|
| 55 |
+
|
| 56 |
+
if (not os.path.exists(memory_index_path)) or update_memory_index:
|
| 57 |
+
print(f'Initializing memory index {memory_index_path}...')
|
| 58 |
+
|
| 59 |
+
if os.path.exists(memory_index_path):
|
| 60 |
+
shutil.rmtree(memory_index_path)
|
| 61 |
+
# Initialize using the local QA object
|
| 62 |
+
memory_index_path, _ = local_memory_qa.init_memory_vector_store(
|
| 63 |
+
filepath=memory_dir,
|
| 64 |
+
vs_path=memory_index_path,
|
| 65 |
+
user_name=name,
|
| 66 |
+
cur_date=cur_date
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
|
| 70 |
+
msg = f"Welcome back, {name}!"
|
| 71 |
+
return msg, user_memory, memory, name, user_memory_index
|
| 72 |
+
else:
|
| 73 |
+
memory[name] = {}
|
| 74 |
+
memory[name].update({"name": name})
|
| 75 |
+
msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
|
| 76 |
+
return msg, memory[name], memory, name, user_memory_index
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
|
| 80 |
+
"""
|
| 81 |
+
Load the user's session, episodic, and semantic memory indices.
|
| 82 |
+
Compatible with LlamaIndex v0.10+.
|
| 83 |
+
"""
|
| 84 |
+
sessions_memory = None
|
| 85 |
+
episodic_memory = None
|
| 86 |
+
semantic_memory = None
|
| 87 |
+
|
| 88 |
+
print(f"[DEBUG] enter_name_llamaindex called with name={name!r}")
|
| 89 |
+
|
| 90 |
+
if name not in memory:
|
| 91 |
+
print(f"[DEBUG] user {name!r} not found in memory")
|
| 92 |
+
return "User not found.", None, None, None, None
|
| 93 |
+
|
| 94 |
+
user_memory = memory[name]
|
| 95 |
+
|
| 96 |
+
# Build one canonical absolute base path so build/load use the same location.
|
| 97 |
+
base_path = os.path.abspath(
|
| 98 |
+
os.path.join(
|
| 99 |
+
data_args.memory_basic_dir,
|
| 100 |
+
"..",
|
| 101 |
+
"memories",
|
| 102 |
+
"memory_index",
|
| 103 |
+
"llamaindex",
|
| 104 |
+
name,
|
| 105 |
+
)
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
sessions_path = os.path.join(base_path, "sessions")
|
| 109 |
+
episodic_path = os.path.join(base_path, "episodic_memory")
|
| 110 |
+
semantic_path = os.path.join(base_path, "semantic_memory")
|
| 111 |
+
|
| 112 |
+
print(f"[DEBUG] base_path: {base_path}")
|
| 113 |
+
print(f"[DEBUG] sessions_path: {sessions_path}")
|
| 114 |
+
print(f"[DEBUG] episodic_path: {episodic_path}")
|
| 115 |
+
print(f"[DEBUG] semantic_path: {semantic_path}")
|
| 116 |
+
|
| 117 |
+
indices_exist = (
|
| 118 |
+
os.path.isdir(sessions_path)
|
| 119 |
+
and os.path.isdir(episodic_path)
|
| 120 |
+
and os.path.isdir(semantic_path)
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
print(f"[DEBUG] indices_exist: {indices_exist}")
|
| 124 |
+
print(f"[DEBUG] update_memory_index: {update_memory_index}")
|
| 125 |
+
|
| 126 |
+
if update_memory_index or not indices_exist:
|
| 127 |
+
print(f"[DEBUG] Initializing memory indices for {name}...")
|
| 128 |
+
|
| 129 |
+
# Important: build_memory_index must persist to these same absolute paths.
|
| 130 |
+
build_memory_index(memory, data_args, name=name)
|
| 131 |
+
|
| 132 |
+
print("[DEBUG] After build:")
|
| 133 |
+
print(f"[DEBUG] sessions_path exists: {os.path.isdir(sessions_path)}")
|
| 134 |
+
print(f"[DEBUG] episodic_path exists: {os.path.isdir(episodic_path)}")
|
| 135 |
+
print(f"[DEBUG] semantic_path exists: {os.path.isdir(semantic_path)}")
|
| 136 |
+
|
| 137 |
+
def load_index_safe(index_name, index_path):
|
| 138 |
+
if not os.path.isdir(index_path):
|
| 139 |
+
print(f"[DEBUG] {index_name} path does not exist: {index_path}")
|
| 140 |
+
return None
|
| 141 |
+
|
| 142 |
+
try:
|
| 143 |
+
storage_context = StorageContext.from_defaults(
|
| 144 |
+
persist_dir=index_path
|
| 145 |
+
)
|
| 146 |
+
index = load_index_from_storage(storage_context)
|
| 147 |
+
print(
|
| 148 |
+
f"[DEBUG] {index_name} loaded: "
|
| 149 |
+
f"{type(index).__name__}, is_none={index is None}"
|
| 150 |
+
)
|
| 151 |
+
return index
|
| 152 |
+
except Exception as exc:
|
| 153 |
+
print(f"[ERROR] Could not load {index_name}: {exc}")
|
| 154 |
+
traceback.print_exc()
|
| 155 |
+
return None
|
| 156 |
+
|
| 157 |
+
sessions_memory = load_index_safe("sessions_memory", sessions_path)
|
| 158 |
+
episodic_memory = load_index_safe("episodic_memory", episodic_path)
|
| 159 |
+
semantic_memory = load_index_safe("semantic_memory", semantic_path)
|
| 160 |
+
|
| 161 |
+
print("[DEBUG] RETURN VALUES:")
|
| 162 |
+
print(f" hello_msg: Welcome back, {name}!")
|
| 163 |
+
print(f" user_memory type: {type(user_memory).__name__}")
|
| 164 |
+
print(f" sessions_memory type: {type(sessions_memory).__name__}")
|
| 165 |
+
print(f" episodic_memory type: {type(episodic_memory).__name__}")
|
| 166 |
+
print(f" semantic_memory type: {type(semantic_memory).__name__}")
|
| 167 |
+
|
| 168 |
+
return (
|
| 169 |
+
f"Welcome back, {name}!",
|
| 170 |
+
user_memory,
|
| 171 |
+
sessions_memory,
|
| 172 |
+
episodic_memory,
|
| 173 |
+
semantic_memory,
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def summarize_memory_event_personality(data_args, memory, user_name):
|
| 178 |
+
"""
|
| 179 |
+
Summarizes the memory and returns the user-specific memory dict.
|
| 180 |
+
"""
|
| 181 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 182 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 183 |
+
|
| 184 |
+
memory_dir = MEMORY_FILE_PATH
|
| 185 |
+
|
| 186 |
+
# Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
|
| 187 |
+
memory = summarize_memory(memory_dir, user_name, language=data_args.language)
|
| 188 |
+
user_memory = memory[user_name] if user_name in memory.keys() else {}
|
| 189 |
+
return user_memory
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
|
| 193 |
+
"""
|
| 194 |
+
Saves user-model conversations into memory and adds episodic memory for each session.
|
| 195 |
+
Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
|
| 196 |
+
"""
|
| 197 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 198 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 199 |
+
|
| 200 |
+
memory_dir = MEMORY_FILE_PATH
|
| 201 |
+
|
| 202 |
+
# 1. Initialize user memory with ALL required structures FIRST
|
| 203 |
+
if user_name not in memory:
|
| 204 |
+
memory[user_name] = {
|
| 205 |
+
"sessions": [],
|
| 206 |
+
"episodic_memory": [],
|
| 207 |
+
"semantic_memory": {}
|
| 208 |
+
}
|
| 209 |
+
|
| 210 |
+
# 2. Ensure all sub-structures exist and are correct type
|
| 211 |
+
memory[user_name].setdefault("sessions", [])
|
| 212 |
+
memory[user_name].setdefault("episodic_memory", [])
|
| 213 |
+
memory[user_name].setdefault("semantic_memory", {})
|
| 214 |
+
|
| 215 |
+
# 3. Now safely check types
|
| 216 |
+
if not isinstance(memory[user_name]["semantic_memory"], dict):
|
| 217 |
+
memory[user_name]["semantic_memory"] = {}
|
| 218 |
+
|
| 219 |
+
# Create new session or update existing one
|
| 220 |
+
if new_conversation or not memory[user_name]["sessions"]:
|
| 221 |
+
if new_conversation and memory[user_name]["sessions"]:
|
| 222 |
+
# Logic to summarize previous session before starting new one could go here
|
| 223 |
+
pass
|
| 224 |
+
|
| 225 |
+
# Create new session
|
| 226 |
+
session = {
|
| 227 |
+
"session_id": len(memory[user_name]["sessions"]),
|
| 228 |
+
"date": time.strftime("%Y-%m-%d", time.localtime()),
|
| 229 |
+
"conversation": []
|
| 230 |
+
}
|
| 231 |
+
memory[user_name]["sessions"].append(session)
|
| 232 |
+
|
| 233 |
+
current_session = memory[user_name]["sessions"][-1]
|
| 234 |
+
|
| 235 |
+
# --- Modified section to fix KeyError: 0 and handle History formats ---
|
| 236 |
+
if not new_conversation and history:
|
| 237 |
+
last_item = history[-1]
|
| 238 |
+
|
| 239 |
+
# Case 1: New Format (List of Dicts)
|
| 240 |
+
# In this format, history is linear. The last item is bot response, second to last is user query.
|
| 241 |
+
if isinstance(last_item, dict):
|
| 242 |
+
if len(history) >= 2:
|
| 243 |
+
user_query = history[-2].get('content', '')
|
| 244 |
+
bot_response = history[-1].get('content', '')
|
| 245 |
+
|
| 246 |
+
# Verify roles to ensure correct pairing
|
| 247 |
+
if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
|
| 248 |
+
current_session["conversation"].append({
|
| 249 |
+
'query': user_query,
|
| 250 |
+
'response': bot_response
|
| 251 |
+
})
|
| 252 |
+
|
| 253 |
+
# Case 2: Old Format (List of Lists/Tuples)
|
| 254 |
+
elif isinstance(last_item, (list, tuple)):
|
| 255 |
+
current_session["conversation"].append({
|
| 256 |
+
'query': last_item[0],
|
| 257 |
+
'response': last_item[1]
|
| 258 |
+
})
|
| 259 |
+
# ----------------------------------------------------------------------
|
| 260 |
+
|
| 261 |
+
# Optional: Update semantic memory in real-time
|
| 262 |
+
memory[user_name]["semantic_memory"] = extract_semantic_memory(
|
| 263 |
+
memory[user_name]["semantic_memory"],
|
| 264 |
+
current_session["conversation"]
|
| 265 |
+
)
|
| 266 |
+
|
| 267 |
+
semantic_memory_text = memory[user_name]["semantic_memory"]
|
| 268 |
+
|
| 269 |
+
# Save to file
|
| 270 |
+
# Ensure memory directory exists
|
| 271 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 272 |
+
|
| 273 |
+
with open(memory_dir, "w", encoding="utf-8") as f:
|
| 274 |
+
json.dump(memory, f, ensure_ascii=False, indent=4)
|
| 275 |
+
|
| 276 |
+
return memory, semantic_memory_text
|
Backup code/memory_utils.py
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import sys
|
| 3 |
+
import json
|
| 4 |
+
import time
|
| 5 |
+
import datetime
|
| 6 |
+
import shutil
|
| 7 |
+
import gradio as gr
|
| 8 |
+
from pprint import pprint
|
| 9 |
+
|
| 10 |
+
# LlamaIndex Imports
|
| 11 |
+
from llama_index.core import StorageContext, load_index_from_storage, VectorStoreIndex
|
| 12 |
+
|
| 13 |
+
# Local Imports setup
|
| 14 |
+
# Assuming this file is in 'utils/', we step back to find 'memory_bank'
|
| 15 |
+
bank_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../memory_bank')
|
| 16 |
+
sys.path.append(bank_path)
|
| 17 |
+
|
| 18 |
+
# Import functions from sibling/child modules
|
| 19 |
+
# Ensure these files exist in the appended path
|
| 20 |
+
try:
|
| 21 |
+
from build_memory_index import build_memory_index
|
| 22 |
+
from summarize_memory import summarize_memory, extract_session_summary, extract_semantic_memory
|
| 23 |
+
except ImportError:
|
| 24 |
+
# Fallback or placeholder if running independently for testing
|
| 25 |
+
print("Warning: Could not import memory build/summary modules.")
|
| 26 |
+
def build_memory_index(*args, **kwargs): pass
|
| 27 |
+
def summarize_memory(*args, **kwargs): return {}
|
| 28 |
+
def extract_session_summary(*args, **kwargs): return {}
|
| 29 |
+
def extract_semantic_memory(*args, **kwargs): return {}
|
| 30 |
+
|
| 31 |
+
# --- Global Config for Paths ---
|
| 32 |
+
# Keeping the specific path requested by user
|
| 33 |
+
MEMORY_FILE_PATH = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def enter_name(name, memory, local_memory_qa, data_args, update_memory_index=True):
|
| 37 |
+
"""
|
| 38 |
+
Legacy/Basic function to load user memory and initialize vector store.
|
| 39 |
+
"""
|
| 40 |
+
cur_date = datetime.date.today().strftime("%Y-%m-%d")
|
| 41 |
+
user_memory_index = None
|
| 42 |
+
|
| 43 |
+
# Handle Gradio States
|
| 44 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 45 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 46 |
+
if isinstance(local_memory_qa, gr.State): local_memory_qa = local_memory_qa.value
|
| 47 |
+
|
| 48 |
+
memory_dir = MEMORY_FILE_PATH
|
| 49 |
+
|
| 50 |
+
if name in memory.keys():
|
| 51 |
+
user_memory = memory[name]
|
| 52 |
+
memory_index_path = os.path.join(data_args.memory_basic_dir, f'memory_index/{name}_index')
|
| 53 |
+
os.makedirs(os.path.dirname(memory_index_path), exist_ok=True)
|
| 54 |
+
|
| 55 |
+
if (not os.path.exists(memory_index_path)) or update_memory_index:
|
| 56 |
+
print(f'Initializing memory index {memory_index_path}...')
|
| 57 |
+
|
| 58 |
+
if os.path.exists(memory_index_path):
|
| 59 |
+
shutil.rmtree(memory_index_path)
|
| 60 |
+
# Initialize using the local QA object
|
| 61 |
+
memory_index_path, _ = local_memory_qa.init_memory_vector_store(
|
| 62 |
+
filepath=memory_dir,
|
| 63 |
+
vs_path=memory_index_path,
|
| 64 |
+
user_name=name,
|
| 65 |
+
cur_date=cur_date
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
user_memory_index = local_memory_qa.load_memory_index(memory_index_path) if memory_index_path else None
|
| 69 |
+
msg = f"Welcome back, {name}!"
|
| 70 |
+
return msg, user_memory, memory, name, user_memory_index
|
| 71 |
+
else:
|
| 72 |
+
memory[name] = {}
|
| 73 |
+
memory[name].update({"name": name})
|
| 74 |
+
msg = f"Welcome, new user {name}! I will remember your name, so next time we meet, I'll be able to call you by your name!"
|
| 75 |
+
return msg, memory[name], memory, name, user_memory_index
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def enter_name_llamaindex(name, memory, data_args, update_memory_index=True):
|
| 79 |
+
"""
|
| 80 |
+
Loads user memory and separate indices for each memory type (sessions, episodic, semantic).
|
| 81 |
+
Compatible with LlamaIndex v0.10+
|
| 82 |
+
"""
|
| 83 |
+
sessions_memory = None
|
| 84 |
+
episodic_memory = None
|
| 85 |
+
semantic_memory = None
|
| 86 |
+
|
| 87 |
+
if name in memory.keys():
|
| 88 |
+
user_memory = memory[name]
|
| 89 |
+
|
| 90 |
+
# Set the base path
|
| 91 |
+
base_path = os.path.join(data_args.memory_basic_dir, f'../memories/memory_index/llamaindex/{name}')
|
| 92 |
+
|
| 93 |
+
# Define paths (باید به پوشهها اشاره کنند، نه فایل)
|
| 94 |
+
sessions_path = f"{base_path}/sessions" # یا نام دقیق پوشه شما
|
| 95 |
+
episodic_path = f"{base_path}/episodic_memory"
|
| 96 |
+
semantic_path = f"{base_path}/semantic_memory"
|
| 97 |
+
|
| 98 |
+
# Check if directories exist to decide on rebuilding
|
| 99 |
+
indices_exist = (
|
| 100 |
+
os.path.isdir(sessions_path) and
|
| 101 |
+
os.path.isdir(episodic_path) and
|
| 102 |
+
os.path.isdir(semantic_path)
|
| 103 |
+
)
|
| 104 |
+
|
| 105 |
+
# If indices do not exist or need updating, rebuild them
|
| 106 |
+
if update_memory_index or not indices_exist:
|
| 107 |
+
print(f'Initializing memory indices for {name}...')
|
| 108 |
+
build_memory_index(memory, data_args, name=name)
|
| 109 |
+
|
| 110 |
+
# --- Modified Section: Loading with new LlamaIndex method ---
|
| 111 |
+
|
| 112 |
+
# 1. Load Sessions Memory
|
| 113 |
+
if os.path.exists(sessions_path):
|
| 114 |
+
try:
|
| 115 |
+
storage_context = StorageContext.from_defaults(persist_dir=sessions_path)
|
| 116 |
+
sessions_memory = load_index_from_storage(storage_context)
|
| 117 |
+
print(f' → Loaded sessions memory index for {name}.')
|
| 118 |
+
except Exception as e:
|
| 119 |
+
print(f"Warning: Could not load sessions memory: {e}")
|
| 120 |
+
|
| 121 |
+
# 2. Load Episodic Memory
|
| 122 |
+
if os.path.exists(episodic_path):
|
| 123 |
+
try:
|
| 124 |
+
storage_context = StorageContext.from_defaults(persist_dir=episodic_path)
|
| 125 |
+
episodic_memory = load_index_from_storage(storage_context)
|
| 126 |
+
print(f' → Loaded episodic memory index for {name}.')
|
| 127 |
+
except Exception as e:
|
| 128 |
+
print(f"Warning: Could not load episodic memory: {e}")
|
| 129 |
+
|
| 130 |
+
# 3. Load Semantic Memory
|
| 131 |
+
if os.path.exists(semantic_path):
|
| 132 |
+
try:
|
| 133 |
+
storage_context = StorageContext.from_defaults(persist_dir=semantic_path)
|
| 134 |
+
semantic_memory = load_index_from_storage(storage_context)
|
| 135 |
+
print(f' → Loaded semantic memory index for {name}.')
|
| 136 |
+
except Exception as e:
|
| 137 |
+
print(f"Warning: Could not load semantic memory: {e}")
|
| 138 |
+
|
| 139 |
+
return f"Welcome back, {name}!", user_memory, sessions_memory, episodic_memory, semantic_memory
|
| 140 |
+
|
| 141 |
+
else:
|
| 142 |
+
# New User Initialization
|
| 143 |
+
memory[name] = {"name": name}
|
| 144 |
+
return f"Welcome, new user {name}! I'll remember your name for next time.", memory[name], None, None, None
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def summarize_memory_event_personality(data_args, memory, user_name):
|
| 148 |
+
"""
|
| 149 |
+
Summarizes the memory and returns the user-specific memory dict.
|
| 150 |
+
"""
|
| 151 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 152 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 153 |
+
|
| 154 |
+
memory_dir = MEMORY_FILE_PATH
|
| 155 |
+
|
| 156 |
+
# Note: Ensure summarize_memory handles the language argument correctly (passed 'en' or similar)
|
| 157 |
+
memory = summarize_memory(memory_dir, user_name, language=data_args.language)
|
| 158 |
+
user_memory = memory[user_name] if user_name in memory.keys() else {}
|
| 159 |
+
return user_memory
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def save_local_memory(memory, history, user_name, data_args, new_conversation=False):
|
| 163 |
+
"""
|
| 164 |
+
Saves user-model conversations into memory and adds episodic memory for each session.
|
| 165 |
+
Handles both list-of-lists (old Gradio) and list-of-dicts (new Gradio/OpenAI) formats.
|
| 166 |
+
"""
|
| 167 |
+
if isinstance(data_args, gr.State): data_args = data_args.value
|
| 168 |
+
if isinstance(memory, gr.State): memory = memory.value
|
| 169 |
+
|
| 170 |
+
memory_dir = MEMORY_FILE_PATH
|
| 171 |
+
|
| 172 |
+
# 1. Initialize user memory with ALL required structures FIRST
|
| 173 |
+
if user_name not in memory:
|
| 174 |
+
memory[user_name] = {
|
| 175 |
+
"sessions": [],
|
| 176 |
+
"episodic_memory": [],
|
| 177 |
+
"semantic_memory": {}
|
| 178 |
+
}
|
| 179 |
+
|
| 180 |
+
# 2. Ensure all sub-structures exist and are correct type
|
| 181 |
+
memory[user_name].setdefault("sessions", [])
|
| 182 |
+
memory[user_name].setdefault("episodic_memory", [])
|
| 183 |
+
memory[user_name].setdefault("semantic_memory", {})
|
| 184 |
+
|
| 185 |
+
# 3. Now safely check types
|
| 186 |
+
if not isinstance(memory[user_name]["semantic_memory"], dict):
|
| 187 |
+
memory[user_name]["semantic_memory"] = {}
|
| 188 |
+
|
| 189 |
+
# Create new session or update existing one
|
| 190 |
+
if new_conversation or not memory[user_name]["sessions"]:
|
| 191 |
+
if new_conversation and memory[user_name]["sessions"]:
|
| 192 |
+
# Logic to summarize previous session before starting new one could go here
|
| 193 |
+
pass
|
| 194 |
+
|
| 195 |
+
# Create new session
|
| 196 |
+
session = {
|
| 197 |
+
"session_id": len(memory[user_name]["sessions"]),
|
| 198 |
+
"date": time.strftime("%Y-%m-%d", time.localtime()),
|
| 199 |
+
"conversation": []
|
| 200 |
+
}
|
| 201 |
+
memory[user_name]["sessions"].append(session)
|
| 202 |
+
|
| 203 |
+
current_session = memory[user_name]["sessions"][-1]
|
| 204 |
+
|
| 205 |
+
# --- Modified section to fix KeyError: 0 and handle History formats ---
|
| 206 |
+
if not new_conversation and history:
|
| 207 |
+
last_item = history[-1]
|
| 208 |
+
|
| 209 |
+
# Case 1: New Format (List of Dicts)
|
| 210 |
+
# In this format, history is linear. The last item is bot response, second to last is user query.
|
| 211 |
+
if isinstance(last_item, dict):
|
| 212 |
+
if len(history) >= 2:
|
| 213 |
+
user_query = history[-2].get('content', '')
|
| 214 |
+
bot_response = history[-1].get('content', '')
|
| 215 |
+
|
| 216 |
+
# Verify roles to ensure correct pairing
|
| 217 |
+
if history[-2].get('role') == 'user' and history[-1].get('role') == 'assistant':
|
| 218 |
+
current_session["conversation"].append({
|
| 219 |
+
'query': user_query,
|
| 220 |
+
'response': bot_response
|
| 221 |
+
})
|
| 222 |
+
|
| 223 |
+
# Case 2: Old Format (List of Lists/Tuples)
|
| 224 |
+
elif isinstance(last_item, (list, tuple)):
|
| 225 |
+
current_session["conversation"].append({
|
| 226 |
+
'query': last_item[0],
|
| 227 |
+
'response': last_item[1]
|
| 228 |
+
})
|
| 229 |
+
# ----------------------------------------------------------------------
|
| 230 |
+
|
| 231 |
+
# Optional: Update semantic memory in real-time
|
| 232 |
+
# memory[user_name]["semantic_memory"] = extract_semantic_memory(
|
| 233 |
+
# memory[user_name]["semantic_memory"],
|
| 234 |
+
# current_session["conversation"]
|
| 235 |
+
# )
|
| 236 |
+
|
| 237 |
+
semantic_memory_text = memory[user_name]["semantic_memory"]
|
| 238 |
+
|
| 239 |
+
# Save to file
|
| 240 |
+
# Ensure memory directory exists
|
| 241 |
+
os.makedirs(os.path.dirname(memory_dir), exist_ok=True)
|
| 242 |
+
|
| 243 |
+
with open(memory_dir, "w", encoding="utf-8") as f:
|
| 244 |
+
json.dump(memory, f, ensure_ascii=False, indent=4)
|
| 245 |
+
|
| 246 |
+
return memory, semantic_memory_text
|
Backup code/prompt_utils.py
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import openai
|
| 2 |
+
from llama_index.core import Settings
|
| 3 |
+
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 4 |
+
from llama_index.llms.openai import OpenAI
|
| 5 |
+
|
| 6 |
+
Settings.llm = OpenAI(api_key="GAPGPT_API_KEY", api_base="https://api.gapgpt.app/v1", model="gpt-3.5-turbo")
|
| 7 |
+
Settings.embed_model = OpenAIEmbedding(api_key="GAPGPT_API_KEY", api_base="https://api.gapgpt.app/v1", model="text-embedding-ada-002")
|
| 8 |
+
|
| 9 |
+
boot_name_dict = {'en':'AI Companion'}
|
| 10 |
+
boot_actual_name_dict = {'en':'Emma'}
|
| 11 |
+
def output_prompt(history, user_name, boot_name):
|
| 12 |
+
prompt = f""
|
| 13 |
+
for dialog in history:
|
| 14 |
+
if isinstance(dialog, dict):
|
| 15 |
+
query = dialog.get('query', '')
|
| 16 |
+
response = dialog.get('response', '')
|
| 17 |
+
else:
|
| 18 |
+
query, response = dialog
|
| 19 |
+
prompt += f"\n\n{user_name}:{query}"
|
| 20 |
+
prompt += f"\n\n{boot_name}:{response}"
|
| 21 |
+
return prompt
|
| 22 |
+
|
| 23 |
+
def generate_meta_prompt_dict_chatgpt():
|
| 24 |
+
meta_prompt_dict = {'cn':"""
|
| 25 |
+
You play the role of an AI assistant in the field of psychology for this user ({user_name}).
|
| 26 |
+
Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
|
| 27 |
+
Use the following user-specific details to inform your response:
|
| 28 |
+
|
| 29 |
+
- **User's Psychological Profile:** {}
|
| 30 |
+
- **Summary of Past Interactions:** {}
|
| 31 |
+
- **Relevant Past Conversations:** {related_memory_content}
|
| 32 |
+
|
| 33 |
+
The user has asked:
|
| 34 |
+
|
| 35 |
+
Please provide an insightful and appropriate response considering their personal history.
|
| 36 |
+
""",
|
| 37 |
+
'en':"""
|
| 38 |
+
You play the role of an AI assistant in the field of psychology for this user ({user_name}).
|
| 39 |
+
Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
|
| 40 |
+
Use the following user-specific details to inform your response:
|
| 41 |
+
|
| 42 |
+
- **User's Psychological Profile:** {personality}
|
| 43 |
+
- **Summary of Past Interactions:** {history_summary}
|
| 44 |
+
- **Relevant Past Conversations:** {related_memory_content}
|
| 45 |
+
|
| 46 |
+
The user has asked:
|
| 47 |
+
|
| 48 |
+
Please provide an insightful and appropriate response considering their personal history.
|
| 49 |
+
""",}
|
| 50 |
+
return meta_prompt_dict
|
| 51 |
+
def generate_meta_prompt_dict_semantic_chatgpt():
|
| 52 |
+
meta_prompt_dict = {'cn':"""
|
| 53 |
+
""",
|
| 54 |
+
|
| 55 |
+
'en':"""
|
| 56 |
+
|
| 57 |
+
You play the role of an AI assistant in the field of psychology for this user ({user_name}).
|
| 58 |
+
Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
|
| 59 |
+
Use the following user-specific semantic memory{semantic_memory_text} to tailor your response:
|
| 60 |
+
""",}
|
| 61 |
+
return meta_prompt_dict
|
| 62 |
+
|
| 63 |
+
def generate_meta_prompt_dict_semantic_episodic_chatgpt():
|
| 64 |
+
meta_prompt_dict = {'cn':"""
|
| 65 |
+
You play the role of an AI assistant in the field of psychology for this user ({user_name}).
|
| 66 |
+
Your goal is to provide emotionally supportive, scientifically grounded, and empathetic responses.
|
| 67 |
+
Use the following user-specific details to inform your response:
|
| 68 |
+
|
| 69 |
+
- **User's Psychological Profile:** {}
|
| 70 |
+
- **Summary of Past Interactions:** {}
|
| 71 |
+
- **Relevant Past Conversations:** {related_memory_content}
|
| 72 |
+
|
| 73 |
+
The user has asked:
|
| 74 |
+
|
| 75 |
+
Please provide an insightful and appropriate response considering their personal history.
|
| 76 |
+
""",
|
| 77 |
+
|
| 78 |
+
'en': """
|
| 79 |
+
You are an AI assistant specializing in psychology, assisting the user ({user_name}) in a supportive, scientifically grounded, and empathetic manner.
|
| 80 |
+
|
| 81 |
+
Use the following memory sections to personalize your response:
|
| 82 |
+
|
| 83 |
+
- **User's Long-Term Traits and Psychological Characteristics (Semantic Memory):**
|
| 84 |
+
{semantic_memory_text}
|
| 85 |
+
|
| 86 |
+
- **Important Past Interactions or Events (Episodic Memory):**
|
| 87 |
+
{related_memory_content}
|
| 88 |
+
|
| 89 |
+
Respond by considering both the long-term traits and recent events of the user, offering personalized, emotionally intelligent support. Keep your response helpful, psychologically informed, and sensitive to the user's unique situation.
|
| 90 |
+
""",}
|
| 91 |
+
return meta_prompt_dict
|
| 92 |
+
|
| 93 |
+
def generate_new_user_meta_prompt_dict_chatgpt():
|
| 94 |
+
meta_prompt_dict = {'cn':"""
|
| 95 |
+
Now you will play the role of an companion AI Companion for user {user_name}, and your name is {boot_actual_name}. You should be able to: (1) provide warm companionship to chat users; (2) you are also an excellent psychological counselor, and when users confide in you about their difficulties and seek help, you can provide them with warm and helpful responses.
|
| 96 |
+
""",
|
| 97 |
+
'en':"""
|
| 98 |
+
Now you will play the role of an companion AI Companion for user {user_name}, and your name is {boot_actual_name}. You should be able to: (1) provide warm companionship to chat users; (2) you are also an excellent psychological counselor, and when users confide in you about their difficulties and seek help, you can provide them with warm and helpful responses.
|
| 99 |
+
"""}
|
| 100 |
+
return meta_prompt_dict
|
| 101 |
+
|
| 102 |
+
def generate_user_keyword():
|
| 103 |
+
return {'cn': '[|User|]', 'en': '[|User|]'}
|
| 104 |
+
|
| 105 |
+
def generate_ai_keyword():
|
| 106 |
+
return {'cn': '[|AI|]', 'en': '[|AI|]'}
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def build_prompt_with_search_memory_llamaindex(
|
| 110 |
+
history,
|
| 111 |
+
query,
|
| 112 |
+
user_memory,
|
| 113 |
+
user_name,
|
| 114 |
+
user_memory_index,
|
| 115 |
+
service_context,
|
| 116 |
+
api_keys,
|
| 117 |
+
api_index,
|
| 118 |
+
meta_prompt,
|
| 119 |
+
new_user_meta_prompt,
|
| 120 |
+
data_args,
|
| 121 |
+
boot_actual_name,
|
| 122 |
+
semantic_memory_text,
|
| 123 |
+
query_category,
|
| 124 |
+
meta_prompt_semantic,
|
| 125 |
+
meta_prompt_semantic_episodic
|
| 126 |
+
):
|
| 127 |
+
|
| 128 |
+
memory_search_query = query
|
| 129 |
+
related_memos = ""
|
| 130 |
+
|
| 131 |
+
print("memory_search_query:", memory_search_query)
|
| 132 |
+
#print("Total nodes in index:", len(user_memory_index.docstore.docs))
|
| 133 |
+
|
| 134 |
+
if user_memory_index:
|
| 135 |
+
retried_times = 2
|
| 136 |
+
count = 0
|
| 137 |
+
|
| 138 |
+
while not related_memos and count < retried_times:
|
| 139 |
+
try:
|
| 140 |
+
# تغییر اول: استفاده از as_retriever به جای as_query_engine
|
| 141 |
+
retriever = user_memory_index.as_retriever(
|
| 142 |
+
similarity_top_k=3,
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
# تغییر دوم: استفاده از متد retrieve
|
| 146 |
+
nodes = retriever.retrieve(memory_search_query)
|
| 147 |
+
|
| 148 |
+
# تغییر سوم: استخراج متن از گرههای پیدا شده
|
| 149 |
+
if nodes:
|
| 150 |
+
related_memos = "\n\n".join([n.node.text for n in nodes])
|
| 151 |
+
else:
|
| 152 |
+
related_memos = ""
|
| 153 |
+
|
| 154 |
+
except Exception as e:
|
| 155 |
+
print(f"Error querying index (attempt {count+1}/{retried_times}): {e}")
|
| 156 |
+
|
| 157 |
+
try:
|
| 158 |
+
api_index = (api_index + 1) % len(api_keys)
|
| 159 |
+
openai.api_key = api_keys[api_index]
|
| 160 |
+
except:
|
| 161 |
+
pass
|
| 162 |
+
|
| 163 |
+
related_memos = ""
|
| 164 |
+
|
| 165 |
+
count += 1
|
| 166 |
+
|
| 167 |
+
# Process history
|
| 168 |
+
print("related_memos found:", len(related_memos) if related_memos else 0)
|
| 169 |
+
|
| 170 |
+
history_summary = ""
|
| 171 |
+
if "overall_history" in user_memory:
|
| 172 |
+
history_summary = f"The summary of your past memories with the user is: {user_memory['overall_history']}"
|
| 173 |
+
|
| 174 |
+
personality = user_memory.get("overall_personality", "")
|
| 175 |
+
print("query_category:", query_category)
|
| 176 |
+
|
| 177 |
+
# Construct the prompt
|
| 178 |
+
if query_category == "semantic_memory":
|
| 179 |
+
prompt = meta_prompt_semantic.format(
|
| 180 |
+
user_name=user_name,
|
| 181 |
+
semantic_memory_text=semantic_memory_text
|
| 182 |
+
)
|
| 183 |
+
|
| 184 |
+
elif query_category == "semantic-episodic":
|
| 185 |
+
prompt = meta_prompt_semantic_episodic.format(
|
| 186 |
+
user_name=user_name,
|
| 187 |
+
history_summary=history_summary,
|
| 188 |
+
related_memory_content=f"\n{str(related_memos).strip()}\n" if related_memos else "None",
|
| 189 |
+
personality=personality,
|
| 190 |
+
boot_actual_name=boot_actual_name,
|
| 191 |
+
semantic_memory_text=semantic_memory_text
|
| 192 |
+
)
|
| 193 |
+
|
| 194 |
+
elif query_category == "episodic_memory":
|
| 195 |
+
if related_memos:
|
| 196 |
+
prompt = meta_prompt.format(
|
| 197 |
+
user_name=user_name,
|
| 198 |
+
history_summary=history_summary,
|
| 199 |
+
related_memory_content=f"\n{str(related_memos).strip()}\n",
|
| 200 |
+
personality=personality,
|
| 201 |
+
boot_actual_name=boot_actual_name
|
| 202 |
+
)
|
| 203 |
+
else:
|
| 204 |
+
prompt = new_user_meta_prompt.format(
|
| 205 |
+
user_name=user_name,
|
| 206 |
+
boot_actual_name=boot_actual_name
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
else:
|
| 210 |
+
prompt = new_user_meta_prompt.format(
|
| 211 |
+
user_name=user_name,
|
| 212 |
+
boot_actual_name=boot_actual_name
|
| 213 |
+
)
|
| 214 |
+
|
| 215 |
+
return prompt, related_memos
|
Backup code/summarize_memory_v4.py
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
import sys
|
| 3 |
+
import os
|
| 4 |
+
import json
|
| 5 |
+
import time
|
| 6 |
+
import copy
|
| 7 |
+
import argparse
|
| 8 |
+
from typing import Dict, Any
|
| 9 |
+
from openai import OpenAI
|
| 10 |
+
|
| 11 |
+
import openai
|
| 12 |
+
|
| 13 |
+
# Add memory bank path
|
| 14 |
+
sys.path.append('../memory_bank')
|
| 15 |
+
|
| 16 |
+
# Configuration for OpenAI API
|
| 17 |
+
CHATGPT_CONFIG = {
|
| 18 |
+
"model": "gpt-4o",
|
| 19 |
+
"temperature": 0.7,
|
| 20 |
+
"max_tokens": 400,
|
| 21 |
+
"top_p": 1.0,
|
| 22 |
+
"frequency_penalty": 0.4,
|
| 23 |
+
"presence_penalty": 0.2,
|
| 24 |
+
"stop": ["<|im_end|>", "¬Human"]
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
# Default memory directory
|
| 28 |
+
MEMORY_DIR = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
class LLMClientSimple:
|
| 32 |
+
def __init__(self, gen_config=None):
|
| 33 |
+
# ایجاد کلاینت جدید با سینتکس نسخه ۱ به بالا
|
| 34 |
+
# اگر برای GapGPT نیاز به base_url دارید، آن را اینجا اضافه کنید
|
| 35 |
+
self.client = OpenAI(
|
| 36 |
+
api_key=os.getenv("GAPGPT_API_KEY"),
|
| 37 |
+
base_url=os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 38 |
+
)
|
| 39 |
+
self.disable_tqdm = False
|
| 40 |
+
self.gen_config = gen_config
|
| 41 |
+
|
| 42 |
+
def generate_text_simple(self, prompt, prompt_num, language='en'):
|
| 43 |
+
self.gen_config['n'] = prompt_num
|
| 44 |
+
retry_times, count = 5, 0
|
| 45 |
+
response = None
|
| 46 |
+
|
| 47 |
+
while response is None and count < retry_times:
|
| 48 |
+
try:
|
| 49 |
+
request = copy.deepcopy(self.gen_config)
|
| 50 |
+
# print(prompt)
|
| 51 |
+
|
| 52 |
+
# System prompt setup based on language
|
| 53 |
+
if language == 'cn':
|
| 54 |
+
message = [
|
| 55 |
+
{"role": "system", "content": "The following is a transcript of a conversation between a human and a smart, psychology-savvy AI assistant."},
|
| 56 |
+
{"role": "user", "content": "Hello! Please help me summarize the conversation"},
|
| 57 |
+
{"role": "system", "content": "OK, I'll try to help you."},
|
| 58 |
+
{"role": "user", "content": f"{prompt}"}
|
| 59 |
+
]
|
| 60 |
+
else:
|
| 61 |
+
message = [
|
| 62 |
+
{"role": "system", "content": "Below is a transcript of a conversation between a human and an AI assistant that is intelligent and knowledgeable in psychology."},
|
| 63 |
+
{"role": "user", "content": "Hello! Please help me summarize the content of the conversation."},
|
| 64 |
+
{"role": "system", "content": "Sure, I will do my best to assist you."},
|
| 65 |
+
{"role": "user", "content": f"{prompt}"}
|
| 66 |
+
]
|
| 67 |
+
|
| 68 |
+
# فراخوانی متد جدید
|
| 69 |
+
response = self.client.chat.completions.create(**request, messages=message)
|
| 70 |
+
# print(prompt)
|
| 71 |
+
|
| 72 |
+
except Exception as e:
|
| 73 |
+
print(e)
|
| 74 |
+
# بررسی متن خطا در نسخه جدید ممکن است کمی متفاوت باشد
|
| 75 |
+
if 'context' in str(e).lower() or 'maximum' in str(e).lower():
|
| 76 |
+
cut_length = 1800 - 200 * count
|
| 77 |
+
print('max context length reached, cut to {}'.format(cut_length))
|
| 78 |
+
prompt = prompt[-cut_length:]
|
| 79 |
+
response = None
|
| 80 |
+
count += 1
|
| 81 |
+
|
| 82 |
+
if response:
|
| 83 |
+
# خواندن محتوای پاسخ با استفاده از سینتکس شیگرا (Dot notation)
|
| 84 |
+
task_desc = response.choices[0].message.content
|
| 85 |
+
else:
|
| 86 |
+
task_desc = ''
|
| 87 |
+
|
| 88 |
+
return task_desc
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
# Initialize the client
|
| 92 |
+
llm_client = LLMClientSimple(CHATGPT_CONFIG)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
# --- Prompt Generation Functions ---
|
| 96 |
+
|
| 97 |
+
def summarize_content_prompt(content, user_name, boot_name, language='en'):
|
| 98 |
+
# Base prompt adjusted based on psychology
|
| 99 |
+
prompt = 'Please summarize the following dialogue from a psychological perspective, focusing on the user\'s emotional state, key concerns, and potential therapeutic insights. Dialogue content:\n'
|
| 100 |
+
|
| 101 |
+
for dialog in content:
|
| 102 |
+
query = dialog['query']
|
| 103 |
+
response = dialog['response']
|
| 104 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 105 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 106 |
+
|
| 107 |
+
prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
|
| 108 |
+
return prompt
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def summarize_user_issues_prompt(content, user_name, boot_name, language='en'):
|
| 112 |
+
"""
|
| 113 |
+
Analyze the conversation from a psychological perspective, identify user problems and their causes,
|
| 114 |
+
and organize them into a structured JSON format.
|
| 115 |
+
"""
|
| 116 |
+
prompt = (
|
| 117 |
+
"Please analyze the following dialogue from a psychological perspective. Identify the user's key "
|
| 118 |
+
"problems and the underlying causes behind them. Structure the results in a clear and concise way. "
|
| 119 |
+
"Dialogue content:\n"
|
| 120 |
+
)
|
| 121 |
+
|
| 122 |
+
for dialog in content:
|
| 123 |
+
query = dialog['query']
|
| 124 |
+
response = dialog['response']
|
| 125 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 126 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 127 |
+
|
| 128 |
+
prompt += '\n\nPlease list the user’s problems and their causes in JSON format, like this:\n'
|
| 129 |
+
prompt += '{\n "problems": [\n {\n "problem": "<problem_1>",\n "cause": "<cause_1>"\n },\n {\n "problem": "<problem_2>",\n "cause": "<cause_2>"\n }\n ]\n}'
|
| 130 |
+
|
| 131 |
+
return prompt
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def summarize_overall_prompt(content, language='en'):
|
| 135 |
+
prompt = 'Please summarize the following events in a high-level manner, and try to be as concise as possible, summarizing and retaining the core key information:\n' if language == 'cn' else "Please provide a highly concise summary of the following event, capturing the essential key information as succinctly as possible. Summarize the event:\n"
|
| 136 |
+
|
| 137 |
+
for date, summary_dict in content:
|
| 138 |
+
summary = summary_dict['content']
|
| 139 |
+
prompt += (f"\nTime {date} The event that occurred was {summary.strip()}" if language == 'cn' else f"At {date}, the events are {summary.strip()}")
|
| 140 |
+
|
| 141 |
+
prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
|
| 142 |
+
return prompt
|
| 143 |
+
|
| 144 |
+
|
| 145 |
+
def summarize_overall_personality(content, language='en'):
|
| 146 |
+
prompt = 'Below are the personality traits and moods of users in multiple conversations, as well as the appropriate response strategies at the time:\n' if language == 'cn' else "The following are the user's exhibited personality traits and emotions throughout multiple dialogues, along with appropriate response strategies for the current situation:"
|
| 147 |
+
|
| 148 |
+
for date, summary in content:
|
| 149 |
+
prompt += (f"\n in time {date} The analysis is {summary.strip()}" if language == 'cn' else f"At {date}, the analysis shows {summary.strip()}")
|
| 150 |
+
|
| 151 |
+
prompt += ('\nPlease give a general summary of the users personality and the most appropriate response strategy for the AI lover, and try to be concise and highly summarized. The summary is:' if language == 'cn' else "Please provide a highly concise and general summary of the user's personality and the most appropriate response strategy for the AI lover, summarized as:")
|
| 152 |
+
return prompt
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def summarize_person_prompt(content, user_name, boot_name, language):
|
| 156 |
+
prompt = f"Based on the following dialogue, analyze {user_name}'s emotional state, cognitive patterns, and potential psychological needs. Suggest therapeutic strategies for the AI to respond empathetically and effectively. Dialogue content:\n"
|
| 157 |
+
|
| 158 |
+
for dialog in content:
|
| 159 |
+
query = dialog['query']
|
| 160 |
+
response = dialog['response']
|
| 161 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 162 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 163 |
+
|
| 164 |
+
prompt += (f'\n{user_name} personality traits, mood, {boot_name} The response strategy is:' if language == 'cn' else f"\n{user_name}'s personality traits, emotions, and {boot_name}'s response strategy are:")
|
| 165 |
+
return prompt
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
# --- Memory Extraction Functions ---
|
| 169 |
+
|
| 170 |
+
def extract_session_summary(conversation_text, session_date, session_id):
|
| 171 |
+
"""
|
| 172 |
+
Extracts session-level insights and creates an episodic memory entry.
|
| 173 |
+
|
| 174 |
+
Args:
|
| 175 |
+
conversation_text (str): The full conversation from the session.
|
| 176 |
+
session_date (str): The date of the session.
|
| 177 |
+
session_id (int): The index of the session.
|
| 178 |
+
|
| 179 |
+
Returns:
|
| 180 |
+
dict: Extracted episodic memory entry.
|
| 181 |
+
"""
|
| 182 |
+
# Prompt to the LLM to extract insights
|
| 183 |
+
insight_prompt = f"""
|
| 184 |
+
Please analyze the following conversation and extract key information:
|
| 185 |
+
Conversation:
|
| 186 |
+
{conversation_text}
|
| 187 |
+
|
| 188 |
+
1. Topics discussed (as a list)
|
| 189 |
+
2. User's emotional state (e.g., happy, anxious, stressed)
|
| 190 |
+
3. Key insights or takeaways (what the user is feeling or thinking)
|
| 191 |
+
|
| 192 |
+
Format response as JSON:
|
| 193 |
+
{{
|
| 194 |
+
"topics_discussed": [],
|
| 195 |
+
"emotional_state": "",
|
| 196 |
+
"insights": ""
|
| 197 |
+
}}
|
| 198 |
+
"""
|
| 199 |
+
|
| 200 |
+
response = llm_client.generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
|
| 201 |
+
|
| 202 |
+
# پاکسازی کاراکترهای اضافی و تگهای مارکداون
|
| 203 |
+
response = response.strip()
|
| 204 |
+
if response.startswith("```json"):response = response[7:]
|
| 205 |
+
elif response.startswith("```"):response = response[3:]
|
| 206 |
+
if response.endswith("```"):response = response[:-3]
|
| 207 |
+
response = response.strip()
|
| 208 |
+
try:
|
| 209 |
+
episodic_memory = json.loads(response)
|
| 210 |
+
except json.JSONDecodeError:
|
| 211 |
+
print("⚠️ Failed to parse episodic memory response!")
|
| 212 |
+
episodic_memory = {
|
| 213 |
+
"topics_discussed": ["N/A"],
|
| 214 |
+
"emotional_state": "unknown",
|
| 215 |
+
"insights": "No insights extracted."
|
| 216 |
+
}
|
| 217 |
+
|
| 218 |
+
# Add session metadata
|
| 219 |
+
episodic_memory["session_date"] = session_date
|
| 220 |
+
episodic_memory["session_id"] = session_id # Store session index
|
| 221 |
+
|
| 222 |
+
return episodic_memory
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
|
| 226 |
+
"""
|
| 227 |
+
Updates semantic memory based on the latest episodic memory.
|
| 228 |
+
|
| 229 |
+
Args:
|
| 230 |
+
latest_episodic_memory (dict): The most recent episodic memory entry.
|
| 231 |
+
existing_semantic_memory (dict): Current state of the user's semantic memory.
|
| 232 |
+
|
| 233 |
+
Returns:
|
| 234 |
+
dict: Updated semantic memory.
|
| 235 |
+
"""
|
| 236 |
+
# Use the insights from episodic memory to infer stable traits and patterns
|
| 237 |
+
semantic_prompt = f"""
|
| 238 |
+
Please analyze the following session summary and infer long-term personality traits and stable characteristics:
|
| 239 |
+
Session Summary:
|
| 240 |
+
{json.dumps(latest_episodic_memory, indent=4)}
|
| 241 |
+
|
| 242 |
+
Update the user's semantic memory with:
|
| 243 |
+
1. Evolving personality traits (Big Five).
|
| 244 |
+
2. Core values and recurring motivations.
|
| 245 |
+
3. Behavioral patterns and consistent emotional responses.
|
| 246 |
+
4. Frequent topics and recurring themes.
|
| 247 |
+
|
| 248 |
+
Format response as JSON:
|
| 249 |
+
{{
|
| 250 |
+
"personality_traits": {{
|
| 251 |
+
"openness": 0.0,
|
| 252 |
+
"conscientiousness": 0.0,
|
| 253 |
+
"extraversion": 0.0,
|
| 254 |
+
"agreeableness": 0.0,
|
| 255 |
+
"neuroticism": 0.0
|
| 256 |
+
}},
|
| 257 |
+
"core_values": [],
|
| 258 |
+
"behavioral_patterns": [],
|
| 259 |
+
"recurring_themes": []
|
| 260 |
+
}}
|
| 261 |
+
"""
|
| 262 |
+
|
| 263 |
+
response = llm_client.generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
|
| 264 |
+
|
| 265 |
+
# پاکسازی کاراکترهای اضافی و تگهای مارکداون
|
| 266 |
+
response = response.strip()
|
| 267 |
+
if response.startswith("```json"):response = response[7:]
|
| 268 |
+
elif response.startswith("```"):response = response[3:]
|
| 269 |
+
if response.endswith("```"):response = response[:-3]
|
| 270 |
+
response = response.strip()
|
| 271 |
+
|
| 272 |
+
# Parse the response
|
| 273 |
+
try:
|
| 274 |
+
new_semantic_data = json.loads(response)
|
| 275 |
+
except json.JSONDecodeError:
|
| 276 |
+
print("⚠️ Failed to parse semantic memory response!")
|
| 277 |
+
return existing_semantic_memory
|
| 278 |
+
|
| 279 |
+
# Merge new data into semantic memory
|
| 280 |
+
updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
|
| 281 |
+
|
| 282 |
+
# Update or average personality traits
|
| 283 |
+
for trait, value in new_semantic_data["personality_traits"].items():
|
| 284 |
+
if trait in updated_semantic_memory.get("personality_traits", {}):
|
| 285 |
+
existing_value = updated_semantic_memory["personality_traits"][trait]
|
| 286 |
+
updated_semantic_memory["personality_traits"][trait] = round((existing_value + value) / 2, 2)
|
| 287 |
+
else:
|
| 288 |
+
updated_semantic_memory.setdefault("personality_traits", {})[trait] = value
|
| 289 |
+
|
| 290 |
+
# Combine core values, avoiding duplicates
|
| 291 |
+
updated_semantic_memory["core_values"] = list(set(
|
| 292 |
+
updated_semantic_memory.get("core_values", []) + new_semantic_data["core_values"]
|
| 293 |
+
))
|
| 294 |
+
|
| 295 |
+
# Combine behavioral patterns
|
| 296 |
+
updated_semantic_memory["behavioral_patterns"] = list(set(
|
| 297 |
+
updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data["behavioral_patterns"]
|
| 298 |
+
))
|
| 299 |
+
|
| 300 |
+
# Combine recurring themes
|
| 301 |
+
updated_semantic_memory["recurring_themes"] = list(set(
|
| 302 |
+
updated_semantic_memory.get("recurring_themes", []) + new_semantic_data["recurring_themes"]
|
| 303 |
+
))
|
| 304 |
+
|
| 305 |
+
print("\n✅ Semantic memory updated successfully!")
|
| 306 |
+
return updated_semantic_memory
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
# --- Main Logic ---
|
| 310 |
+
|
| 311 |
+
def summarize_memory(memory_dir, name=None, language='en'):
|
| 312 |
+
boot_name = 'AI'
|
| 313 |
+
gen_prompt_num = 1
|
| 314 |
+
|
| 315 |
+
with open(memory_dir, 'r', encoding='utf8') as f:
|
| 316 |
+
memory = json.loads(f.read())
|
| 317 |
+
|
| 318 |
+
for k, v in memory.items():
|
| 319 |
+
if name is not None and k != name:
|
| 320 |
+
continue
|
| 321 |
+
|
| 322 |
+
user_name = k
|
| 323 |
+
print(f'Updating memory for user {user_name}')
|
| 324 |
+
|
| 325 |
+
if v.get('history') is None:
|
| 326 |
+
continue
|
| 327 |
+
|
| 328 |
+
history = v['history']
|
| 329 |
+
|
| 330 |
+
if v.get('summary') is None:
|
| 331 |
+
memory[user_name]['summary'] = {}
|
| 332 |
+
if v.get('personality') is None:
|
| 333 |
+
memory[user_name]['personality'] = {}
|
| 334 |
+
if v.get('issues') is None:
|
| 335 |
+
memory[user_name]['issues'] = {}
|
| 336 |
+
|
| 337 |
+
for date, content in history.items():
|
| 338 |
+
# Check flags to see if update is needed
|
| 339 |
+
his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
|
| 340 |
+
person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
|
| 341 |
+
problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
|
| 342 |
+
|
| 343 |
+
hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
|
| 344 |
+
issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
|
| 345 |
+
person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
|
| 346 |
+
|
| 347 |
+
if his_flag:
|
| 348 |
+
his_summary = llm_client.generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
|
| 349 |
+
memory[user_name]['summary'][date] = {'content': his_summary}
|
| 350 |
+
|
| 351 |
+
if problem_flag:
|
| 352 |
+
issues_summary = llm_client.generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
|
| 353 |
+
memory[user_name]['issues'][date] = {'content': issues_summary}
|
| 354 |
+
print(issues_summary)
|
| 355 |
+
|
| 356 |
+
if person_flag:
|
| 357 |
+
person_summary = llm_client.generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
|
| 358 |
+
memory[user_name]['personality'][date] = person_summary
|
| 359 |
+
|
| 360 |
+
overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
|
| 361 |
+
overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
|
| 362 |
+
|
| 363 |
+
memory[user_name]['overall_history'] = llm_client.generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
|
| 364 |
+
memory[user_name]['overall_personality'] = llm_client.generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
|
| 365 |
+
|
| 366 |
+
with open(memory_dir, 'w', encoding='utf8') as f:
|
| 367 |
+
print(f'Successfully updated memory for {name}')
|
| 368 |
+
json.dump(memory, f, ensure_ascii=False)
|
| 369 |
+
return memory
|
| 370 |
+
|
| 371 |
+
|
| 372 |
+
if __name__ == '__main__':
|
| 373 |
+
summarize_memory('../memories/eng_memory_cases.json', language='en')
|
Backup code/summarize_memory_v5.py
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
import sys
|
| 3 |
+
import os
|
| 4 |
+
import json
|
| 5 |
+
import time
|
| 6 |
+
import copy
|
| 7 |
+
import argparse
|
| 8 |
+
from typing import Dict, Any
|
| 9 |
+
from openai import OpenAI
|
| 10 |
+
import re
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
import openai
|
| 14 |
+
|
| 15 |
+
# Add memory bank path
|
| 16 |
+
sys.path.append('../memory_bank')
|
| 17 |
+
|
| 18 |
+
# Configuration for OpenAI API
|
| 19 |
+
CHATGPT_CONFIG = {
|
| 20 |
+
"model": "gpt-4o",
|
| 21 |
+
"temperature": 0.7,
|
| 22 |
+
"max_tokens": 400,
|
| 23 |
+
"top_p": 1.0,
|
| 24 |
+
"frequency_penalty": 0.4,
|
| 25 |
+
"presence_penalty": 0.2,
|
| 26 |
+
"stop": ["<|im_end|>", "¬Human"]
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
# Default memory directory
|
| 30 |
+
MEMORY_DIR = os.path.expanduser("C:\\Users\\keyva\\MMPL_gpt\\memories\\update_memory_0512_eng.json")
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class LLMClientSimple:
|
| 34 |
+
def __init__(self, gen_config=None):
|
| 35 |
+
# ایجاد کلاینت جدید با سینتکس نسخه ۱ به بالا
|
| 36 |
+
# اگر برای GapGPT نیاز به base_url دارید، آن را اینجا اضافه کنید
|
| 37 |
+
self.client = OpenAI(
|
| 38 |
+
api_key=os.getenv("GAPGPT_API_KEY"),
|
| 39 |
+
base_url=os.getenv("GAPGPT_BASE_URL", "https://api.gapgpt.app/v1")
|
| 40 |
+
)
|
| 41 |
+
self.disable_tqdm = False
|
| 42 |
+
self.gen_config = gen_config
|
| 43 |
+
|
| 44 |
+
def generate_text_simple(self, prompt, prompt_num, language='en'):
|
| 45 |
+
self.gen_config['n'] = prompt_num
|
| 46 |
+
retry_times, count = 5, 0
|
| 47 |
+
response = None
|
| 48 |
+
|
| 49 |
+
while response is None and count < retry_times:
|
| 50 |
+
try:
|
| 51 |
+
request = copy.deepcopy(self.gen_config)
|
| 52 |
+
# print(prompt)
|
| 53 |
+
|
| 54 |
+
# System prompt setup based on language
|
| 55 |
+
if language == 'cn':
|
| 56 |
+
message = [
|
| 57 |
+
{"role": "system", "content": "The following is a transcript of a conversation between a human and a smart, psychology-savvy AI assistant."},
|
| 58 |
+
{"role": "user", "content": "Hello! Please help me summarize the conversation"},
|
| 59 |
+
{"role": "system", "content": "OK, I'll try to help you."},
|
| 60 |
+
{"role": "user", "content": f"{prompt}"}
|
| 61 |
+
]
|
| 62 |
+
else:
|
| 63 |
+
message = [
|
| 64 |
+
{"role": "system", "content": "Below is a transcript of a conversation between a human and an AI assistant that is intelligent and knowledgeable in psychology."},
|
| 65 |
+
{"role": "user", "content": "Hello! Please help me summarize the content of the conversation."},
|
| 66 |
+
{"role": "system", "content": "Sure, I will do my best to assist you."},
|
| 67 |
+
{"role": "user", "content": f"{prompt}"}
|
| 68 |
+
]
|
| 69 |
+
|
| 70 |
+
# فراخوانی متد جدید
|
| 71 |
+
response = self.client.chat.completions.create(**request, messages=message)
|
| 72 |
+
# print(prompt)
|
| 73 |
+
|
| 74 |
+
except Exception as e:
|
| 75 |
+
print(e)
|
| 76 |
+
# بررسی متن خطا در نسخه جدید ممکن است کمی متفاوت باشد
|
| 77 |
+
if 'context' in str(e).lower() or 'maximum' in str(e).lower():
|
| 78 |
+
cut_length = 1800 - 200 * count
|
| 79 |
+
print('max context length reached, cut to {}'.format(cut_length))
|
| 80 |
+
prompt = prompt[-cut_length:]
|
| 81 |
+
response = None
|
| 82 |
+
count += 1
|
| 83 |
+
|
| 84 |
+
if response:
|
| 85 |
+
# خواندن محتوای پاسخ با استفاده از سینتکس شیگرا (Dot notation)
|
| 86 |
+
task_desc = response.choices[0].message.content
|
| 87 |
+
else:
|
| 88 |
+
task_desc = ''
|
| 89 |
+
|
| 90 |
+
return task_desc
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
# Initialize the client
|
| 94 |
+
llm_client = LLMClientSimple(CHATGPT_CONFIG)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
# --- Prompt Generation Functions ---
|
| 98 |
+
|
| 99 |
+
def summarize_content_prompt(content, user_name, boot_name, language='en'):
|
| 100 |
+
# Base prompt adjusted based on psychology
|
| 101 |
+
prompt = 'Please summarize the following dialogue from a psychological perspective, focusing on the user\'s emotional state, key concerns, and potential therapeutic insights. Dialogue content:\n'
|
| 102 |
+
|
| 103 |
+
for dialog in content:
|
| 104 |
+
query = dialog['query']
|
| 105 |
+
response = dialog['response']
|
| 106 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 107 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 108 |
+
|
| 109 |
+
prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
|
| 110 |
+
return prompt
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def summarize_user_issues_prompt(content, user_name, boot_name, language='en'):
|
| 114 |
+
"""
|
| 115 |
+
Analyze the conversation from a psychological perspective, identify user problems and their causes,
|
| 116 |
+
and organize them into a structured JSON format.
|
| 117 |
+
"""
|
| 118 |
+
prompt = (
|
| 119 |
+
"Please analyze the following dialogue from a psychological perspective. Identify the user's key "
|
| 120 |
+
"problems and the underlying causes behind them. Structure the results in a clear and concise way. "
|
| 121 |
+
"Dialogue content:\n"
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
for dialog in content:
|
| 125 |
+
query = dialog['query']
|
| 126 |
+
response = dialog['response']
|
| 127 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 128 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 129 |
+
|
| 130 |
+
prompt += '\n\nPlease list the user’s problems and their causes in JSON format, like this:\n'
|
| 131 |
+
prompt += '{\n "problems": [\n {\n "problem": "<problem_1>",\n "cause": "<cause_1>"\n },\n {\n "problem": "<problem_2>",\n "cause": "<cause_2>"\n }\n ]\n}'
|
| 132 |
+
|
| 133 |
+
return prompt
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def summarize_overall_prompt(content, language='en'):
|
| 137 |
+
prompt = 'Please summarize the following events in a high-level manner, and try to be as concise as possible, summarizing and retaining the core key information:\n' if language == 'cn' else "Please provide a highly concise summary of the following event, capturing the essential key information as succinctly as possible. Summarize the event:\n"
|
| 138 |
+
|
| 139 |
+
for date, summary_dict in content:
|
| 140 |
+
summary = summary_dict['content']
|
| 141 |
+
prompt += (f"\nTime {date} The event that occurred was {summary.strip()}" if language == 'cn' else f"At {date}, the events are {summary.strip()}")
|
| 142 |
+
|
| 143 |
+
prompt += ('\nSummary:' if language == 'cn' else '\nSummarization:')
|
| 144 |
+
return prompt
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def summarize_overall_personality(content, language='en'):
|
| 148 |
+
prompt = 'Below are the personality traits and moods of users in multiple conversations, as well as the appropriate response strategies at the time:\n' if language == 'cn' else "The following are the user's exhibited personality traits and emotions throughout multiple dialogues, along with appropriate response strategies for the current situation:"
|
| 149 |
+
|
| 150 |
+
for date, summary in content:
|
| 151 |
+
prompt += (f"\n in time {date} The analysis is {summary.strip()}" if language == 'cn' else f"At {date}, the analysis shows {summary.strip()}")
|
| 152 |
+
|
| 153 |
+
prompt += ('\nPlease give a general summary of the users personality and the most appropriate response strategy for the AI lover, and try to be concise and highly summarized. The summary is:' if language == 'cn' else "Please provide a highly concise and general summary of the user's personality and the most appropriate response strategy for the AI lover, summarized as:")
|
| 154 |
+
return prompt
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def summarize_person_prompt(content, user_name, boot_name, language):
|
| 158 |
+
prompt = f"Based on the following dialogue, analyze {user_name}'s emotional state, cognitive patterns, and potential psychological needs. Suggest therapeutic strategies for the AI to respond empathetically and effectively. Dialogue content:\n"
|
| 159 |
+
|
| 160 |
+
for dialog in content:
|
| 161 |
+
query = dialog['query']
|
| 162 |
+
response = dialog['response']
|
| 163 |
+
prompt += f"\n{user_name}: {query.strip()}"
|
| 164 |
+
prompt += f"\n{boot_name}: {response.strip()}"
|
| 165 |
+
|
| 166 |
+
prompt += (f'\n{user_name} personality traits, mood, {boot_name} The response strategy is:' if language == 'cn' else f"\n{user_name}'s personality traits, emotions, and {boot_name}'s response strategy are:")
|
| 167 |
+
return prompt
|
| 168 |
+
|
| 169 |
+
|
| 170 |
+
# --- Memory Extraction Functions ---
|
| 171 |
+
|
| 172 |
+
def extract_session_summary(conversation_text, session_date, session_id):
|
| 173 |
+
"""
|
| 174 |
+
Extracts session-level insights and creates an episodic memory entry.
|
| 175 |
+
|
| 176 |
+
Args:
|
| 177 |
+
conversation_text (str): The full conversation from the session.
|
| 178 |
+
session_date (str): The date of the session.
|
| 179 |
+
session_id (int): The index of the session.
|
| 180 |
+
|
| 181 |
+
Returns:
|
| 182 |
+
dict: Extracted episodic memory entry.
|
| 183 |
+
"""
|
| 184 |
+
# Prompt to the LLM to extract insights
|
| 185 |
+
insight_prompt = f"""
|
| 186 |
+
Please analyze the following conversation and extract key information:
|
| 187 |
+
Conversation:
|
| 188 |
+
{conversation_text}
|
| 189 |
+
|
| 190 |
+
1. Topics discussed (as a list)
|
| 191 |
+
2. User's emotional state (e.g., happy, anxious, stressed)
|
| 192 |
+
3. Key insights or takeaways (what the user is feeling or thinking)
|
| 193 |
+
|
| 194 |
+
Format response as JSON:
|
| 195 |
+
{{
|
| 196 |
+
"topics_discussed": [],
|
| 197 |
+
"emotional_state": "",
|
| 198 |
+
"insights": ""
|
| 199 |
+
}}
|
| 200 |
+
"""
|
| 201 |
+
|
| 202 |
+
response = llm_client.generate_text_simple(prompt=insight_prompt, prompt_num=1, language='en')
|
| 203 |
+
|
| 204 |
+
# پاکسازی کاراکترهای اضافی و تگهای مارکداون
|
| 205 |
+
response = response.strip()
|
| 206 |
+
if response.startswith("```json"):response = response[7:]
|
| 207 |
+
elif response.startswith("```"):response = response[3:]
|
| 208 |
+
if response.endswith("```"):response = response[:-3]
|
| 209 |
+
response = response.strip()
|
| 210 |
+
try:
|
| 211 |
+
episodic_memory = json.loads(response)
|
| 212 |
+
except json.JSONDecodeError:
|
| 213 |
+
print("⚠️ Failed to parse episodic memory response!")
|
| 214 |
+
episodic_memory = {
|
| 215 |
+
"topics_discussed": ["N/A"],
|
| 216 |
+
"emotional_state": "unknown",
|
| 217 |
+
"insights": "No insights extracted."
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
+
# Add session metadata
|
| 221 |
+
episodic_memory["session_date"] = session_date
|
| 222 |
+
episodic_memory["session_id"] = session_id # Store session index
|
| 223 |
+
|
| 224 |
+
return episodic_memory
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def extract_semantic_memory(latest_episodic_memory, existing_semantic_memory):
|
| 228 |
+
"""
|
| 229 |
+
Updates semantic memory based on the latest episodic memory.
|
| 230 |
+
|
| 231 |
+
Args:
|
| 232 |
+
latest_episodic_memory (dict): The most recent episodic memory entry.
|
| 233 |
+
existing_semantic_memory (dict): Current state of the user's semantic memory.
|
| 234 |
+
|
| 235 |
+
Returns:
|
| 236 |
+
dict: Updated semantic memory.
|
| 237 |
+
"""
|
| 238 |
+
# Use the insights from episodic memory to infer stable traits and patterns
|
| 239 |
+
semantic_prompt = f"""
|
| 240 |
+
Please analyze the following session summary and infer long-term personality traits and stable characteristics:
|
| 241 |
+
Session Summary:
|
| 242 |
+
{json.dumps(latest_episodic_memory, indent=4)}
|
| 243 |
+
|
| 244 |
+
Update the user's semantic memory with:
|
| 245 |
+
1. Evolving personality traits (Big Five).
|
| 246 |
+
2. Core values and recurring motivations.
|
| 247 |
+
3. Behavioral patterns and consistent emotional responses.
|
| 248 |
+
4. Frequent topics and recurring themes.
|
| 249 |
+
|
| 250 |
+
Format response as JSON:
|
| 251 |
+
{{
|
| 252 |
+
"personality_traits": {{
|
| 253 |
+
"openness": 0.0,
|
| 254 |
+
"conscientiousness": 0.0,
|
| 255 |
+
"extraversion": 0.0,
|
| 256 |
+
"agreeableness": 0.0,
|
| 257 |
+
"neuroticism": 0.0
|
| 258 |
+
}},
|
| 259 |
+
"core_values": [],
|
| 260 |
+
"behavioral_patterns": [],
|
| 261 |
+
"recurring_themes": []
|
| 262 |
+
}}
|
| 263 |
+
"""
|
| 264 |
+
|
| 265 |
+
response = llm_client.generate_text_simple(prompt=semantic_prompt, prompt_num=1, language='en')
|
| 266 |
+
|
| 267 |
+
# استخراج امن JSON با استفاده از Regex
|
| 268 |
+
try:
|
| 269 |
+
# پیدا کردن محتوای بین اولین { و آخرین }
|
| 270 |
+
json_match = re.search(r'\{.*\}', response, re.DOTALL)
|
| 271 |
+
if json_match:
|
| 272 |
+
json_str = json_match.group(0)
|
| 273 |
+
new_semantic_data = json.loads(json_str)
|
| 274 |
+
else:
|
| 275 |
+
raise ValueError("No JSON object found in response.")
|
| 276 |
+
|
| 277 |
+
except Exception as e:
|
| 278 |
+
print(f"⚠️ Failed to parse semantic memory response! Error: {e}")
|
| 279 |
+
print(f"LLM Response was:\n{response}") # چاپ خروجی خام برای خطایابی
|
| 280 |
+
return existing_semantic_memory
|
| 281 |
+
|
| 282 |
+
# Merge new data into semantic memory
|
| 283 |
+
updated_semantic_memory = existing_semantic_memory if isinstance(existing_semantic_memory, dict) else {}
|
| 284 |
+
|
| 285 |
+
# Update or average personality traits
|
| 286 |
+
for trait, value in new_semantic_data.get("personality_traits", {}).items():
|
| 287 |
+
try:
|
| 288 |
+
val_float = float(value)
|
| 289 |
+
except (ValueError, TypeError):
|
| 290 |
+
val_float = 0.0
|
| 291 |
+
|
| 292 |
+
if trait in updated_semantic_memory.get("personality_traits", {}):
|
| 293 |
+
existing_value = float(updated_semantic_memory["personality_traits"].get(trait, 0.0))
|
| 294 |
+
updated_semantic_memory["personality_traits"][trait] = round((existing_value + val_float) / 2, 2)
|
| 295 |
+
else:
|
| 296 |
+
updated_semantic_memory.setdefault("personality_traits", {})[trait] = val_float
|
| 297 |
+
|
| 298 |
+
# Combine core values, avoiding duplicates
|
| 299 |
+
updated_semantic_memory["core_values"] = list(set(
|
| 300 |
+
updated_semantic_memory.get("core_values", []) + new_semantic_data.get("core_values", [])
|
| 301 |
+
))
|
| 302 |
+
|
| 303 |
+
# Combine behavioral patterns
|
| 304 |
+
updated_semantic_memory["behavioral_patterns"] = list(set(
|
| 305 |
+
updated_semantic_memory.get("behavioral_patterns", []) + new_semantic_data.get("behavioral_patterns", [])
|
| 306 |
+
))
|
| 307 |
+
|
| 308 |
+
# Combine recurring themes
|
| 309 |
+
updated_semantic_memory["recurring_themes"] = list(set(
|
| 310 |
+
updated_semantic_memory.get("recurring_themes", []) + new_semantic_data.get("recurring_themes", [])
|
| 311 |
+
))
|
| 312 |
+
|
| 313 |
+
print("\n✅ Semantic memory updated successfully!")
|
| 314 |
+
return updated_semantic_memory
|
| 315 |
+
|
| 316 |
+
|
| 317 |
+
# --- Main Logic ---
|
| 318 |
+
|
| 319 |
+
def summarize_memory(memory_dir, name=None, language='en'):
|
| 320 |
+
boot_name = 'AI'
|
| 321 |
+
gen_prompt_num = 1
|
| 322 |
+
|
| 323 |
+
with open(memory_dir, 'r', encoding='utf8') as f:
|
| 324 |
+
memory = json.loads(f.read())
|
| 325 |
+
|
| 326 |
+
for k, v in memory.items():
|
| 327 |
+
if name is not None and k != name:
|
| 328 |
+
continue
|
| 329 |
+
|
| 330 |
+
user_name = k
|
| 331 |
+
print(f'Updating memory for user {user_name}')
|
| 332 |
+
|
| 333 |
+
if v.get('history') is None:
|
| 334 |
+
continue
|
| 335 |
+
|
| 336 |
+
history = v['history']
|
| 337 |
+
|
| 338 |
+
if v.get('summary') is None:
|
| 339 |
+
memory[user_name]['summary'] = {}
|
| 340 |
+
if v.get('personality') is None:
|
| 341 |
+
memory[user_name]['personality'] = {}
|
| 342 |
+
if v.get('issues') is None:
|
| 343 |
+
memory[user_name]['issues'] = {}
|
| 344 |
+
|
| 345 |
+
for date, content in history.items():
|
| 346 |
+
# Check flags to see if update is needed
|
| 347 |
+
his_flag = False if (date in v['summary'].keys() and v['summary'][date]) else True
|
| 348 |
+
person_flag = False if (date in v['personality'].keys() and v['personality'][date]) else True
|
| 349 |
+
problem_flag = False if (date in v['issues'].keys() and v['issues'][date]) else True
|
| 350 |
+
|
| 351 |
+
hisprompt = summarize_content_prompt(content, user_name, boot_name, language)
|
| 352 |
+
issues_prompt = summarize_user_issues_prompt(content, user_name, boot_name, language)
|
| 353 |
+
person_prompt = summarize_person_prompt(content, user_name, boot_name, language)
|
| 354 |
+
|
| 355 |
+
if his_flag:
|
| 356 |
+
his_summary = llm_client.generate_text_simple(prompt=hisprompt, prompt_num=gen_prompt_num, language=language)
|
| 357 |
+
memory[user_name]['summary'][date] = {'content': his_summary}
|
| 358 |
+
|
| 359 |
+
if problem_flag:
|
| 360 |
+
issues_summary = llm_client.generate_text_simple(prompt=issues_prompt, prompt_num=gen_prompt_num, language=language)
|
| 361 |
+
memory[user_name]['issues'][date] = {'content': issues_summary}
|
| 362 |
+
print(issues_summary)
|
| 363 |
+
|
| 364 |
+
if person_flag:
|
| 365 |
+
person_summary = llm_client.generate_text_simple(prompt=person_prompt, prompt_num=gen_prompt_num, language=language)
|
| 366 |
+
memory[user_name]['personality'][date] = person_summary
|
| 367 |
+
|
| 368 |
+
overall_his_prompt = summarize_overall_prompt(list(memory[user_name]['summary'].items()), language=language)
|
| 369 |
+
overall_person_prompt = summarize_overall_personality(list(memory[user_name]['personality'].items()), language=language)
|
| 370 |
+
|
| 371 |
+
memory[user_name]['overall_history'] = llm_client.generate_text_simple(prompt=overall_his_prompt, prompt_num=gen_prompt_num, language=language)
|
| 372 |
+
memory[user_name]['overall_personality'] = llm_client.generate_text_simple(prompt=overall_person_prompt, prompt_num=gen_prompt_num, language=language)
|
| 373 |
+
|
| 374 |
+
with open(memory_dir, 'w', encoding='utf8') as f:
|
| 375 |
+
print(f'Successfully updated memory for {name}')
|
| 376 |
+
json.dump(memory, f, ensure_ascii=False)
|
| 377 |
+
return memory
|
| 378 |
+
|
| 379 |
+
|
| 380 |
+
if __name__ == '__main__':
|
| 381 |
+
summarize_memory('../memories/eng_memory_cases.json', language='en')
|
Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
COPY requirements.txt .
|
| 6 |
+
COPY wheels/ /wheels/
|
| 7 |
+
|
| 8 |
+
RUN pip install \
|
| 9 |
+
--no-cache-dir \
|
| 10 |
+
--no-index \
|
| 11 |
+
--find-links=/wheels \
|
| 12 |
+
-r requirements.txt
|
| 13 |
+
|
| 14 |
+
COPY . .
|
| 15 |
+
|
| 16 |
+
EXPOSE 7860
|
| 17 |
+
|
| 18 |
+
CMD ["python", "app.py"]
|
Emma/.gradio/certificate.pem
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
-----BEGIN CERTIFICATE-----
|
| 2 |
+
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
| 3 |
+
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
| 4 |
+
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
|
| 5 |
+
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
|
| 6 |
+
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
|
| 7 |
+
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
|
| 8 |
+
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
|
| 9 |
+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
|
| 10 |
+
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
|
| 11 |
+
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
|
| 12 |
+
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
|
| 13 |
+
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
|
| 14 |
+
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
|
| 15 |
+
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
|
| 16 |
+
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
|
| 17 |
+
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
|
| 18 |
+
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
|
| 19 |
+
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
|
| 20 |
+
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
|
| 21 |
+
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
|
| 22 |
+
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
|
| 23 |
+
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
|
| 24 |
+
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
|
| 25 |
+
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
|
| 26 |
+
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
|
| 27 |
+
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
|
| 28 |
+
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
|
| 29 |
+
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
|
| 30 |
+
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
|
| 31 |
+
-----END CERTIFICATE-----
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/default__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": [-0.054931640625, -0.02520751953125, 0.037078857421875, -0.0305023193359375, 0.034637451171875, 0.0411376953125, 0.01110076904296875, 0.0251007080078125, 0.046966552734375, 0.0552978515625, 0.033721923828125, -0.0107879638671875, -0.0300750732421875, -0.0250396728515625, 0.01258087158203125, 0.012481689453125, -0.00882720947265625, 0.0281524658203125, -0.042327880859375, 0.052154541015625, 0.024017333984375, -0.0105133056640625, -0.0004830360412597656, -0.0036449432373046875, -0.0379638671875, -0.01457977294921875, 0.003505706787109375, 0.01454925537109375, 0.004550933837890625, -0.01016998291015625, 0.016815185546875, -0.02203369140625, -0.016387939453125, 0.0116424560546875, -0.0156097412109375, 0.0236663818359375, -0.0017337799072265625, -0.02197265625, -0.028076171875, -0.00971221923828125, 0.020294189453125, -0.0253448486328125, -0.00411224365234375, 0.03350830078125, -0.04608154296875, -0.032135009765625, -0.0535888671875, -0.0216217041015625, 0.033843994140625, 0.04034423828125, -0.03643798828125, 0.00566864013671875, -0.00656890869140625, 0.024871826171875, -0.00942230224609375, -0.004886627197265625, -0.0081024169921875, 0.0120849609375, 0.0112152099609375, -0.002902984619140625, 0.02862548828125, -0.006313323974609375, 0.0447998046875, 0.037841796875, 0.007534027099609375, -0.033355712890625, -0.00177001953125, 0.004486083984375, 0.021209716796875, 0.0032138824462890625, 0.02606201171875, 0.03466796875, 0.005649566650390625, 0.00010776519775390625, 0.04705810546875, 0.006740570068359375, -0.002140045166015625, -0.02313232421875, -0.0657958984375, -0.08209228515625, 0.001438140869140625, 0.042144775390625, -0.0283660888671875, -0.007312774658203125, -0.0130767822265625, -0.011566162109375, -0.058624267578125, 0.0013074874877929688, 0.003505706787109375, -0.0044708251953125, -0.0137481689453125, -0.0323486328125, -0.019439697265625, 0.0090179443359375, 0.03912353515625, -0.0297698974609375, 0.01306915283203125, -0.001644134521484375, -0.0273284912109375, 0.0286712646484375, -0.0054779052734375, -0.0267791748046875, -0.0168304443359375, 0.035186767578125, 0.0013751983642578125, 0.0310516357421875, 0.035797119140625, -0.032073974609375, -0.0662841796875, -0.016754150390625, -0.018035888671875, -0.0266876220703125, -0.024200439453125, 0.0141448974609375, -0.047821044921875, -0.0018749237060546875, -0.0675048828125, 0.0014486312866210938, 0.0017156600952148438, -0.010955810546875, -0.061065673828125, 0.01116943359375, -0.0062255859375, 0.0153656005859375, 0.003269195556640625, -0.0147705078125, -0.007770538330078125, -0.03277587890625, -0.037261962890625, -0.0229034423828125, 0.039306640625, 0.0310516357421875, 0.01513671875, -0.062225341796875, -0.0599365234375, -0.03570556640625, -0.0010204315185546875, 0.063232421875, -0.0198516845703125, -0.043243408203125, -0.019287109375, -0.01702880859375, -0.01410675048828125, 0.04656982421875, -0.03118896484375, 0.007114410400390625, 0.0230865478515625, 0.05706787109375, 0.0011510848999023438, -0.00873565673828125, 0.0189361572265625, 0.011444091796875, -0.038177490234375, 0.003955841064453125, 0.013092041015625, -0.016815185546875, -0.0018167495727539062, 0.0193023681640625, 0.01378631591796875, -0.0233306884765625, -0.01220703125, 0.0005774497985839844, -0.0161590576171875, 0.00555419921875, -0.0263671875, 0.03973388671875, 0.023040771484375, -0.01412200927734375, -0.07073974609375, -0.09661865234375, 0.005504608154296875, -0.046966552734375, -0.0202789306640625, -0.0110321044921875, -0.0273590087890625, -0.045989990234375, 0.01287841796875, 0.001583099365234375, -0.014739990234375, 0.00970458984375, -0.0013179779052734375, -0.01436614990234375, -0.07598876953125, 0.029022216796875, -0.0418701171875, -0.058349609375, -0.00270843505859375, -0.008758544921875, 0.02044677734375, -0.0064849853515625, 0.007244110107421875, 0.031829833984375, 0.036590576171875, 0.031890869140625, 0.050933837890625, -0.0679931640625, 0.03326416015625, 0.00800323486328125, -0.003330230712890625, 0.015960693359375, 0.0150146484375, 0.0242156982421875, 0.044097900390625, 0.0229339599609375, 0.00921630859375, -0.01265716552734375, 0.003078460693359375, -0.0157623291015625, -0.06280517578125, 0.007007598876953125, 0.038726806640625, 0.01214599609375, 0.0291290283203125, 0.027313232421875, -0.032470703125, -0.00453948974609375, -0.059600830078125, 0.00556182861328125, 0.00991058349609375, 0.002185821533203125, 0.021453857421875, 0.0181121826171875, 0.038177490234375, -0.0128173828125, 0.003292083740234375, 0.0699462890625, 0.0215606689453125, -0.0272216796875, 0.003932952880859375, -0.005397796630859375, 0.01123809814453125, -0.00635528564453125, -0.02386474609375, 0.0002313852310180664, 0.0285797119140625, -0.017974853515625, 0.055572509765625, -0.0022296905517578125, -0.0076904296875, 0.017730712890625, -0.0010900497436523438, -0.007129669189453125, 0.0147705078125, 0.0638427734375, 0.01482391357421875, -0.00930023193359375, -0.01532745361328125, -0.06341552734375, -0.03338623046875, 0.02398681640625, 0.0055389404296875, 0.015869140625, -0.02362060546875, -0.038238525390625, -0.01412200927734375, -0.06463623046875, -0.0218658447265625, -0.0222625732421875, -0.0224761962890625, -0.04864501953125, 0.0762939453125, -0.0116729736328125, 0.00174713134765625, 0.018890380859375, -0.052001953125, -0.06561279296875, 0.0123138427734375, -0.0017070770263671875, -0.0169830322265625, -0.0496826171875, 0.0087127685546875, 0.003437042236328125, 0.02532958984375, 0.003200531005859375, -0.053619384765625, -0.0181121826171875, 0.0194854736328125, -0.0002827644348144531, -0.02484130859375, -0.0235443115234375, 0.0165252685546875, -0.01568603515625, -0.0235443115234375, 0.038482666015625, -0.01519775390625, 0.0091705322265625, 0.00988006591796875, 0.01526641845703125, 0.0279388427734375, -0.0007257461547851562, 0.006549835205078125, -0.055328369140625, 0.043914794921875, 0.010345458984375, -0.01160430908203125, 0.01032257080078125, 0.029052734375, 0.01172637939453125, 0.0004963874816894531, -0.0023193359375, 0.05224609375, -0.06488037109375, 0.0201416015625, 0.018310546875, 0.044891357421875, 0.0123138427734375, 0.027252197265625, -0.0214996337890625, 0.026458740234375, -0.0246429443359375, -0.00786590576171875, -0.01678466796875, 0.0230865478515625, -0.01031494140625, -0.04852294921875, 0.01512908935546875, 0.054901123046875, 0.01465606689453125, 0.0277252197265625, -0.0374755859375, -0.024505615234375, -0.045867919921875, 0.038909912109375, 0.0165557861328125, 8.994340896606445e-05, 0.011474609375, -0.004909515380859375, 0.0176239013671875, -0.0166015625, -0.0301971435546875, -0.07037353515625, -0.026641845703125, -0.015594482421875, 0.042327880859375, -0.0040435791015625, -0.038787841796875, -0.04840087890625, -0.025177001953125, -0.001430511474609375, 0.024932861328125, -0.056732177734375, -0.045074462890625, -0.03277587890625, -0.05279541015625, -0.0020503997802734375, 0.00447845458984375, -0.0391845703125, -0.0072174072265625, -0.01082611083984375, 0.00972747802734375, 0.0208587646484375, -0.00572967529296875, 0.019683837890625, -0.006412506103515625, -0.038818359375, -0.0164031982421875, 0.013671875, 0.022247314453125, -0.05303955078125, 0.006317138671875, 0.00839996337890625, 0.0019626617431640625, 0.015594482421875, 0.0115814208984375, 0.043487548828125, 0.01128387451171875, -0.08782958984375, -0.048583984375, 0.0006170272827148438, -0.0357666015625, 0.0191497802734375, -0.05804443359375, 0.00897216796875, -0.03253173828125, -0.0261383056640625, 0.018280029296875, -0.013763427734375, 0.030487060546875, -0.0003170967102050781, 0.09124755859375, 0.007648468017578125, -0.0119171142578125, -0.0248260498046875, -0.0233917236328125, 0.02484130859375, 0.023223876953125, -0.04638671875, 0.004497528076171875, -0.052581787109375, -0.00972747802734375, -0.0029315948486328125, -0.0123138427734375, -0.040924072265625, -0.0088348388671875, -0.031982421875, -0.0176849365234375, -0.016632080078125, 0.0174560546875, 0.024993896484375, -0.01214599609375, -0.0286712646484375, 0.00749969482421875, -0.0022068023681640625, -0.0209808349609375, -0.005283355712890625, 0.037445068359375, -0.03594970703125, 0.0068206787109375, 0.03460693359375, -0.00835418701171875, 0.0240936279296875, -0.01806640625, 0.0296783447265625, -0.03521728515625, -0.003940582275390625, -0.020721435546875, 0.01079559326171875, 0.05126953125, 0.034393310546875, 0.044647216796875, 0.00931549072265625, -0.0419921875, -0.0034961700439453125, 0.01128387451171875, -0.006893157958984375, 0.006320953369140625, 0.05279541015625, -0.02142333984375, 0.05975341796875, -0.043365478515625, -0.011688232421875, 0.050567626953125, 0.0306549072265625, -0.01079559326171875, 0.024627685546875, -0.03509521484375, 0.0010538101196289062, 0.03631591796875, -0.03265380859375, -0.003444671630859375, 0.018707275390625, 0.0020427703857421875, -0.03955078125, -0.031524658203125, -0.07269287109375, 0.0151519775390625, -0.024749755859375, -0.052825927734375, 0.039794921875, -0.0133056640625, -0.01271820068359375, -0.060546875, 0.0038204193115234375, 0.0086669921875, -0.054229736328125, -0.04022216796875, -0.0287017822265625, -0.01546478271484375, 0.022247314453125, -0.0250396728515625, -0.034576416015625, -0.0010843276977539062, 0.01148223876953125, 0.0469970703125, 0.047576904296875, -0.00046515464782714844, -0.020843505859375, -0.0247802734375, 0.0059661865234375, 0.03033447265625, 0.01398468017578125, 0.0004336833953857422, 0.0040435791015625, 0.006450653076171875, -0.0216217041015625, 0.031646728515625, -0.0156707763671875, 0.0074005126953125, 0.0126190185546875, -0.01052093505859375, -0.01554107666015625, 0.0206451416015625, -0.0098419189453125, 0.0220184326171875, 0.05084228515625, 0.034515380859375, -0.0208740234375, 0.02996826171875, 0.006175994873046875, 0.0292816162109375, -0.025848388671875, -0.00830078125, 0.016876220703125, -0.018218994140625, -0.007320404052734375, 0.016937255859375, -0.0164337158203125, -0.032470703125, -0.0068206787109375, -0.0435791015625, -0.017913818359375, -0.0015134811401367188, 0.04156494140625, 0.048309326171875, -0.01043701171875, -0.0002624988555908203, -0.040069580078125, -0.00959014892578125, 0.0179443359375, -0.009002685546875, 0.024932861328125, 0.03955078125, -0.01776123046875, -0.0181732177734375, -0.002086639404296875, 0.0255279541015625, 0.004474639892578125, 0.0028934478759765625, -0.0156402587890625, 0.0159912109375, -0.0014085769653320312, -0.0214080810546875, 0.010284423828125, 0.0024566650390625, -0.020721435546875, -0.02606201171875, 0.01708984375, -0.043182373046875, -0.01739501953125, -0.01442718505859375, 0.02679443359375, -0.0019121170043945312, 0.0263214111328125, 0.02398681640625, -0.06805419921875, -0.00699615478515625, 0.006587982177734375, -0.0293121337890625, -0.03656005859375, 0.019134521484375, 0.043182373046875, 0.054534912109375, -0.00209808349609375, 0.023101806640625, 0.007122039794921875, -0.002658843994140625, 0.00438690185546875, 0.0374755859375, -0.01459503173828125, 0.0241241455078125, 0.007049560546875, -0.0261993408203125, 0.04534912109375, 0.01139068603515625, 0.0246429443359375, -0.02496337890625, 0.006320953369140625, -0.04107666015625, -0.0282440185546875, -0.00724029541015625, 0.0215606689453125, -0.04217529296875, 0.055023193359375, 0.018096923828125, -0.01044464111328125, 0.0195159912109375, 0.0129241943359375, 0.02593994140625, -0.01287078857421875, 0.0193328857421875, 0.0123138427734375, -0.001644134521484375, 0.0019178390502929688, -0.01207733154296875, 0.0014820098876953125, -0.003997802734375, -0.004291534423828125, 0.002162933349609375, 0.00946044921875, -0.0244903564453125, -0.037353515625, -0.02581787109375, -0.0135955810546875, 0.0589599609375, -0.03253173828125, 0.032928466796875, 0.0577392578125, -0.0014467239379882812, 0.0141448974609375, 0.00023698806762695312, 0.0369873046875, -0.00977325439453125, 0.0226898193359375, 0.0214691162109375, 0.01027679443359375, 0.023193359375, -0.019805908203125, -0.00830841064453125, -0.024993896484375, 0.016845703125, 0.037109375, -0.0018911361694335938, -0.057464599609375, -0.01361083984375, 0.025787353515625, 0.041015625, -0.002197265625, 0.0305938720703125, -0.01258087158203125, 0.00713348388671875, 0.002681732177734375, 0.01369476318359375, 0.018035888671875, -0.051544189453125, -0.00809478759765625, 0.00429534912109375, 0.0089874267578125, 0.0024280548095703125, 0.04412841796875, -0.04083251953125, -0.00908660888671875, -0.006381988525390625, -0.0361328125, -0.00994110107421875, 0.0291900634765625, 0.03704833984375, -0.00789642333984375, -0.032196044921875, 0.01302337646484375, 0.005519866943359375, -0.01434326171875, -0.0004317760467529297, 0.005405426025390625, -0.0026454925537109375, -0.0131683349609375, 0.0279541015625, 0.0008616447448730469, 0.01450347900390625, -0.0017385482788085938, -0.0200958251953125, 0.0260772705078125, -0.0185394287109375, 0.022979736328125, -0.039031982421875, 0.0211639404296875, -0.0129547119140625, -0.0200958251953125, -0.01419830322265625, -0.0391845703125, -0.007625579833984375, -0.0232391357421875, -0.06561279296875, 0.007282257080078125, -0.0034885406494140625, 0.0262908935546875, -0.0220947265625, 0.033203125, 0.004711151123046875, -0.035491943359375, 0.00875091552734375, -0.0158233642578125, 0.013275146484375, 0.00461578369140625, -0.034393310546875, -0.0200958251953125, 0.037139892578125, -0.0111236572265625, -0.0198516845703125, 0.024383544921875, 0.054473876953125, -0.054931640625, -0.01311492919921875, 0.0149383544921875, 0.01374053955078125, 0.01776123046875, -0.002239227294921875, -0.006763458251953125, -0.017913818359375, -0.01039886474609375, 0.006351470947265625, -0.02398681640625, 0.020599365234375, -0.01557159423828125, -0.0010166168212890625, 0.00670623779296875, -0.01081085205078125, 0.060272216796875, -0.01995849609375, 0.0052337646484375, 0.0248565673828125, 0.005584716796875, 0.0278167724609375, 0.004909515380859375, 0.009613037109375, 0.030731201171875, 0.0179443359375, -0.003520965576171875, 0.01171875, -0.007442474365234375, -0.023101806640625, -0.03924560546875, -0.01383209228515625, -0.0052337646484375, 0.0160369873046875, -0.0223388671875, 0.01390838623046875, 0.0214080810546875, -0.005828857421875, 0.03814697265625, -0.02984619140625, -0.0279998779296875, 0.0117950439453125, -0.01288604736328125, 0.0343017578125, -0.00830841064453125, -0.004638671875, -0.011993408203125, 0.014434814453125, 0.03619384765625, -0.0152130126953125, 0.02984619140625, 0.0220794677734375, -0.02874755859375, 0.038848876953125, -0.0092926025390625, 0.0005102157592773438, -0.016815185546875, 0.02093505859375, -0.0088653564453125, -0.00127410888671875, -0.01116943359375, 0.017730712890625, 0.00998687744140625, -0.03326416015625, 0.0077972412109375, 0.020294189453125, -0.034820556640625, 0.03240966796875, -0.0241546630859375, 0.01214599609375, 0.03515625, -0.042755126953125, 0.006427764892578125, -0.01354217529296875, 0.05230712890625, -0.00923919677734375, 0.0069732666015625, 0.0289764404296875, -0.019561767578125, -0.007534027099609375, -0.0130767822265625, 0.01220703125, -0.00032210350036621094, -0.018707275390625, 0.047637939453125, 0.0009469985961914062, 0.00310516357421875, 0.01035308837890625, 0.00086212158203125, -0.0005550384521484375, 0.0243377685546875, 0.04510498046875, 0.02996826171875, 0.0264892578125, -0.0019330978393554688, -0.00562286376953125, -0.01617431640625, 0.0251007080078125, -0.036834716796875, -0.0019893646240234375, -0.017822265625, 8.052587509155273e-05, -0.005615234375, 0.00659942626953125, 0.061309814453125, 0.00043892860412597656, 0.0221405029296875, 0.0174407958984375, -0.04736328125, 0.033966064453125, 0.032745361328125, 0.01323699951171875, 0.004852294921875, -0.03485107421875, -0.006313323974609375, -0.00125885009765625, -0.020294189453125, -0.0328369140625, -0.0298004150390625, -0.0293121337890625, 0.0018672943115234375, -0.00247955322265625, 0.0310821533203125, -0.0113525390625, -0.00937652587890625, -0.00832366943359375, -0.0231170654296875, -0.1217041015625, 0.030029296875, 0.0361328125, -0.0267486572265625, 0.0240631103515625, -0.0140380859375, 0.006755828857421875, 0.03076171875, -0.020416259765625, -0.03668212890625, 0.01453399658203125, -0.0537109375, -0.004825592041015625, -0.02484130859375, -0.0033512115478515625, -0.031768798828125, 0.005588531494140625, -0.004703521728515625, -0.0291900634765625, 0.0156402587890625, -0.055419921875, 0.0175933837890625, -0.01525115966796875, 0.047515869140625, -0.044952392578125, 0.002223968505859375, -0.0389404296875, 0.0113372802734375, 0.009246826171875, 0.00826263427734375, 0.0228729248046875, -0.029876708984375, -0.0157623291015625, 0.0209808349609375, 0.006237030029296875, -0.002902984619140625, -0.0268096923828125, 0.00919342041015625, 0.001434326171875, -0.005886077880859375, 0.0208740234375, 0.0054473876953125, 0.0386962890625, 0.0187530517578125, 0.0306549072265625, -0.00318145751953125, 0.0192108154296875, 0.026611328125, 0.007160186767578125, -0.021942138671875, -0.02392578125, 0.02008056640625, 0.0104217529296875, -0.042633056640625, 0.0228424072265625, 0.037109375, -0.01641845703125, -0.0201568603515625, 0.03179931640625, -0.0123138427734375, -0.0031223297119140625, -0.0016345977783203125, -0.0096435546875, -0.0097198486328125, -0.01555633544921875, 0.0019664764404296875, -0.00400543212890625, -0.00661468505859375, 0.015838623046875, -0.0163726806640625, -0.0555419921875, -0.0013875961303710938, 0.00856781005859375, -0.0220794677734375, -0.011444091796875, 0.005588531494140625, 0.0294036865234375, 0.0162353515625, -0.0164947509765625, 0.019500732421875, 0.0228424072265625, -0.0183563232421875, 0.03326416015625, 0.0034942626953125, 0.00234222412109375, 0.006916046142578125, 0.0255279541015625, 0.005939483642578125, -0.03973388671875, 0.029510498046875, 0.03369140625, -0.007404327392578125, -0.01898193359375, 0.007640838623046875, -0.0291900634765625, 0.028533935546875, 0.0092926025390625, 0.0227203369140625, 0.02374267578125, 0.0179443359375, -0.01212310791015625, -0.0108184814453125, -0.002346038818359375, -0.007648468017578125, -0.026611328125, -0.00769805908203125, 0.007770538330078125, 0.01155853271484375, 0.0011816024780273438, 0.02508544921875, -0.0167999267578125, 0.040069580078125, 0.012420654296875, 0.01177215576171875, 0.007598876953125, 0.01702880859375, 0.0262603759765625, -0.00652313232421875, 0.0001894235610961914, -0.029876708984375, 0.00726318359375, 0.015960693359375, 0.007411956787109375, 0.030792236328125, -0.01239013671875, 0.04620361328125, 0.022735595703125, -0.01161956787109375, -0.0174560546875, 0.03826904296875, 0.0164794921875, 0.01549530029296875, -0.0239105224609375, 0.01503753662109375, 0.0174407958984375, -0.0025386810302734375, 0.041259765625, -0.01548004150390625, 0.00455474853515625, 0.041168212890625, 0.0176239013671875, 0.0101776123046875, 0.0191802978515625, -0.0017881393432617188, -0.01123809814453125, 0.018096923828125, -0.0374755859375, -0.0073699951171875, -0.0064697265625, 0.0298309326171875, 0.01230621337890625, -0.0311431884765625, 0.004425048828125, 0.0335693359375, 0.0252532958984375, 0.038421630859375, -0.014129638671875, -0.01387786865234375, -0.01812744140625, 0.034942626953125, -0.02520751953125, 0.0341796875, 0.02667236328125, 0.0005617141723632812, 0.044921875, -0.004840850830078125, -0.033935546875, -0.0220489501953125, -0.00640869140625, 0.034088134765625, -0.0362548828125, 0.0174407958984375, 0.0061492919921875, 0.01458740234375, 0.015899658203125, 0.0379638671875, -0.01131439208984375, 0.006542205810546875, -0.00179290771484375, 0.0085296630859375, 0.01146697998046875, 0.02093505859375, 0.0021457672119140625, 0.0177459716796875, 0.0672607421875, 0.01468658447265625, -0.031890869140625, 0.0136260986328125, -0.04779052734375, 0.0026302337646484375, 0.0019102096557617188, 0.04449462890625, 0.05194091796875, 0.06732177734375, -0.009490966796875, -0.027923583984375, 0.00867462158203125, 0.003345489501953125, -0.029510498046875, -0.01165771484375, -0.01531219482421875, 0.031646728515625, 0.02099609375, -0.01568603515625, 0.049530029296875, 0.0262908935546875, -0.032928466796875, 0.01187896728515625, 0.0062713623046875, -9.238719940185547e-06, -0.016815185546875, -0.0018978118896484375, -0.019317626953125, -0.04046630859375, -0.04296875, 0.026824951171875, -0.017120361328125, -0.00214385986328125, 0.0194549560546875, -0.010955810546875, -0.01617431640625, 0.0010461807250976562, -0.00955963134765625, -0.00347137451171875, -0.0132904052734375, 0.0218658447265625, -0.0227508544921875, 0.00012195110321044922, 0.01279449462890625, 0.0077056884765625, 0.024383544921875, -0.02777099609375, -0.0026092529296875, 0.00518798828125, 0.0030803680419921875, 0.006565093994140625, 0.0123138427734375, -0.0185394287109375, 0.0156707763671875, -0.030487060546875, 0.04388427734375, 0.00988006591796875, -0.0008020401000976562, -0.037322998046875, -0.019439697265625, -0.0211944580078125, 0.0019931793212890625, 0.01406097412109375, 0.03717041015625, -0.00634765625, -0.0227813720703125, -0.01506805419921875, 0.022796630859375, -0.03271484375, 0.0189056396484375, 0.01306915283203125, -0.0037250518798828125, 0.0143585205078125, 0.0012950897216796875, 0.0230255126953125, -0.020904541015625, 0.00643157958984375, -0.0168609619140625, -0.040435791015625, -0.0086822509765625, -0.00458526611328125, 0.00226593017578125, -0.01910400390625, 0.0156402587890625, 0.03167724609375, -0.0200653076171875, 0.038482666015625, 0.0156707763671875, -0.001010894775390625, 0.00226593017578125, -0.0160675048828125, -0.005401611328125, -0.020050048828125, 0.03759765625, 0.0189208984375, -0.023223876953125, -0.026641845703125, 0.03863525390625, -0.00939178466796875, 0.0207366943359375, -0.004604339599609375, -0.043182373046875, -0.04156494140625, 0.0026073455810546875, 0.005069732666015625, 0.002468109130859375, -0.0006465911865234375, 0.0242767333984375, 0.0013246536254882812, -0.0384521484375, 0.039886474609375, -0.006633758544921875, 0.0305938720703125, 0.0297698974609375, -0.03045654296875, -0.006866455078125, -0.031158447265625, 0.02008056640625, 0.0022068023681640625, -0.0126495361328125, 0.04388427734375, -0.00724029541015625, -0.01548004150390625, -0.0037822723388671875, -0.0004825592041015625, -0.0222015380859375, -0.01904296875, 0.0048980712890625, 0.0205078125, 0.002590179443359375, 0.0094146728515625, 0.046478271484375, -0.018096923828125, -0.007762908935546875, -0.003841400146484375, -0.01641845703125, 0.017852783203125, 0.007122039794921875, -0.009552001953125, -0.016448974609375, -0.005054473876953125, 0.0200347900390625, -0.026641845703125, -0.00911712646484375, -0.007320404052734375, -0.039947509765625, -0.020599365234375, 0.0007290840148925781, 0.0194854736328125, 0.00876617431640625, 0.038421630859375, 0.007167816162109375, 0.007171630859375, -0.0340576171875, -0.026611328125, -0.0125579833984375, -0.03851318359375, -0.0004596710205078125, -0.00670623779296875, 0.0117950439453125, -0.0301361083984375, -0.01837158203125, 0.019683837890625, 0.019805908203125, 0.0229339599609375, 0.0889892578125, 0.003894805908203125, -0.023193359375, 0.034759521484375, -0.0269775390625, 0.00244903564453125, -0.010528564453125, 0.0013494491577148438, -0.0479736328125, 0.01141357421875, -0.0226593017578125, 0.036773681640625, 0.022491455078125, 0.029937744140625, 0.0013170242309570312, 0.039703369140625, -0.0226593017578125, 0.032318115234375, 0.01236724853515625, -0.0050201416015625, 0.0130462646484375, 0.0092620849609375, 0.037750244140625, -0.02874755859375, -0.00965118408203125, 0.009246826171875, 0.04437255859375, -0.01319122314453125, -0.0023288726806640625, 0.0015544891357421875, 0.006256103515625, -0.05596923828125, 0.00444793701171875, 0.01346588134765625, -0.0163726806640625, 0.01898193359375, -0.00807952880859375, 0.035552978515625, -0.0055084228515625, 0.016021728515625, 0.030853271484375, -0.006847381591796875, 0.0298004150390625, -0.0180206298828125, 0.0024700164794921875, 0.0175628662109375, -0.015594482421875, 0.0145111083984375, -0.00841522216796875, 0.01450347900390625, 0.0009632110595703125, 0.0280609130859375, -0.0400390625, -0.0222625732421875, -0.0361328125, 0.005054473876953125, -0.000438690185546875, 0.03033447265625, 0.0282440185546875, 0.0084075927734375, -0.027374267578125, 0.01467132568359375, -0.00655364990234375, 0.03228759765625, 0.031829833984375, -0.048736572265625, -0.0032367706298828125, -0.00531768798828125, -0.023468017578125, 0.01317596435546875, 0.02252197265625, 0.01544189453125, -0.0088958740234375, -0.010498046875, 0.00019824504852294922, 0.0309600830078125, 0.0161590576171875, 0.0203399658203125, 0.037872314453125, -0.00226593017578125, 0.0159454345703125, -0.002368927001953125, -0.01079559326171875, -0.02008056640625, 0.0036487579345703125, -0.00968170166015625, -0.0003581047058105469, 0.039459228515625, -0.0180816650390625, 0.007720947265625, -0.00916290283203125, 0.00469207763671875, 0.01071929931640625, 0.0292510986328125, 0.0095672607421875, 0.01287841796875, -0.0232391357421875, -0.0013170242309570312, 0.0258026123046875, -0.0199432373046875, 0.041290283203125, 0.002376556396484375, -0.04132080078125, 0.0032939910888671875, -0.00467681884765625, -0.0164337158203125, -0.0262451171875, -0.001743316650390625, -0.056640625, -0.022247314453125, 0.00786590576171875, 0.0318603515625, 0.017852783203125, -0.00933074951171875, -0.004825592041015625, -0.015411376953125, -0.024383544921875, -0.026611328125, -0.0113677978515625, -0.046875, 0.0416259765625, -0.005565643310546875, -0.0033817291259765625, -0.0218963623046875, -0.0014104843139648438, 0.005580902099609375, 0.0132598876953125, -0.0112457275390625, -0.0268096923828125, -0.002349853515625, -0.01174163818359375, 0.0201568603515625, 0.016082763671875, -0.0269012451171875, 0.02288818359375, 0.00519561767578125, 0.005401611328125, -0.043853759765625, -0.0175323486328125, 0.0024662017822265625, -0.00428009033203125, 0.0172576904296875, -0.0174560546875, -0.030059814453125, 0.0283050537109375, -0.0023059844970703125, 0.00604248046875, -0.0287322998046875, 0.032470703125, 0.0340576171875, -0.0025653839111328125, -0.038421630859375, 0.02655029296875, 0.042572021484375, 0.01052093505859375, -0.005970001220703125, 0.0198974609375, -0.053131103515625, 0.0037593841552734375, -0.00858306884765625, 0.0012407302856445312, 0.0085296630859375, -0.034149169921875, -0.011749267578125, 0.0243377685546875, 0.01104736328125, -0.0015096664428710938, 0.01076507568359375, 0.0034465789794921875, 0.016510009765625, 0.00899505615234375, -0.0256500244140625, 0.023284912109375, 0.031494140625, 0.052490234375, -0.00299072265625, 0.0168304443359375, 0.0002148151397705078, -0.03076171875, 0.0002372264862060547, -0.00557708740234375, -0.0316162109375, -0.0038166046142578125, -0.0035953521728515625, 0.014495849609375, -0.0018768310546875, 0.0293121337890625, -0.0074005126953125, 0.0144195556640625, -0.0181121826171875, -0.020477294921875, -0.00804901123046875, 0.006809234619140625, -0.015594482421875, 0.0269317626953125, 0.04052734375, -0.0032138824462890625, 0.01983642578125, -0.0293121337890625, 0.024261474609375, -0.00284576416015625, -0.04925537109375, -0.06500244140625, 0.0245361328125, 0.01079559326171875, 0.0479736328125, -0.03155517578125, -0.036102294921875, 0.0026721954345703125, 0.013427734375, 0.002651214599609375, 0.0107879638671875, 0.007598876953125, -0.01178741455078125, 0.0101776123046875, 0.007152557373046875, -0.0249786376953125, 0.0277099609375, -0.0190887451171875, -0.01364898681640625, 0.004566192626953125, -0.004619598388671875, 0.0089569091796875, -0.0479736328125, 0.01456451416015625, 0.00484466552734375, 0.032806396484375, 0.006717681884765625, 0.0188751220703125, -0.0343017578125, 0.058746337890625, -0.0159759521484375, -0.0169219970703125, -0.03326416015625, 0.0210723876953125, 0.011016845703125, -0.03369140625, 0.0003204345703125, -0.003993988037109375, -0.0273284912109375, 0.01103973388671875, -0.006931304931640625, -0.00217437744140625, 0.009735107421875, 0.0042266845703125, 0.0228729248046875, -0.0013265609741210938, -0.0101165771484375, -0.0213623046875, 0.00923919677734375, -0.0176849365234375, 0.0338134765625, 0.01459503173828125, -0.01071929931640625, -0.035980224609375, 0.01251220703125, -0.0108184814453125, 0.0013952255249023438, -0.0222015380859375, -0.0390625, -0.0236358642578125, -0.0111083984375, -0.00807952880859375, -0.002101898193359375, 0.0289154052734375, 0.01442718505859375, -0.021728515625, -0.012786865234375, -0.043609619140625, 0.0216827392578125, -0.02899169921875, 0.029449462890625, -0.02532958984375, -0.03369140625, -0.014129638671875, 0.01160430908203125, 0.00330352783203125, 0.005031585693359375, 0.0030727386474609375, -0.004428863525390625, -0.0355224609375, 0.036865234375, -0.018463134765625, 0.0009975433349609375, 0.005962371826171875, -0.0116729736328125, -0.0164642333984375, 0.005481719970703125, 0.06842041015625, -0.01390838623046875, 0.0247650146484375, 0.0306549072265625, -0.0235748291015625, -0.01165008544921875, 0.0252532958984375, 0.017974853515625, -0.0030384063720703125, -0.01372528076171875, 0.0016460418701171875, 0.03515625, -0.00933837890625, -0.0272369384765625, 0.00634002685546875, -0.0162811279296875, 0.011016845703125, -0.006999969482421875, 0.0084686279296875, 0.0083160400390625, -0.017578125, -0.0009016990661621094, -0.006259918212890625, 0.01007080078125, 0.0008511543273925781, 0.0029315948486328125, 0.018585205078125, -0.00858306884765625, 0.005641937255859375, 0.0010890960693359375, -0.003620147705078125, 0.0014934539794921875, 0.0106201171875, -0.00811767578125, 0.03424072265625, 0.00383758544921875, 0.01275634765625, 0.010101318359375, 0.0036296844482421875, 0.00637054443359375, -0.005092620849609375, -0.0019702911376953125, 0.041015625, -0.0193328857421875, -0.01491546630859375, -0.002170562744140625, 0.0167236328125, 0.0161895751953125, 0.0086669921875, 0.004405975341796875, 0.004619598388671875, -0.0034942626953125, -0.027435302734375, -0.0194244384765625, 0.024688720703125, -0.0117645263671875, -0.01027679443359375, 0.035308837890625, 0.043975830078125, -0.0218048095703125, -0.0027790069580078125, 0.0235443115234375, -0.004062652587890625, 0.0255126953125, -0.0097198486328125, 0.0010595321655273438, 0.0031871795654296875, 0.01111602783203125, 0.019805908203125, 0.02685546875, -0.0134124755859375, 0.022735595703125, -0.02545166015625, -0.021820068359375, 0.0236968994140625, 0.006500244140625, -0.0268402099609375, -0.007404327392578125, 0.02032470703125, -0.0221710205078125, -0.011810302734375, 0.030914306640625, 0.00800323486328125, -0.0007004737854003906, -0.0013952255249023438, -0.0200347900390625, 0.002346038818359375, -0.0092620849609375, -0.0104217529296875, -0.00467681884765625, -0.009765625, -0.0294189453125, 0.0338134765625, -0.0399169921875, 0.0289154052734375, 0.01226806640625, 0.0017671585083007812, -0.038665771484375, 0.0006999969482421875, 0.0064849853515625, -0.0179595947265625], "5692100e-6f1f-48eb-95e5-e02bb96eecb3": [-0.0308685302734375, -0.034637451171875, 0.007659912109375, 0.0012655258178710938, 0.00787353515625, 0.01068115234375, 0.003086090087890625, 0.048187255859375, 0.0289459228515625, 0.05548095703125, 0.02923583984375, -0.025848388671875, -0.0187225341796875, -0.042327880859375, -0.005161285400390625, 0.034088134765625, -0.008941650390625, 0.04534912109375, -0.03094482421875, 0.0242156982421875, 0.047027587890625, 0.0275726318359375, -0.0181427001953125, 0.007293701171875, -0.0208892822265625, 0.0090484619140625, 0.0011243820190429688, 0.005584716796875, -0.0124664306640625, -0.0159912109375, -0.004913330078125, -0.022247314453125, 0.012176513671875, 0.00836944580078125, -0.0153350830078125, 0.038238525390625, -0.01364898681640625, -0.00948333740234375, -0.00433349609375, -0.01065826416015625, 0.01453399658203125, -0.033477783203125, 0.0097503662109375, 0.0293731689453125, -0.022705078125, 0.002841949462890625, -0.038055419921875, -0.0018558502197265625, 0.0413818359375, 0.00555419921875, -0.0433349609375, 0.022979736328125, 0.0212249755859375, 0.0204620361328125, 0.0273895263671875, -0.0120086669921875, 0.00046539306640625, 0.0282135009765625, -0.0242156982421875, 0.03515625, 0.0655517578125, -0.0272216796875, 0.011566162109375, 0.01235198974609375, 0.00807952880859375, -0.034698486328125, 0.006977081298828125, -0.00669097900390625, 0.01959228515625, 0.0057830810546875, 0.062225341796875, 0.0272674560546875, -0.0013208389282226562, -0.01354217529296875, 0.007843017578125, -0.00897216796875, 0.030731201171875, -0.009063720703125, -0.041473388671875, -0.0794677734375, 0.0176544189453125, 0.03131103515625, -0.0287628173828125, -0.00539398193359375, -0.03466796875, -0.039337158203125, -0.07171630859375, 0.003200531005859375, -0.0157470703125, -0.024078369140625, -0.032684326171875, -0.024078369140625, -0.03704833984375, 0.0201568603515625, 0.04888916015625, -0.0273895263671875, 0.0234832763671875, 0.028900146484375, -0.01220703125, -0.01000213623046875, -0.024261474609375, -0.0199432373046875, -0.060791015625, 0.0014801025390625, 0.006099700927734375, 0.01438140869140625, 0.035125732421875, -0.02716064453125, -0.058013916015625, 0.02154541015625, -0.0548095703125, 0.027435302734375, -0.001232147216796875, 0.047943115234375, -0.05657958984375, -0.023895263671875, -0.0614013671875, -0.01142120361328125, -0.01448822021484375, 0.01149749755859375, -0.04241943359375, 0.006824493408203125, -0.02001953125, 0.032623291015625, -0.0086212158203125, -0.02008056640625, 0.01300048828125, -0.008819580078125, -0.044677734375, -0.021087646484375, 0.03765869140625, -0.0052642822265625, 0.0227203369140625, -0.04083251953125, -0.050506591796875, -0.04595947265625, -0.0028171539306640625, 0.042327880859375, -0.0163116455078125, -0.0015697479248046875, 0.016326904296875, -0.01366424560546875, -0.01528167724609375, 0.036224365234375, -0.0231170654296875, -0.01421356201171875, -0.006763458251953125, 0.052642822265625, -0.051544189453125, 0.0236358642578125, 0.04986572265625, 0.031341552734375, -0.033447265625, 0.01250457763671875, 0.0037708282470703125, -0.001617431640625, 0.0128173828125, 0.0035800933837890625, -0.00286102294921875, -0.032989501953125, -0.006298065185546875, -0.046783447265625, 0.0018444061279296875, -0.022979736328125, 0.036895751953125, 0.042449951171875, 0.01276397705078125, -0.00677490234375, -0.0287322998046875, -0.0770263671875, -0.0294189453125, -0.04132080078125, -0.025634765625, 0.04901123046875, -0.0352783203125, -0.0452880859375, 0.0408935546875, -0.0124664306640625, -0.01131439208984375, 0.0270233154296875, -0.0169525146484375, 0.01544189453125, -0.03875732421875, 0.0003695487976074219, -0.042144775390625, -0.0435791015625, -0.01195526123046875, -0.03387451171875, 0.041473388671875, -0.0010852813720703125, 0.0161895751953125, 0.028350830078125, 0.0232086181640625, -0.0016603469848632812, 0.047271728515625, -0.056976318359375, 0.042144775390625, -0.00734710693359375, -0.046356201171875, 0.0523681640625, -0.002193450927734375, -0.0031528472900390625, 0.03277587890625, -0.0016326904296875, 0.03704833984375, -0.059356689453125, 0.0253448486328125, 0.006378173828125, -0.04302978515625, 0.0543212890625, 0.0287933349609375, 0.004638671875, 0.053680419921875, 0.020355224609375, -0.022125244140625, 0.050079345703125, -0.033905029296875, 0.001697540283203125, 0.003086090087890625, 0.0265045166015625, -0.007122039794921875, 0.0233306884765625, 0.07537841796875, -0.027618408203125, 0.00548553466796875, 0.0213775634765625, 0.05047607421875, 0.0012865066528320312, 0.0059967041015625, -0.04986572265625, 0.0102081298828125, -0.026123046875, -0.0020656585693359375, -0.0265655517578125, 0.0299835205078125, -0.030029296875, 0.052825927734375, 0.0033740997314453125, -0.00244903564453125, 0.007709503173828125, 0.001491546630859375, 0.00994110107421875, 0.027557373046875, 0.066650390625, 0.046295166015625, 0.020843505859375, -0.03741455078125, -0.0947265625, 0.002460479736328125, 0.01708984375, 0.03448486328125, 0.0040130615234375, 0.05389404296875, -0.01800537109375, -0.0254364013671875, -0.04119873046875, 0.007541656494140625, -0.044891357421875, -0.01303863525390625, -0.0201568603515625, 0.04541015625, -0.0245513916015625, 0.036590576171875, 0.019775390625, -0.03369140625, -0.054595947265625, -0.004924774169921875, 0.018310546875, -0.01335906982421875, -0.04974365234375, -0.0216522216796875, -0.009979248046875, 0.0157012939453125, 0.0279083251953125, -0.054901123046875, -0.01081085205078125, 0.009613037109375, 0.053619384765625, -0.0255126953125, 0.027435302734375, 0.00853729248046875, 0.03460693359375, -0.00815582275390625, 0.0293426513671875, 0.021148681640625, 0.03680419921875, 0.00720977783203125, -0.01329803466796875, -0.016387939453125, 0.004489898681640625, -0.003032684326171875, -0.0236663818359375, 0.0278778076171875, 0.0361328125, -0.01139068603515625, -0.017852783203125, 0.0203094482421875, 0.001415252685546875, -0.00151824951171875, -0.01132965087890625, 0.049041748046875, -0.027801513671875, -0.0178375244140625, 0.038482666015625, 0.024169921875, 0.0123443603515625, 0.049163818359375, 0.0219268798828125, 0.030731201171875, -0.051177978515625, 0.0003409385681152344, 0.0283660888671875, 0.04193115234375, 0.0102691650390625, -0.06732177734375, 0.0231170654296875, 0.0543212890625, 0.033935546875, 0.023590087890625, -0.034393310546875, -0.04852294921875, -0.01221466064453125, 0.040863037109375, -0.0172576904296875, -0.01030731201171875, -0.01361083984375, 0.032684326171875, 0.020904541015625, -0.0152130126953125, -0.0210113525390625, -0.03228759765625, -0.042724609375, -0.014617919921875, 0.0298614501953125, 0.0465087890625, -0.03948974609375, -0.0154571533203125, -0.0240478515625, -0.010101318359375, 0.0010461807250976562, -0.037628173828125, -0.040313720703125, -0.060455322265625, -0.01184844970703125, 0.015350341796875, 0.01462554931640625, -0.0079803466796875, -0.0096435546875, 0.0015668869018554688, 0.0228424072265625, 0.03033447265625, 0.033172607421875, -0.0017976760864257812, -0.00635528564453125, -0.034912109375, -0.03277587890625, 0.0012969970703125, 0.005153656005859375, -0.024993896484375, 0.003875732421875, 0.0016736984252929688, -0.0245361328125, 0.0111541748046875, 0.01149749755859375, 0.0550537109375, -0.016632080078125, -0.05078125, -0.040985107421875, -0.01081085205078125, -0.06591796875, 0.017059326171875, -0.0455322265625, 0.041717529296875, -0.043121337890625, -0.0340576171875, 0.0244903564453125, -0.0106964111328125, 0.022705078125, 0.005596160888671875, 0.08660888671875, 0.056671142578125, -0.032867431640625, -0.048919677734375, -0.040069580078125, 0.0020694732666015625, 0.0293731689453125, -0.0112762451171875, -0.037933349609375, -0.00391387939453125, -0.021331787109375, 0.0188751220703125, -0.0252532958984375, -0.05242919921875, -0.03765869140625, -0.00995635986328125, 0.0158843994140625, -0.02752685546875, 0.049102783203125, 0.0232086181640625, -0.0533447265625, -0.01187896728515625, 0.050506591796875, -0.0115814208984375, 0.01467132568359375, -0.013641357421875, 0.0110015869140625, -0.034210205078125, 0.008270263671875, 0.0119476318359375, 0.001590728759765625, 0.05401611328125, -0.061614990234375, 0.0163421630859375, -0.0050811767578125, 0.0093536376953125, -0.029998779296875, 0.059234619140625, -0.0088348388671875, 0.0458984375, 0.036102294921875, 0.0207977294921875, -0.033843994140625, -0.0038604736328125, 0.034088134765625, -0.0200042724609375, 0.044158935546875, 0.0264892578125, -0.0200042724609375, 0.058563232421875, -0.056915283203125, 0.01224517822265625, 0.01555633544921875, 0.0094146728515625, -0.0196685791015625, 0.004497528076171875, -0.01464080810546875, 0.002307891845703125, 0.0634765625, -0.048553466796875, -0.031280517578125, -0.0031032562255859375, -0.007762908935546875, -0.056396484375, -0.0180816650390625, -0.047119140625, 0.04437255859375, -0.0301666259765625, -0.0462646484375, 0.005359649658203125, -0.0229949951171875, 0.00860595703125, -0.027496337890625, 0.00832366943359375, 0.019439697265625, -0.044158935546875, -0.050689697265625, -0.0003840923309326172, -0.0099945068359375, 0.02587890625, -0.03240966796875, -0.019073486328125, 0.0027256011962890625, -0.026580810546875, 0.044586181640625, 0.01904296875, -0.0101776123046875, -0.01526641845703125, -0.0230712890625, -0.013092041015625, 0.040679931640625, 0.0119171142578125, 0.0120086669921875, 0.02001953125, 0.01320648193359375, -0.052520751953125, 0.0157623291015625, -0.014404296875, -0.0269927978515625, -0.0147705078125, 0.011016845703125, 0.0310821533203125, 0.0355224609375, 0.01364898681640625, 0.034332275390625, 0.05841064453125, 0.006633758544921875, 0.0094146728515625, -0.0014591217041015625, 0.03729248046875, 0.014617919921875, 0.00765228271484375, -0.00431060791015625, 0.0516357421875, -0.0160369873046875, 0.0162506103515625, 0.031494140625, 0.004638671875, -0.01241302490234375, 0.01186370849609375, -0.0455322265625, -0.004390716552734375, 0.0280609130859375, 0.011749267578125, 0.059661865234375, 0.01187896728515625, -0.0179443359375, -0.052642822265625, 0.00012362003326416016, 0.002399444580078125, -0.00878143310546875, -0.01084136962890625, -0.021881103515625, -0.0282135009765625, 0.005153656005859375, 0.01015472412109375, 0.0204010009765625, 0.01158905029296875, 0.007274627685546875, -0.023284912109375, -0.00537872314453125, -0.0159912109375, -0.007404327392578125, 0.014068603515625, 0.0029773712158203125, -0.038909912109375, -0.0127410888671875, 0.0034084320068359375, -0.0047607421875, -0.006763458251953125, -0.0181427001953125, 0.0189361572265625, -0.0178985595703125, 0.0202178955078125, 0.02374267578125, -0.062286376953125, 0.0234375, -0.0052642822265625, -0.03265380859375, -0.01244354248046875, 0.006072998046875, 0.02581787109375, 0.037384033203125, 0.02288818359375, 0.0185546875, -0.0003085136413574219, 0.00794219970703125, 0.01215362548828125, 0.02496337890625, -0.042510986328125, 0.008331298828125, -0.00023829936981201172, -0.034271240234375, 0.040618896484375, -0.0218963623046875, 0.004856109619140625, 0.00882720947265625, -0.00806427001953125, -0.03985595703125, -0.0005011558532714844, 0.0068206787109375, -0.0169525146484375, -0.04425048828125, 0.057525634765625, 0.03363037109375, -0.046295166015625, 0.02337646484375, 0.0074310302734375, 0.03167724609375, -0.03143310546875, 0.03009033203125, -0.020294189453125, -0.01239013671875, -0.01111602783203125, -0.028839111328125, 0.03131103515625, -0.02325439453125, 0.00787353515625, 0.00890350341796875, 0.0031604766845703125, -0.015716552734375, -0.01494598388671875, -0.0270843505859375, -0.0062713623046875, 0.04638671875, -0.0301971435546875, 0.005649566650390625, 0.0556640625, -0.0206298828125, 0.0110626220703125, 0.0008006095886230469, 0.016265869140625, -0.017730712890625, 0.017730712890625, 0.038177490234375, 0.0228424072265625, 0.00457000732421875, -0.0310211181640625, -0.0201416015625, -0.028045654296875, 0.00785064697265625, 0.0273895263671875, -0.01206207275390625, -0.08062744140625, -0.0207366943359375, 0.0179443359375, 0.0018339157104492188, -0.0030345916748046875, 0.0008177757263183594, -0.0027065277099609375, 0.02081298828125, -0.007720947265625, 0.03411865234375, -0.004558563232421875, -0.07183837890625, -0.035308837890625, -0.01030731201171875, 0.02447509765625, -0.0181884765625, 0.056182861328125, -0.0244598388671875, 0.0004050731658935547, 2.7418136596679688e-05, -0.022247314453125, -0.0008873939514160156, 0.0160369873046875, 0.036529541015625, -0.021881103515625, -0.00969696044921875, -0.007389068603515625, -0.00936126708984375, 0.01317596435546875, 0.0032253265380859375, -0.004909515380859375, -0.044708251953125, -0.03363037109375, 0.0132904052734375, -0.0236053466796875, 0.00969696044921875, -0.031646728515625, -0.0222625732421875, 0.034698486328125, -0.0173187255859375, 0.0204010009765625, -0.04510498046875, 0.0217132568359375, -0.003673553466796875, -0.05206298828125, -0.01551055908203125, -0.028350830078125, 0.0117950439453125, -0.0025634765625, -0.028350830078125, 0.0081787109375, -0.0128021240234375, 0.036468505859375, -0.01715087890625, 0.0151824951171875, -0.00536346435546875, -0.0252227783203125, 0.008697509765625, -0.03851318359375, 0.0205078125, -0.0011911392211914062, -0.005611419677734375, 0.00795745849609375, 0.0462646484375, -0.000583648681640625, -0.0156402587890625, 0.033294677734375, 0.03216552734375, -0.06634521484375, -0.038543701171875, 0.020233154296875, 0.00458526611328125, 0.011627197265625, -0.005832672119140625, -0.02105712890625, -0.0253753662109375, 0.0005822181701660156, 0.0009107589721679688, -0.0012712478637695312, 0.0021800994873046875, -0.0230560302734375, 0.00457763671875, 0.005519866943359375, 0.0188751220703125, 0.031463623046875, -0.02532958984375, 0.0191802978515625, 0.00392913818359375, -0.005535125732421875, 0.021240234375, -0.0308074951171875, 0.041717529296875, 0.00844573974609375, 0.041168212890625, -0.01377105712890625, 0.038543701171875, 0.02069091796875, -0.005992889404296875, -0.027862548828125, 0.0082855224609375, -0.01715087890625, 0.003749847412109375, -0.00928497314453125, -0.006046295166015625, -0.00904083251953125, 0.01250457763671875, 0.0291748046875, 0.0008344650268554688, -0.040435791015625, -0.0002567768096923828, -0.01369476318359375, 0.0595703125, -0.00626373291015625, -0.0018186569213867188, 0.0095977783203125, 0.01263427734375, 0.042022705078125, -0.0400390625, -0.0015506744384765625, 0.013580322265625, -0.005451202392578125, 0.0019083023071289062, -0.01296234130859375, -0.01386260986328125, -0.0030975341796875, 0.0192718505859375, 0.00525665283203125, 0.0022602081298828125, 0.0055999755859375, 0.05224609375, 0.00621795654296875, -0.026641845703125, -0.005435943603515625, 0.0226898193359375, -0.028106689453125, 0.0299835205078125, -0.034698486328125, -0.02783203125, 0.01995849609375, -0.03851318359375, 0.0012798309326171875, -0.0155029296875, 0.04400634765625, -0.0246429443359375, -0.0045166015625, 0.043426513671875, -0.02069091796875, 0.0157928466796875, -0.00518798828125, 0.0128326416015625, -0.00031948089599609375, -0.0093231201171875, 0.0302886962890625, 0.033447265625, -0.02410888671875, 0.0095062255859375, -0.0157318115234375, -0.00799560546875, 0.03363037109375, 0.0310211181640625, -0.004077911376953125, 0.039154052734375, -0.005077362060546875, 0.01076507568359375, 0.009674072265625, 0.020294189453125, -0.01155853271484375, -0.00592041015625, -0.009521484375, -0.03521728515625, -0.0159912109375, 0.0192718505859375, 0.0516357421875, -0.01885986328125, 0.01568603515625, 0.01508331298828125, -0.031982421875, -0.00986480712890625, 0.0169525146484375, 0.00015926361083984375, 0.0214691162109375, -0.0267486572265625, 0.01499176025390625, 0.004589080810546875, 0.01235198974609375, -0.04241943359375, -0.030029296875, -0.038482666015625, -0.01131439208984375, 0.0220947265625, 0.017791748046875, -0.030364990234375, -0.020050048828125, 0.01407623291015625, -0.0171966552734375, -0.0791015625, 0.01149749755859375, 0.034393310546875, -0.0243377685546875, 0.0157623291015625, -0.022705078125, -0.00836181640625, 0.00556182861328125, 0.0030059814453125, -0.0283050537109375, 0.01366424560546875, -0.010894775390625, -0.007293701171875, -0.018798828125, -0.012237548828125, -0.051971435546875, 0.007541656494140625, -0.00316619873046875, 0.0033206939697265625, 0.00012969970703125, -0.035736083984375, 0.0242919921875, -0.0222930908203125, 0.05908203125, -0.0207672119140625, -0.00202178955078125, -0.03863525390625, 0.00485992431640625, 0.01568603515625, 0.0033016204833984375, -0.00830841064453125, 0.0195159912109375, -0.00463104248046875, 0.0157012939453125, 0.010467529296875, -0.01317596435546875, -0.0117950439453125, 0.006473541259765625, -0.00687408447265625, 0.006557464599609375, 0.05010986328125, 0.024932861328125, 0.056854248046875, 0.0201568603515625, 0.03277587890625, -0.0153045654296875, 0.0146942138671875, 0.03466796875, 0.0233917236328125, -0.007236480712890625, -0.033050537109375, 0.0106048583984375, 0.0206146240234375, -0.053802490234375, -0.01385498046875, 0.0391845703125, -0.01506805419921875, -0.043731689453125, 0.00931549072265625, 0.01739501953125, -0.01232147216796875, -0.0173797607421875, -0.0134429931640625, 0.0090484619140625, 0.0034313201904296875, 0.0013332366943359375, -0.0013561248779296875, -0.003360748291015625, -0.00835418701171875, 0.0021114349365234375, -0.042724609375, 0.00841522216796875, -0.0017747879028320312, -0.0250091552734375, -0.011627197265625, 0.022216796875, 0.01509857177734375, 0.022735595703125, -0.0005631446838378906, 0.00849151611328125, 0.017333984375, -0.01116180419921875, 0.040924072265625, 0.0186309814453125, 0.00669097900390625, 0.01971435546875, 0.02191162109375, 0.00498199462890625, -0.027557373046875, 0.01059722900390625, 0.02667236328125, -0.0237884521484375, -0.0127105712890625, 0.0131988525390625, -0.00974273681640625, 0.033447265625, 0.005321502685546875, 0.018798828125, 0.05133056640625, -0.00029468536376953125, 0.00025463104248046875, 0.0025482177734375, -0.024322509765625, -0.0254364013671875, -0.0022907257080078125, -0.0198974609375, -0.00556182861328125, 0.00884246826171875, -0.01073455810546875, 0.005008697509765625, -0.0194244384765625, 0.007598876953125, 0.0167236328125, 0.01023101806640625, -0.00649261474609375, -0.01351165771484375, 0.04876708984375, 0.0015048980712890625, -0.02288818359375, -0.0202178955078125, 0.0148468017578125, 0.052154541015625, 0.00333404541015625, 0.0293731689453125, 0.00928497314453125, 0.0296478271484375, 0.0278472900390625, -0.013031005859375, -0.0236053466796875, -0.005382537841796875, 0.017791748046875, 0.0012683868408203125, -0.0196075439453125, -0.02606201171875, 0.0215301513671875, 0.0140228271484375, 0.0166168212890625, 0.00121307373046875, 0.00853729248046875, 0.0308685302734375, 0.00597381591796875, 0.0160675048828125, 0.017303466796875, -0.038299560546875, -0.004192352294921875, 0.0097808837890625, 0.00675201416015625, -0.0238189697265625, 0.01099395751953125, 0.00353240966796875, 0.01036834716796875, -0.018768310546875, -0.007965087890625, 0.048858642578125, 0.03668212890625, 0.04229736328125, 0.0016641616821289062, 0.0041656494140625, -0.053375244140625, 0.003681182861328125, -0.0208740234375, 0.00905609130859375, 0.0362548828125, 0.0008144378662109375, -0.002674102783203125, 0.0025730133056640625, -0.060882568359375, 0.0008025169372558594, -0.0027751922607421875, 0.032623291015625, -0.007785797119140625, 0.00844573974609375, 0.01229095458984375, -0.006084442138671875, 0.01363372802734375, 0.05487060546875, -0.010986328125, 0.005523681640625, 0.00493621826171875, 0.0083160400390625, 0.00897979736328125, 0.025054931640625, 0.0217742919921875, 0.00907135009765625, 0.056671142578125, -0.0017108917236328125, 0.00016033649444580078, -0.0235137939453125, -0.052947998046875, -0.0263824462890625, 0.0175323486328125, 0.005290985107421875, 0.0213623046875, 0.06243896484375, -0.024810791015625, -0.031494140625, 0.0172882080078125, 0.0017194747924804688, -0.044158935546875, -0.0032863616943359375, -0.008514404296875, 0.0252532958984375, 0.01558685302734375, -0.0103302001953125, 0.0214691162109375, 0.0239105224609375, -0.047393798828125, -0.006656646728515625, -0.026336669921875, -0.019195556640625, -0.033172607421875, -0.0027713775634765625, -0.0230712890625, -0.040496826171875, -0.0268707275390625, 0.00457000732421875, 0.025054931640625, -0.002445220947265625, -0.0163421630859375, -0.0193634033203125, 0.018768310546875, 0.0094146728515625, -0.0208740234375, 0.0528564453125, -0.019683837890625, 0.031494140625, -0.0287322998046875, -0.0028018951416015625, 0.00449371337890625, 0.016082763671875, 0.02301025390625, -0.0051727294921875, 0.0196075439453125, -0.005771636962890625, 0.025115966796875, -0.01181793212890625, 0.0005049705505371094, -0.03582763671875, 0.0033111572265625, 0.001819610595703125, 0.041656494140625, 0.0156097412109375, -0.0026721954345703125, -0.053619384765625, 0.00011795759201049805, -0.038116455078125, -0.00139617919921875, 0.0193328857421875, 0.020599365234375, -0.0017786026000976562, -0.022003173828125, -0.01551055908203125, 0.01439666748046875, -0.035614013671875, -0.019256591796875, 0.0093536376953125, 0.0227813720703125, 0.0158233642578125, -0.00399017333984375, -0.009368896484375, -0.01959228515625, -0.0010137557983398438, 0.00998687744140625, -0.06396484375, 0.0014276504516601562, 0.004604339599609375, -0.0084381103515625, -0.01373291015625, 0.03399658203125, 0.02947998046875, -0.0380859375, 0.017303466796875, 0.0033817291259765625, 0.005527496337890625, 0.03546142578125, -0.024871826171875, -0.00505828857421875, -0.03533935546875, 0.033447265625, 0.043060302734375, -0.026123046875, -0.00437164306640625, 0.03070068359375, -0.0092315673828125, 0.031890869140625, -0.006591796875, -0.0557861328125, -0.0280303955078125, 0.007904052734375, 0.01328277587890625, 0.01016998291015625, -0.002651214599609375, 0.007335662841796875, -0.0008420944213867188, -0.0117950439453125, 0.00750732421875, -0.01055145263671875, 0.0273590087890625, 0.034912109375, -0.035247802734375, -0.014251708984375, -0.01369476318359375, 0.02142333984375, 0.0296783447265625, 0.004169464111328125, 0.032928466796875, 0.001483917236328125, -0.0180816650390625, -0.007457733154296875, -0.0093231201171875, -0.011199951171875, -0.01020050048828125, 0.032440185546875, 0.018951416015625, 0.0002779960632324219, 0.0214080810546875, 0.0201568603515625, -0.0172119140625, 0.007244110107421875, 0.00557708740234375, 0.0002484321594238281, 0.019012451171875, -0.005451202392578125, 0.0166473388671875, 0.00678253173828125, 0.0174407958984375, 0.029144287109375, -0.0266876220703125, -0.00882720947265625, -0.0024566650390625, 0.004852294921875, -0.024566650390625, -0.00968170166015625, 0.01654052734375, 0.005702972412109375, -0.02801513671875, -0.0144195556640625, 0.026153564453125, -0.0103607177734375, -0.0110626220703125, -0.0148468017578125, -0.00522613525390625, 0.0034084320068359375, 0.014007568359375, -0.007843017578125, -0.005237579345703125, -0.004119873046875, -0.0003867149353027344, -0.0066375732421875, -0.004261016845703125, 0.07122802734375, 0.006977081298828125, -0.0103912353515625, 0.0273895263671875, -0.00792694091796875, -0.0269927978515625, -0.0171051025390625, 0.007965087890625, -0.038604736328125, 0.0157928466796875, -0.01499176025390625, 0.00156402587890625, -0.0022640228271484375, 0.00382232666015625, -0.014251708984375, 0.004741668701171875, 0.020782470703125, 0.0217437744140625, -0.001983642578125, -0.00885772705078125, -0.01117706298828125, 0.0367431640625, 0.019622802734375, -0.0133514404296875, -0.024139404296875, 0.01184844970703125, 0.035675048828125, -0.024566650390625, -0.0005464553833007812, -0.00489044189453125, -0.0256500244140625, -0.005191802978515625, -0.020599365234375, 0.0016155242919921875, -0.0302276611328125, 0.0213775634765625, -0.00836181640625, 0.0227203369140625, 0.002941131591796875, 0.002956390380859375, 0.0211334228515625, -0.00812530517578125, 0.0181732177734375, -0.0055999755859375, 5.650520324707031e-05, -0.0113372802734375, -0.00846099853515625, -0.00240325927734375, -0.0321044921875, 0.005512237548828125, 0.031890869140625, 0.0245208740234375, -0.0308380126953125, -0.0002949237823486328, -0.0173797607421875, -0.00476837158203125, -0.0116424560546875, 0.0330810546875, 0.01062774658203125, 0.00782012939453125, -0.01079559326171875, 0.0176849365234375, -0.005889892578125, 0.0190582275390625, 0.03802490234375, -0.027374267578125, 0.00685882568359375, -0.0024890899658203125, -0.061279296875, -0.0030498504638671875, -0.04095458984375, -0.0025043487548828125, -0.02069091796875, -0.006244659423828125, 0.0017728805541992188, 0.0233154296875, 0.031982421875, 0.0030536651611328125, 0.029998779296875, -0.014556884765625, 0.002841949462890625, 0.0180511474609375, -0.01276397705078125, -0.0214385986328125, -0.001079559326171875, -0.0310821533203125, -0.016693115234375, 0.0250091552734375, 0.0005946159362792969, 0.0182342529296875, -0.0047760009765625, 0.0087432861328125, -0.0051727294921875, 0.0256500244140625, 0.009918212890625, 0.0216522216796875, -0.0011892318725585938, 0.0170440673828125, 0.018096923828125, -0.021881103515625, 0.0260162353515625, 0.0105133056640625, -0.0161590576171875, 0.02777099609375, -0.026611328125, -0.0267181396484375, -0.020660400390625, 0.0035610198974609375, -0.0184173583984375, 0.004161834716796875, 0.0011529922485351562, 0.0056304931640625, 0.0214996337890625, -0.0005021095275878906, -0.00440216064453125, -0.025909423828125, -0.01047515869140625, -0.05340576171875, -0.033294677734375, -0.040557861328125, 0.041748046875, 0.00036025047302246094, 0.0025177001953125, -0.0059814453125, -0.00455474853515625, 0.035125732421875, 0.01153564453125, -0.0193634033203125, -0.039520263671875, -0.0234222412109375, -0.01336669921875, 0.012359619140625, 0.006053924560546875, -0.00201416015625, -0.0091400146484375, 0.007793426513671875, 0.005290985107421875, -0.0301971435546875, -0.0036334991455078125, 0.0158538818359375, -0.0100860595703125, 0.005397796630859375, -0.01171875, -0.0010519027709960938, 0.00856781005859375, -0.044189453125, 0.0159149169921875, -0.011810302734375, 0.03289794921875, 0.0107879638671875, 0.01074981689453125, -0.0196685791015625, 0.00562286376953125, 0.031890869140625, -0.0060577392578125, -0.018402099609375, 0.015167236328125, -0.036956787109375, -0.0221099853515625, 0.0237579345703125, -0.01396942138671875, 0.00485992431640625, -0.032867431640625, -0.044342041015625, 0.0302886962890625, -0.006622314453125, 0.004974365234375, 0.0035915374755859375, 0.0037364959716796875, 0.0382080078125, -0.0016508102416992188, -0.05010986328125, -0.01334381103515625, 0.0175018310546875, 0.06317138671875, 0.00537872314453125, 0.01308441162109375, 0.0225677490234375, -0.005035400390625, 0.002582550048828125, 0.005084991455078125, -0.00955963134765625, 0.0034770965576171875, -0.024566650390625, 0.002918243408203125, -0.01192474365234375, 0.0335693359375, -0.00518035888671875, 0.021697998046875, 0.00484466552734375, -0.021636962890625, -0.0273284912109375, -0.0139007568359375, -0.0016422271728515625, 0.00760650634765625, 0.0261993408203125, 0.0167388916015625, -0.0017232894897460938, -0.0276641845703125, -0.00147247314453125, -0.0162811279296875, -0.05377197265625, -0.0233306884765625, 0.0080413818359375, -0.0218048095703125, 0.055816650390625, -0.05169677734375, -0.042266845703125, -0.003520965576171875, 0.0164337158203125, 0.0214385986328125, -0.0019083023071289062, 0.0174407958984375, -0.0111541748046875, 0.031707763671875, 0.01506805419921875, -0.0174407958984375, 0.007312774658203125, -0.0265655517578125, -0.019683837890625, 0.0347900390625, 0.0031528472900390625, 0.0004901885986328125, -0.07196044921875, 0.0232391357421875, 0.02435302734375, -0.0067901611328125, 0.002841949462890625, 0.0028018951416015625, -0.030670166015625, 0.049468994140625, -0.017059326171875, 0.00036835670471191406, -0.0098114013671875, 0.00844573974609375, 0.025726318359375, -0.0158843994140625, 0.01465606689453125, 9.739398956298828e-05, -0.0238800048828125, -0.010833740234375, 0.0128631591796875, -0.00844573974609375, 0.005832672119140625, -0.0244293212890625, 0.0170440673828125, -0.0040130615234375, 0.0175018310546875, 0.00450897216796875, 0.0158843994140625, -0.0234832763671875, 0.01421356201171875, -0.00289154052734375, -0.027984619140625, -0.01345062255859375, -0.00273895263671875, -0.03265380859375, -0.01464080810546875, -0.00429534912109375, -0.02032470703125, -0.017852783203125, -0.0016021728515625, 0.020355224609375, 0.01143646240234375, 0.0189208984375, 0.00991058349609375, -0.026702880859375, -0.027252197265625, -0.0318603515625, 0.013824462890625, -0.0186920166015625, 0.03466796875, -0.0218963623046875, -0.03009033203125, -0.0308380126953125, -0.0014162063598632812, 0.01111602783203125, 0.01261138916015625, 0.012908935546875, -0.0147705078125, -0.0148468017578125, 0.01540374755859375, -0.0222320556640625, 0.018035888671875, 0.01268768310546875, -0.01904296875, -0.00891876220703125, -0.01253509521484375, 0.043731689453125, 0.003570556640625, 0.0240936279296875, 0.006664276123046875, -0.007022857666015625, -0.0014190673828125, 0.0016641616821289062, 0.036102294921875, 0.01593017578125, -0.01091766357421875, -0.01194000244140625, 0.01186370849609375, -0.024169921875, -0.0161590576171875, 0.005161285400390625, -0.0219573974609375, -0.00024175643920898438, -0.0023059844970703125, 0.01290130615234375, 0.01291656494140625, -0.00696563720703125, -0.0012035369873046875, 0.01206207275390625, -0.007167816162109375, -0.0007696151733398438, 0.00391387939453125, 0.02099609375, -0.0026645660400390625, 0.0117950439453125, 0.0128936767578125, -0.0269927978515625, 0.0126495361328125, 0.01029205322265625, 0.00018286705017089844, 0.037200927734375, 0.0287322998046875, 0.038330078125, 0.01678466796875, -0.01227569580078125, 0.0018682479858398438, -0.0195465087890625, 0.01250457763671875, 0.0305328369140625, -0.017242431640625, -0.0125579833984375, 0.002468109130859375, 0.00801849365234375, 0.0160369873046875, 0.01378631591796875, 0.035858154296875, -0.00521087646484375, -0.005428314208984375, -0.027313232421875, -0.004917144775390625, 0.02447509765625, -0.018035888671875, -0.004566192626953125, 0.02349853515625, 0.016021728515625, -0.035552978515625, -0.0134124755859375, 0.0174560546875, -0.005039215087890625, 0.031982421875, -0.00518035888671875, -0.003940582275390625, 0.0021648406982421875, 0.0233917236328125, 0.03143310546875, -0.0230712890625, -0.016021728515625, -0.01027679443359375, -0.059173583984375, -0.023834228515625, 0.002216339111328125, 0.01448822021484375, -0.041778564453125, 0.01629638671875, 0.029510498046875, 0.01276397705078125, 0.01203155517578125, 0.0401611328125, -0.0206298828125, -0.01215362548828125, -0.0006728172302246094, -0.0265350341796875, -0.01541900634765625, 0.00010961294174194336, 0.01387786865234375, -0.019866943359375, -0.01287841796875, -0.0157470703125, 0.044342041015625, -0.032073974609375, 0.023193359375, 0.0158538818359375, 0.01149749755859375, 0.0112152099609375, 0.00412750244140625, -0.042724609375, -0.015899658203125], "caa2ef46-a962-4005-a550-132f2f557db5": [-0.0216064453125, -0.0303192138671875, 0.0212860107421875, -0.0007805824279785156, 0.0321044921875, -0.0017957687377929688, 0.00867462158203125, 0.036865234375, 0.03076171875, 0.06231689453125, 0.006114959716796875, -0.051910400390625, -0.015899658203125, -0.060882568359375, -0.0294036865234375, 0.0061798095703125, -0.042938232421875, 0.025390625, -0.0232696533203125, -0.008758544921875, 0.035369873046875, 0.04156494140625, -0.032379150390625, 0.007335662841796875, -0.0181121826171875, -0.0145721435546875, -0.004070281982421875, 0.01389312744140625, -0.01195526123046875, -0.004364013671875, 0.010528564453125, -0.0237579345703125, -0.01611328125, 0.006877899169921875, -0.019561767578125, 0.0435791015625, -0.0159454345703125, -0.0291748046875, 0.0161285400390625, -0.0084228515625, -0.0011339187622070312, -0.0239715576171875, 0.0207366943359375, 0.0274810791015625, -0.01995849609375, 0.0006866455078125, -0.0225677490234375, -0.001773834228515625, 0.0169219970703125, 0.0225830078125, -0.05401611328125, 0.03338623046875, 0.01277923583984375, 0.01183319091796875, -0.00737762451171875, 0.006702423095703125, 0.01568603515625, 0.00261688232421875, -0.0004482269287109375, 0.0305938720703125, 0.0469970703125, -0.0148468017578125, 0.01331329345703125, 0.0203399658203125, -0.0038700103759765625, -0.039459228515625, 0.0154266357421875, 0.027008056640625, 0.0145263671875, -0.01183319091796875, 0.055389404296875, 0.0305938720703125, -0.037017822265625, -0.0239715576171875, 0.0072021484375, -0.005504608154296875, 0.021514892578125, -0.007659912109375, -0.03973388671875, -0.060546875, -0.00788116455078125, 0.014862060546875, -0.026397705078125, -0.0355224609375, -0.02581787109375, -0.01064300537109375, -0.051666259765625, -0.01395416259765625, -0.0228271484375, -0.032562255859375, -0.02740478515625, 0.0026302337646484375, -0.00782012939453125, 0.0081329345703125, 0.060089111328125, -0.0099945068359375, 0.034881591796875, 0.0178070068359375, 0.00957489013671875, 0.0024814605712890625, -0.034942626953125, -0.0347900390625, -0.07464599609375, 0.0231170654296875, 0.0128173828125, 0.01441192626953125, 0.0439453125, -0.04400634765625, -0.048828125, 0.01318359375, -0.078125, 0.017120361328125, -0.0195770263671875, 0.016845703125, -0.0404052734375, -0.0310211181640625, -0.045928955078125, -0.0032939910888671875, -0.0193939208984375, -0.01099395751953125, -0.062164306640625, 0.0031528472900390625, -0.00873565673828125, 0.02618408203125, -0.0167694091796875, -0.030731201171875, 0.022430419921875, -0.0134429931640625, -0.046905517578125, -0.0247650146484375, -0.004001617431640625, 0.0183258056640625, 0.026824951171875, -0.0433349609375, -0.032073974609375, -0.04241943359375, 0.0063323974609375, 0.033111572265625, -0.0309600830078125, -0.01529693603515625, 0.01000213623046875, -0.0222320556640625, -0.0164031982421875, 0.043182373046875, -0.0310821533203125, -0.01427459716796875, -0.0142364501953125, 0.026214599609375, -0.04559326171875, 0.038421630859375, 0.0299530029296875, 0.0369873046875, -0.036041259765625, 0.003612518310546875, -0.0027332305908203125, 0.0267486572265625, 0.0047607421875, 0.015960693359375, -0.01490020751953125, -0.0284271240234375, -0.0262603759765625, -0.0285186767578125, -0.00286102294921875, -0.03143310546875, -0.001232147216796875, 0.05865478515625, 0.0175933837890625, -0.003658294677734375, -0.03973388671875, -0.06512451171875, -0.022613525390625, -0.03558349609375, -0.038482666015625, 0.044097900390625, -0.01468658447265625, -0.048828125, 0.0271453857421875, 0.0157318115234375, -0.01079559326171875, 0.007259368896484375, -0.01137542724609375, 0.0264129638671875, -0.039642333984375, 0.0010919570922851562, -0.03228759765625, -0.048828125, -0.01837158203125, -0.0263671875, 0.01323699951171875, 0.005828857421875, 0.0171356201171875, 0.0201873779296875, 0.048492431640625, 0.0265655517578125, 0.05145263671875, -0.058746337890625, 0.054229736328125, -0.0298919677734375, -0.023895263671875, 0.028076171875, 0.0217437744140625, 0.00029277801513671875, 0.0235443115234375, -0.00011008977890014648, 0.036956787109375, -0.05694580078125, 0.016204833984375, 0.0208740234375, -0.0628662109375, 0.0435791015625, 0.044219970703125, -0.01873779296875, 0.05322265625, 0.026885986328125, -0.039306640625, 0.025848388671875, -0.0303802490234375, 0.003143310546875, -0.0244598388671875, 0.01451873779296875, -0.00732421875, 0.0248260498046875, 0.067138671875, -0.0226287841796875, -0.00970458984375, 0.0313720703125, 0.037567138671875, -0.00565338134765625, -0.0037689208984375, -0.0357666015625, 0.00734710693359375, -0.0174102783203125, -0.0168304443359375, -0.0198974609375, 0.03466796875, -0.03173828125, 0.059967041015625, 0.0028324127197265625, 0.01544952392578125, 0.00624847412109375, 0.007080078125, -0.007488250732421875, 0.06121826171875, 0.06280517578125, 0.0220489501953125, 0.01739501953125, -0.0265960693359375, -0.09033203125, 0.033660888671875, 0.0250091552734375, 0.0182952880859375, -0.022247314453125, 0.06170654296875, -0.006412506103515625, -0.035400390625, -0.03558349609375, -0.0018024444580078125, -0.006343841552734375, -0.0132293701171875, -0.03216552734375, 0.0574951171875, 0.002368927001953125, 0.0145721435546875, 0.0158538818359375, -0.03985595703125, -0.07208251953125, -0.0104522705078125, 0.01727294921875, -0.01708984375, -0.033935546875, -0.023468017578125, -0.0092620849609375, 0.0193634033203125, 0.038360595703125, -0.054046630859375, -0.01213836669921875, -0.00923919677734375, 0.0219879150390625, -0.0282135009765625, 0.053131103515625, 0.0079193115234375, 0.045166015625, -0.0246734619140625, 0.0305938720703125, 0.018646240234375, 0.038726806640625, -0.0220489501953125, -0.007965087890625, -0.0176544189453125, -0.0170135498046875, -0.01013946533203125, -0.0282745361328125, 0.0455322265625, 0.030609130859375, -0.00824737548828125, -0.00426483154296875, 0.03839111328125, 0.01934814453125, 0.0004978179931640625, 0.0084075927734375, 0.0640869140625, -0.0462646484375, 0.0178070068359375, 0.033905029296875, 0.01531982421875, 0.0197906494140625, 0.0146026611328125, 0.035064697265625, 0.038726806640625, -0.0250701904296875, 0.00911712646484375, 0.05548095703125, 0.0221405029296875, 0.01360321044921875, -0.049957275390625, -0.0225372314453125, 0.0660400390625, 0.01427459716796875, 0.0367431640625, -0.042755126953125, -0.045806884765625, -0.00589752197265625, 0.0413818359375, -0.017425537109375, -0.0266571044921875, -0.012847900390625, 0.047119140625, 0.012542724609375, -0.02880859375, -0.02105712890625, -0.037139892578125, -0.040802001953125, -0.020904541015625, 0.015625, 0.03082275390625, -0.003322601318359375, -0.032684326171875, -0.0167388916015625, -0.0179595947265625, 0.00389862060546875, -0.035614013671875, -0.042694091796875, -0.08734130859375, -0.007190704345703125, 0.0186614990234375, 0.018402099609375, 0.0030975341796875, 0.003444671630859375, 0.006500244140625, 0.022796630859375, 0.0233917236328125, 0.0216827392578125, 0.007049560546875, 0.00771331787109375, -0.0467529296875, -0.045928955078125, -0.00518798828125, 0.00954437255859375, -0.036651611328125, 7.706880569458008e-05, 0.0003190040588378906, -0.025543212890625, 0.007190704345703125, 0.0272064208984375, 0.03118896484375, -0.028961181640625, -0.0472412109375, -0.03985595703125, -0.01052093505859375, -0.040863037109375, 0.01033782958984375, -0.051300048828125, 0.039520263671875, -0.03204345703125, -0.034576416015625, 0.03326416015625, -0.0174102783203125, 0.038177490234375, 0.01097869873046875, 0.06585693359375, 0.058502197265625, -0.02886962890625, -0.052825927734375, -0.04815673828125, -0.01898193359375, 0.0261688232421875, -0.01007080078125, -0.0090789794921875, -0.0208892822265625, -0.02020263671875, 0.02166748046875, -0.04736328125, -0.03826904296875, -0.0372314453125, -0.01264190673828125, 0.024658203125, -0.005207061767578125, 0.043914794921875, 0.024261474609375, -0.03009033203125, -0.0164642333984375, 0.0357666015625, -0.01447296142578125, 0.0292816162109375, -0.00988006591796875, -0.0009112358093261719, -0.026153564453125, 0.0124359130859375, 0.0242462158203125, 0.0264129638671875, 0.05523681640625, -0.04888916015625, 0.0305328369140625, -0.0233001708984375, -0.01316070556640625, -0.0198974609375, 0.0259552001953125, -0.011627197265625, 0.053253173828125, 0.042633056640625, 0.00827789306640625, -0.047515869140625, -0.0035839080810546875, 0.029144287109375, 0.004413604736328125, 0.06695556640625, 0.00879669189453125, -0.00322723388671875, 0.08135986328125, -0.058563232421875, -0.0014495849609375, 0.01549530029296875, 0.0144500732421875, -0.0259857177734375, 0.0086517333984375, -0.0113677978515625, -0.006038665771484375, 0.052093505859375, -0.037567138671875, -0.016693115234375, 0.00528717041015625, -0.0255889892578125, -0.059783935546875, -0.0394287109375, -0.0250091552734375, 0.037811279296875, -0.0310516357421875, -0.0272674560546875, 0.0258636474609375, -0.0233612060546875, 0.00914764404296875, -0.052581787109375, -0.0023670196533203125, 0.037628173828125, -0.03289794921875, -0.043670654296875, 0.005771636962890625, -0.01235198974609375, 0.01343536376953125, -0.018890380859375, 0.0123291015625, -0.012237548828125, -0.02716064453125, 0.03265380859375, 0.01085662841796875, 0.0019969940185546875, -0.01369476318359375, -0.0054168701171875, -0.0389404296875, 0.03265380859375, -0.00878143310546875, 0.0153350830078125, 0.033416748046875, -0.0045623779296875, -0.039581298828125, 0.0031871795654296875, 0.01319122314453125, -0.015045166015625, -0.041534423828125, -0.005428314208984375, 0.0248260498046875, 0.05059814453125, 0.0197601318359375, 0.061981201171875, 0.056549072265625, 0.013702392578125, 0.0140228271484375, -0.01107025146484375, 0.053802490234375, 0.01702880859375, 0.030059814453125, -0.007049560546875, 0.05108642578125, -0.0182037353515625, 0.046173095703125, 0.0281524658203125, 0.020843505859375, -0.0157623291015625, 0.0013036727905273438, -0.037506103515625, -0.020355224609375, 0.029754638671875, 0.01202392578125, 0.06524658203125, -0.0119781494140625, -0.0034770965576171875, -0.0382080078125, -0.0014333724975585938, 0.00899505615234375, -0.0181427001953125, 0.006565093994140625, -0.0225982666015625, -0.0148468017578125, -0.007659912109375, 0.0093841552734375, 0.02606201171875, 0.02801513671875, 0.01187896728515625, -0.015106201171875, -0.01861572265625, -0.01529693603515625, -0.014678955078125, 0.0172882080078125, -0.010406494140625, -0.032501220703125, -0.02093505859375, -0.00923919677734375, 0.0028514862060546875, -0.00577545166015625, -0.0258941650390625, 0.022705078125, -0.004802703857421875, 0.032012939453125, 0.0041656494140625, -0.05853271484375, 0.017547607421875, -0.00562286376953125, -0.01325225830078125, -0.0305633544921875, 0.0118408203125, 0.0205078125, 0.038482666015625, 0.034088134765625, 0.0087890625, -0.00429534912109375, 0.0210418701171875, -0.0108642578125, 0.0011205673217773438, -0.0286102294921875, 0.0122528076171875, 0.01476287841796875, -0.0099334716796875, 0.0303497314453125, -0.02105712890625, 0.0215911865234375, 0.002410888671875, 0.007480621337890625, -0.054534912109375, 0.0008296966552734375, 0.024688720703125, -0.02825927734375, -0.0245361328125, 0.043304443359375, 0.024017333984375, -0.042877197265625, 0.0013628005981445312, 0.016815185546875, 0.029632568359375, -0.001255035400390625, 0.017730712890625, -0.040069580078125, -0.00830841064453125, -0.007450103759765625, -0.040252685546875, 0.0173797607421875, -0.01357269287109375, 0.0093231201171875, 0.0189361572265625, 0.004291534423828125, -0.0017337799072265625, -0.00917816162109375, -0.043304443359375, -0.00649261474609375, 0.06536865234375, -0.00508880615234375, 0.0169830322265625, 0.0290679931640625, 0.01403045654296875, 0.007106781005859375, 0.007770538330078125, 0.01007080078125, -0.01322174072265625, 0.034698486328125, 0.018310546875, 0.00907135009765625, 0.0019083023071289062, -0.04071044921875, -0.00460052490234375, -0.010894775390625, 0.03729248046875, 0.0186920166015625, -0.004772186279296875, -0.06982421875, 0.006317138671875, 0.007049560546875, -0.0028324127197265625, -0.0131072998046875, -0.00861358642578125, -0.00185394287109375, 0.033721923828125, 0.0018014907836914062, 0.020599365234375, -0.006927490234375, -0.06658935546875, -0.025360107421875, -0.03594970703125, 0.0010395050048828125, -0.01415252685546875, 0.05914306640625, -0.0277252197265625, 0.01104736328125, 0.0236968994140625, -0.032745361328125, 0.00673675537109375, 0.0197601318359375, 0.02142333984375, -0.0310516357421875, -0.009613037109375, -0.01493072509765625, 0.00160980224609375, 0.0030155181884765625, 0.025909423828125, -0.006511688232421875, -0.037322998046875, -0.013458251953125, 0.00479888916015625, -0.0174713134765625, 0.0228424072265625, -0.01248931884765625, -0.033416748046875, 0.0170745849609375, -0.0169830322265625, 0.0028133392333984375, -0.044189453125, 0.009246826171875, 0.0032482147216796875, -0.041107177734375, -0.025360107421875, -0.03363037109375, 0.01276397705078125, -0.022552490234375, -0.048248291015625, 0.0034637451171875, 0.010528564453125, 0.04290771484375, -0.0167999267578125, -0.007511138916015625, 0.0009794235229492188, -0.03631591796875, -0.002994537353515625, -0.035125732421875, -0.0081787109375, 0.0059814453125, -0.00021922588348388672, 0.01325225830078125, 0.04693603515625, -0.008544921875, -0.00841522216796875, 0.040283203125, 0.017425537109375, -0.063720703125, -0.0223846435546875, 0.032073974609375, 0.00861358642578125, -0.00753021240234375, -0.01739501953125, -0.0012407302856445312, -0.0167694091796875, 0.0165863037109375, -0.00820159912109375, -0.01222991943359375, 0.01450347900390625, -0.02545166015625, -0.01425933837890625, 0.0197601318359375, -0.002696990966796875, 0.037994384765625, -0.016815185546875, 0.0259857177734375, 0.007305145263671875, -0.0025196075439453125, 0.0251922607421875, -0.036346435546875, 0.0389404296875, 0.01433563232421875, 0.0309600830078125, -0.007171630859375, 0.041717529296875, 0.01290130615234375, 0.00830078125, -0.04107666015625, 0.0012569427490234375, -0.005748748779296875, 0.003681182861328125, -0.006084442138671875, -0.0031642913818359375, -0.0121612548828125, 0.018707275390625, 0.00835418701171875, 0.009124755859375, -0.05126953125, -0.00673675537109375, 0.0016193389892578125, 0.06622314453125, -0.00168609619140625, 0.0016841888427734375, -0.00417327880859375, 0.01103973388671875, 0.03143310546875, -0.0311279296875, 0.0003688335418701172, -0.0002593994140625, 0.005680084228515625, -0.00034499168395996094, -0.01678466796875, -0.03515625, -0.0191192626953125, 0.02557373046875, -0.004627227783203125, 0.006114959716796875, 0.008941650390625, 0.041534423828125, -0.00452423095703125, -0.0273284912109375, -0.00010216236114501953, 0.01517486572265625, -0.057342529296875, 0.021484375, -0.037322998046875, -0.031768798828125, 0.02606201171875, -0.02850341796875, 0.007843017578125, -0.003841400146484375, 0.03204345703125, -0.0216522216796875, -0.0025634765625, 0.054779052734375, -0.033447265625, 0.006473541259765625, -0.001125335693359375, 0.01334381103515625, -0.02044677734375, -0.01285552978515625, 0.02056884765625, 0.03314208984375, -0.0253143310546875, 0.01403045654296875, -0.0204620361328125, 0.00589752197265625, 0.0226287841796875, 0.01013946533203125, -0.0036525726318359375, 0.036468505859375, 0.0052490234375, 0.002666473388671875, 0.0150909423828125, 0.01155853271484375, -0.006443023681640625, 0.00037026405334472656, -0.0109405517578125, -0.046875, -0.02410888671875, 0.01129150390625, 0.057037353515625, -0.0170745849609375, 0.038055419921875, 0.007843017578125, -0.016143798828125, -0.0165557861328125, 0.01090240478515625, 0.0117340087890625, 0.0165252685546875, -0.0225372314453125, 0.0116424560546875, -0.0002428293228149414, 0.00943756103515625, -0.01690673828125, -0.0172882080078125, -0.036651611328125, -0.020660400390625, 0.01369476318359375, 0.004810333251953125, -0.030792236328125, -0.01258087158203125, 0.014892578125, -0.0033111572265625, -0.09405517578125, -0.0061492919921875, 0.02789306640625, -0.0303497314453125, 0.0127105712890625, -0.029571533203125, -0.004665374755859375, 0.0208587646484375, -0.0009226799011230469, -0.036376953125, 0.01422119140625, 0.0038700103759765625, 0.0010995864868164062, -0.03363037109375, -0.001888275146484375, -0.043212890625, -0.0005393028259277344, -0.00366973876953125, 0.031768798828125, -0.0113677978515625, -0.0421142578125, 0.026885986328125, -0.0299835205078125, 0.046966552734375, -0.01165771484375, -0.003681182861328125, -0.0252532958984375, 0.04010009765625, -0.0077972412109375, -0.0032367706298828125, -0.02679443359375, 0.00849151611328125, 0.01441192626953125, 0.0509033203125, -0.016815185546875, -0.0028972625732421875, -0.01200103759765625, 0.015655517578125, -0.01983642578125, 0.00972747802734375, 0.03839111328125, 0.00481414794921875, 0.07208251953125, 0.003978729248046875, 0.0084228515625, -0.01611328125, 0.0197601318359375, 0.0245208740234375, 0.0162200927734375, -0.00820159912109375, -0.0217437744140625, 0.02777099609375, 0.0223541259765625, -0.047393798828125, -0.0252838134765625, 0.043853759765625, -0.0077056884765625, -0.006969451904296875, 0.00836944580078125, 0.01491546630859375, -0.008056640625, -0.032318115234375, -0.0113067626953125, 0.0099639892578125, 0.0086517333984375, 0.0026645660400390625, 0.02947998046875, 0.02081298828125, 0.004795074462890625, -0.01039886474609375, -0.057708740234375, -0.0033626556396484375, -0.011962890625, -0.0165252685546875, 0.0099334716796875, 0.00501251220703125, 0.00959014892578125, 0.033294677734375, 0.019866943359375, 0.01104736328125, 0.03173828125, -0.0092010498046875, 0.0237579345703125, 0.018218994140625, -0.015380859375, 0.01806640625, 0.0197296142578125, -0.002544403076171875, -0.03729248046875, -0.0023555755615234375, 0.0279693603515625, -0.035186767578125, -0.01409912109375, 0.005298614501953125, -0.0271453857421875, 0.0352783203125, 0.0034046173095703125, 0.0175323486328125, 0.055633544921875, -0.003467559814453125, 0.0027980804443359375, -0.004146575927734375, -0.03912353515625, -0.01471710205078125, 0.004749298095703125, -0.00788116455078125, -0.0127716064453125, 0.0207061767578125, 0.01177215576171875, 0.0022449493408203125, 0.002597808837890625, 0.01474761962890625, 0.003948211669921875, 0.001857757568359375, 0.016021728515625, 0.00948333740234375, 0.04705810546875, -0.021820068359375, -0.026458740234375, -0.021759033203125, 0.0144500732421875, 0.0300445556640625, -0.00444793701171875, 0.016510009765625, 0.0055999755859375, 0.017730712890625, 0.01126861572265625, -0.01116943359375, -0.0140380859375, -0.002086639404296875, 0.02032470703125, 0.00870513916015625, -0.023529052734375, -0.01412200927734375, -0.00327301025390625, 0.0156097412109375, 0.029571533203125, -0.0076751708984375, 0.005207061767578125, 0.0252838134765625, 0.01129150390625, 0.0011386871337890625, -0.0088043212890625, -0.044921875, -0.028167724609375, 0.0078887939453125, 0.0257415771484375, -0.0140228271484375, -0.0027713775634765625, 0.00818634033203125, -0.0166473388671875, -0.0207061767578125, 0.005706787109375, 0.056121826171875, 0.03375244140625, 0.05218505859375, 0.007568359375, 0.0080718994140625, -0.046875, 0.004520416259765625, -0.0226898193359375, 0.00608062744140625, 0.020263671875, 0.01409149169921875, 0.006679534912109375, -0.0038661956787109375, -0.041473388671875, 0.0056610107421875, -0.0120849609375, 0.042633056640625, -0.002227783203125, 0.00543975830078125, 0.018829345703125, -0.0012912750244140625, 0.01525115966796875, 0.03759765625, 0.0184173583984375, -0.00785064697265625, 0.0087890625, 0.010528564453125, 0.011688232421875, 0.019683837890625, 0.019744873046875, 0.0140838623046875, 0.054595947265625, 0.0080108642578125, -0.0107879638671875, -0.0093841552734375, -0.050323486328125, -0.0257568359375, 0.0316162109375, -0.0094451904296875, 0.023162841796875, 0.03350830078125, -0.0214691162109375, -0.0372314453125, 0.0306396484375, 0.0115814208984375, -0.055145263671875, -0.01171112060546875, -0.0258026123046875, 0.037017822265625, 0.01027679443359375, 0.00043082237243652344, 0.013671875, 0.0263519287109375, -0.03729248046875, -0.02508544921875, -0.01219940185546875, -0.03759765625, -0.042938232421875, -0.01262664794921875, -0.0298614501953125, -0.046112060546875, -0.02593994140625, 0.023406982421875, 0.00757598876953125, 0.0105743408203125, -0.0369873046875, -0.013092041015625, 0.02203369140625, 0.010955810546875, -0.0309906005859375, 0.0340576171875, -0.00812530517578125, 0.032928466796875, -0.0247039794921875, -0.004657745361328125, 0.0014181137084960938, 0.0134735107421875, 0.02471923828125, -0.03192138671875, 0.032440185546875, 0.0006923675537109375, 0.0252227783203125, -0.01015472412109375, 0.0185089111328125, -0.035980224609375, 0.0244903564453125, 0.0070037841796875, 0.03472900390625, 0.00948333740234375, 0.001514434814453125, -0.03900146484375, 0.01001739501953125, -0.021820068359375, -0.01227569580078125, 0.00821685791015625, 0.005809783935546875, -0.004253387451171875, -0.004974365234375, -0.0138397216796875, 0.0195159912109375, -0.0212554931640625, -0.0008687973022460938, 0.0019626617431640625, 0.033416748046875, 0.01556396484375, -0.0007538795471191406, -0.00970458984375, -0.0194244384765625, 0.004856109619140625, 0.0198516845703125, -0.060699462890625, -0.0007433891296386719, 0.0006866455078125, -0.0153045654296875, -0.015350341796875, 0.0251007080078125, 0.040130615234375, -0.03009033203125, 0.037841796875, 0.0284423828125, 0.00428009033203125, 0.0037937164306640625, -0.00714874267578125, -0.01213836669921875, -0.0185394287109375, 0.01520538330078125, 0.0181121826171875, -0.0136566162109375, -0.023468017578125, 0.0263214111328125, -0.01207733154296875, 0.0262603759765625, -0.005207061767578125, -0.04486083984375, -0.027923583984375, 0.006275177001953125, 0.0084686279296875, 0.018707275390625, 0.00316619873046875, 0.01483154296875, 0.0034637451171875, -0.01396942138671875, 0.012115478515625, -0.013275146484375, 0.00902557373046875, 0.0175323486328125, -0.037567138671875, -0.0192413330078125, 0.00136566162109375, 0.0214996337890625, 0.01351165771484375, 0.035919189453125, 0.0181732177734375, 0.00678253173828125, -0.0175628662109375, 0.01348114013671875, -0.01247406005859375, -0.032684326171875, -0.0021724700927734375, 0.021942138671875, -0.002063751220703125, 0.01971435546875, -0.0022068023681640625, 0.0089569091796875, -0.01021575927734375, 0.01442718505859375, 0.006031036376953125, -0.0036907196044921875, 0.019927978515625, 0.006587982177734375, 0.019622802734375, 0.0194091796875, -0.0030040740966796875, 0.0305328369140625, -0.0241546630859375, 0.00655364990234375, -0.01238250732421875, 0.00273895263671875, -0.01515960693359375, -0.0037517547607421875, 0.0221099853515625, 0.00897979736328125, -0.0310821533203125, -0.0162811279296875, 0.0244903564453125, -0.0030574798583984375, -6.967782974243164e-05, -0.0208282470703125, -0.0135955810546875, 0.0018939971923828125, 0.0097808837890625, 0.0030975341796875, -0.00989532470703125, 0.00811004638671875, -0.004405975341796875, 0.0096893310546875, -0.00995635986328125, 0.08099365234375, 0.0015935897827148438, -0.01181793212890625, 0.00024318695068359375, -0.00959014892578125, -0.009429931640625, -0.00787353515625, -0.01016998291015625, -0.04290771484375, -0.004421234130859375, -0.01277923583984375, 0.002719879150390625, 0.00872039794921875, 0.0083465576171875, -0.005840301513671875, -0.0014591217041015625, 0.01268768310546875, 0.029144287109375, 0.0037689208984375, -0.00913238525390625, -0.032989501953125, 0.048126220703125, 0.00931549072265625, -0.02239990234375, -0.010650634765625, 0.029266357421875, 0.04974365234375, -0.01702880859375, 0.007366180419921875, 0.0033245086669921875, -0.010986328125, -0.0096435546875, -0.0280609130859375, 0.020263671875, -0.0299224853515625, 0.00785064697265625, -0.0061187744140625, 0.039947509765625, 0.0106353759765625, -0.0123443603515625, 0.015869140625, -0.0015306472778320312, 0.003482818603515625, 0.0048675537109375, 0.004512786865234375, -0.0236358642578125, -0.039306640625, -0.014862060546875, -0.042816162109375, 0.00888824462890625, 0.030670166015625, 0.02001953125, -0.024932861328125, -0.0012197494506835938, -0.026458740234375, 0.0099945068359375, -0.0217437744140625, 0.0328369140625, 0.00783538818359375, 0.00907135009765625, -0.0104522705078125, 0.0191192626953125, -0.00394439697265625, 0.033111572265625, 0.0241851806640625, -0.033416748046875, 0.015625, 0.0052947998046875, -0.053314208984375, -0.0129547119140625, -0.044403076171875, -0.01220703125, -0.01256561279296875, -0.0262451171875, 0.0038623809814453125, 0.024444580078125, 0.01432037353515625, 0.005832672119140625, 0.0236053466796875, -0.0010366439819335938, 0.005611419677734375, 0.0233154296875, -0.0035915374755859375, -0.04217529296875, -0.009735107421875, -0.03619384765625, -0.01519012451171875, 0.030853271484375, -0.0157623291015625, 0.0272064208984375, -0.0174713134765625, 0.0014753341674804688, 0.0028839111328125, 0.04022216796875, 0.00829315185546875, 0.021697998046875, 0.0031032562255859375, 0.0178985595703125, 0.021087646484375, -0.0197296142578125, 0.0250244140625, 0.013671875, -0.035980224609375, 0.0175018310546875, -0.0216217041015625, -0.02587890625, -0.00310516357421875, 0.0164794921875, 0.0017213821411132812, 0.018402099609375, 0.0024871826171875, 0.00739288330078125, 0.02606201171875, 0.0119476318359375, -0.0087127685546875, -0.0216217041015625, 0.01491546630859375, -0.0288848876953125, -0.02252197265625, -0.0546875, 0.033233642578125, -0.0017766952514648438, -0.01232147216796875, -0.003261566162109375, -0.017974853515625, 0.0418701171875, 0.0142059326171875, -0.03521728515625, -0.0189361572265625, -0.0109100341796875, -0.015716552734375, 0.00518035888671875, 0.0229034423828125, 0.0107574462890625, -0.0006546974182128906, 0.00628662109375, 0.0156707763671875, -0.041046142578125, -0.00665283203125, 0.01690673828125, -0.004302978515625, 0.01654052734375, -0.004215240478515625, 0.00063323974609375, 0.001018524169921875, -0.0294342041015625, 0.0161895751953125, 0.00664520263671875, 0.016387939453125, 0.001399993896484375, 0.00847625732421875, -0.01204681396484375, 0.00653839111328125, 0.054931640625, -0.00481414794921875, -0.0021686553955078125, 0.0180511474609375, -0.029693603515625, -0.03131103515625, 0.0262603759765625, -0.0234375, -0.00910186767578125, -0.0338134765625, -0.039215087890625, 0.030792236328125, 0.0033512115478515625, 0.0011835098266601562, 0.01727294921875, -0.01641845703125, 0.029632568359375, 0.00591278076171875, -0.0204620361328125, -0.0058746337890625, -0.0035724639892578125, 0.06280517578125, -0.0181427001953125, -0.00243377685546875, 0.023956298828125, -0.0004527568817138672, 0.0038890838623046875, -0.0092010498046875, -0.00821685791015625, 0.00484466552734375, -0.02899169921875, -0.0064239501953125, -0.0005602836608886719, 0.0013704299926757812, -0.002471923828125, 0.01084136962890625, 0.005588531494140625, -0.0268402099609375, -0.0225067138671875, -0.00833892822265625, -0.022674560546875, -0.0009331703186035156, 0.023834228515625, 0.00980377197265625, 0.0012187957763671875, -0.01190185546875, 0.004276275634765625, -0.0211639404296875, -0.05352783203125, -0.036529541015625, 0.005401611328125, -0.0194244384765625, 0.07659912109375, -0.026702880859375, -0.03460693359375, -0.02203369140625, 0.006938934326171875, 0.0250091552734375, 0.002716064453125, 0.017608642578125, -0.0033931732177734375, 0.01690673828125, -0.002681732177734375, -0.004772186279296875, -0.0027065277099609375, -0.024017333984375, -0.0097808837890625, 0.027801513671875, 0.0003712177276611328, 0.00643157958984375, -0.061126708984375, 0.0170745849609375, -0.0040435791015625, 0.0034656524658203125, 0.0169219970703125, 0.0156402587890625, -0.0160980224609375, 0.0484619140625, -0.0107269287109375, 0.0047454833984375, -0.00778961181640625, -0.01154327392578125, 0.0142059326171875, -0.0191497802734375, -0.0105743408203125, 0.0167694091796875, -0.004486083984375, -0.0219879150390625, 0.0211181640625, -0.01776123046875, 0.004734039306640625, -0.031890869140625, 0.0074462890625, 0.010467529296875, 0.007472991943359375, -0.01189422607421875, 0.0148773193359375, -0.0009984970092773438, 0.0211944580078125, -0.02166748046875, -0.016510009765625, -0.007595062255859375, -0.0283203125, -0.042510986328125, -0.0122833251953125, -0.0084075927734375, -0.025726318359375, -0.0279388427734375, -0.00904083251953125, 0.020904541015625, 0.004245758056640625, 0.01094818115234375, 0.01171875, -0.0399169921875, -0.0162811279296875, -0.0200958251953125, 0.005207061767578125, 0.003009796142578125, 0.0304718017578125, -0.0235595703125, -0.01312255859375, -0.0316162109375, -0.006977081298828125, 0.0035152435302734375, 0.034423828125, 0.0175933837890625, -0.0263519287109375, -0.01232147216796875, 0.0054473876953125, -0.00722503662109375, 0.0166473388671875, 0.0130462646484375, -0.0216522216796875, -0.006404876708984375, -0.004108428955078125, 0.04864501953125, 0.01175689697265625, 0.005157470703125, 0.00726318359375, -0.0007867813110351562, 0.01617431640625, 0.0019626617431640625, 0.043914794921875, 0.004589080810546875, 0.01555633544921875, -0.00921630859375, 0.01371002197265625, -0.0228118896484375, -0.013519287109375, 0.01263427734375, -0.030120849609375, 0.006282806396484375, 0.01412200927734375, -0.0015468597412109375, 0.03594970703125, -0.00896453857421875, 0.00045561790466308594, 0.0081634521484375, 0.004413604736328125, -0.0008130073547363281, 0.0017242431640625, 0.01206207275390625, 0.019012451171875, 0.0163726806640625, 0.0112457275390625, -0.0289764404296875, 0.0084381103515625, 0.0209197998046875, 0.0027027130126953125, 0.03936767578125, 0.02685546875, 0.034027099609375, 0.0249481201171875, -0.009521484375, 0.01332855224609375, -0.008819580078125, 0.01342010498046875, 0.034881591796875, -0.006946563720703125, -0.0064544677734375, -0.00727081298828125, 0.0035228729248046875, 0.00312042236328125, 0.009368896484375, 0.0305633544921875, -0.01311492919921875, -0.002170562744140625, -0.0276641845703125, -0.01427459716796875, 0.006099700927734375, -0.01404571533203125, -0.01190185546875, 0.0136871337890625, 0.014617919921875, -0.0279541015625, -0.016204833984375, 0.0212249755859375, -0.027587890625, 0.031463623046875, 0.0050811767578125, 0.0189666748046875, -0.01959228515625, 0.02276611328125, 0.0244598388671875, -0.004627227783203125, -0.0137939453125, -0.01525115966796875, -0.06439208984375, -0.03375244140625, 0.013031005859375, 0.01285552978515625, -0.033172607421875, 0.049530029296875, 0.0079803466796875, 0.01727294921875, -0.01529693603515625, 0.0184478759765625, -0.008575439453125, -0.006256103515625, 0.0221710205078125, -0.03936767578125, -0.00919342041015625, -0.0005445480346679688, -0.00461578369140625, -0.01236724853515625, -0.0173187255859375, -0.021881103515625, 0.05584716796875, -0.036529541015625, 0.0207672119140625, 0.01554107666015625, 0.01119232177734375, 0.00435638427734375, -0.006500244140625, -0.0223541259765625, -0.01525115966796875]}, "text_id_to_ref_doc_id": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "5692100e-6f1f-48eb-95e5-e02bb96eecb3": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "caa2ef46-a962-4005-a550-132f2f557db5": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "metadata_dict": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"_node_type": "TextNode", "document_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/docstore.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"docstore/metadata": {"7702a8c5-b003-4773-8e9e-552b88bf4d1b": {"doc_hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b"}, "b778a1ad-ee64-425c-85f1-da60ecbb5543": {"doc_hash": "b9ba40979d6d88c0df9ad8b43c75e84bd04830cc4f36686d10c9f636394131e7", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"doc_hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"doc_hash": "a6d6eb6eda3c59f142aa2dad0b9c0d3100b23c62d5b3b57686a666696f6d8b83", "ref_doc_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b"}}, "docstore/ref_doc_info": {"7702a8c5-b003-4773-8e9e-552b88bf4d1b": {"node_ids": ["b778a1ad-ee64-425c-85f1-da60ecbb5543", "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "caa2ef46-a962-4005-a550-132f2f557db5"], "metadata": {}}}, "docstore/data": {"b778a1ad-ee64-425c-85f1-da60ecbb5543": {"__data__": {"id_": "b778a1ad-ee64-425c-85f1-da60ecbb5543", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "node_type": "1", "metadata": {}, "hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Recent experiences:\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-08', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 19:54:22', 'session_id': 1}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 19:54:50', 'session_id': 2}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 20:10:29', 'session_id': 3}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 20:13:31', 'session_id': 0}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 21:38:35', 'session_id': 5}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 1485, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "5692100e-6f1f-48eb-95e5-e02bb96eecb3": {"__data__": {"id_": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "b778a1ad-ee64-425c-85f1-da60ecbb5543", "node_type": "1", "metadata": {}, "hash": "b9ba40979d6d88c0df9ad8b43c75e84bd04830cc4f36686d10c9f636394131e7", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "caa2ef46-a962-4005-a550-132f2f557db5", "node_type": "1", "metadata": {}, "hash": "a6d6eb6eda3c59f142aa2dad0b9c0d3100b23c62d5b3b57686a666696f6d8b83", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "', 'session_date': '2026-07-12 21:39:00', 'session_id': 6}\n- {'topics_discussed': ['N/A'], 'emotional_state': 'unknown', 'insights': 'No insights extracted.', 'session_date': '2026-07-12 23:17:29', 'session_id': 7}\n- {'topics_discussed': ['Public speaking anxiety and stress', 'Fear of making mistakes during speeches', 'Lack of self-confidence', 'Strategies to manage speaking anxiety (e.g., shifting focus, preparation, breathing techniques, visualization, reframing nervousness as excitement, and gradual progress)'], 'emotional_state': 'Stressed and anxious about public speaking; feeling a lack of self-confidence', 'insights': 'The user feels nervous and afraid when speaking in front of a group due to fear of making mistakes and perceives themselves as lacking self-confidence. They are seeking support and strategies to manage this fear and improve their confidence.', 'session_date': '2026-07-12 23:19:29', 'session_id': 8}\n- {'topics_discussed': ['Greetings'], 'emotional_state': 'Neutral (insufficient information to determine specific emotions) ', 'insights': \"The conversation is brief and primarily focused on exchanging greetings. The user's emotional state or thoughts cannot be inferred from the limited interaction.\", 'session_date': '2026-07-12 23:50:58', 'session_id': 9}\n- {'topics_discussed': ['Public speaking challenges', 'Stress and nervousness while speaking in front of a group', 'Lack of self-confidence', 'Strategies to overcome fear of public speaking, such as starting small, preparation, breathing techniques, positive self-talk, and focusing on connection over perfection'], 'emotional_state': 'stressed and anxious', 'insights': 'The user feels nervous and lacks confidence when speaking in front of groups due to a fear of making mistakes. They are aware of this issue and want to work on improving their self-confidence. They are open to exploring strategies to address their public speaking anxiety.", "mimetype": "text/plain", "start_char_idx": 1485, "end_char_idx": 3422, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "caa2ef46-a962-4005-a550-132f2f557db5": {"__data__": {"id_": "caa2ef46-a962-4005-a550-132f2f557db5", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "7702a8c5-b003-4773-8e9e-552b88bf4d1b", "node_type": "4", "metadata": {}, "hash": "6606341430bc1f11c594e8ae1379f198f99ae3bb16538c2e11d4846966e1500b", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "5692100e-6f1f-48eb-95e5-e02bb96eecb3", "node_type": "1", "metadata": {}, "hash": "80cdc0df5a7bea15718c7a70e6ba0fb75dcb2ebad612a7aa622ec56ec3c13b15", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "They are open to exploring strategies to address their public speaking anxiety.', 'session_date': '2026-07-13 17:35:48', 'session_id': 10}\n- {'topics_discussed': ['greeting'], 'emotional_state': 'neutral', 'insights': 'The user initiated the conversation with a simple greeting, and no specific emotional state or detailed thoughts were conveyed.', 'session_date': '2026-07-13 17:56:55', 'session_id': 11}\n- {'topics_discussed': ['Greeting'], 'emotional_state': 'Neutral (insufficient information to determine emotional state)', 'insights': 'The user initiated a greeting, but there is no detailed information about their feelings or thoughts based on the conversation.', 'session_date': '2026-07-13 17:56:55', 'session_id': 11}\n- {'topics_discussed': ['Fear and stress related to public speaking', 'Building self-confidence', 'Techniques for overcoming nervousness while speaking in front of a group', 'Memory limitations of the AI assistant'], 'emotional_state': 'stressed and anxious, with feelings of low self-confidence', 'insights': \"The user struggles with nervousness and fear when speaking in front of groups, stemming from concerns about making mistakes and lacking self-confidence. They are actively seeking strategies to overcome these challenges. The user also inquired about the AI's ability to recall past conversations, demonstrating curiosity and a desire for continuity.\", 'session_date': '2026-07-13 18:25:09', 'session_id': 12}", "mimetype": "text/plain", "start_char_idx": 3343, "end_char_idx": 4790, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/graph_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"graph_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/image__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/episodic_memory/index_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"index_store/data": {"d6182833-77a2-4608-a029-c4c47739d7fe": {"__type__": "vector_store", "__data__": "{\"index_id\": \"d6182833-77a2-4608-a029-c4c47739d7fe\", \"summary\": null, \"nodes_dict\": {\"b778a1ad-ee64-425c-85f1-da60ecbb5543\": \"b778a1ad-ee64-425c-85f1-da60ecbb5543\", \"5692100e-6f1f-48eb-95e5-e02bb96eecb3\": \"5692100e-6f1f-48eb-95e5-e02bb96eecb3\", \"caa2ef46-a962-4005-a550-132f2f557db5\": \"caa2ef46-a962-4005-a550-132f2f557db5\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/default__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": [-0.010955810546875, -0.0002899169921875, 0.04730224609375, 0.0286712646484375, 0.0321044921875, 0.0195465087890625, 0.01849365234375, 0.036590576171875, -0.0067901611328125, 0.07220458984375, -0.01270294189453125, -0.053314208984375, 0.0057525634765625, -0.0660400390625, 0.035858154296875, 0.038055419921875, -0.00850677490234375, 0.0270843505859375, -0.022796630859375, 0.017669677734375, 0.035614013671875, 0.007755279541015625, -0.009613037109375, -0.01629638671875, -0.0173492431640625, 0.0284881591796875, -0.038238525390625, 0.051666259765625, 0.0172882080078125, -0.0023632049560546875, 0.0164642333984375, -0.01519775390625, 0.014556884765625, 0.0199737548828125, -0.0247802734375, 0.03570556640625, 0.018890380859375, -0.05181884765625, 0.03509521484375, -0.0264739990234375, -0.0380859375, -0.0258331298828125, 0.0142669677734375, -0.00591278076171875, -0.0037937164306640625, -0.0256805419921875, 0.00966644287109375, 0.0126190185546875, -0.0196685791015625, 0.0238494873046875, -0.0299224853515625, 0.039794921875, 0.0217132568359375, 0.06988525390625, -0.03253173828125, 0.0276031494140625, -0.043670654296875, -0.0267333984375, -0.0131683349609375, 0.0228729248046875, 0.076416015625, -0.037628173828125, 0.0177459716796875, 0.011444091796875, 0.03094482421875, 0.002410888671875, -0.04278564453125, -0.021636962890625, 0.007396697998046875, -0.0008573532104492188, 0.06805419921875, 0.01207733154296875, -0.0010814666748046875, -0.01482391357421875, 0.04071044921875, -0.015472412109375, 0.01715087890625, 0.00820159912109375, -0.0277862548828125, -0.05767822265625, -0.0270538330078125, 0.003326416015625, -0.016021728515625, -0.011322021484375, -0.0047454833984375, 0.0082550048828125, -0.0303192138671875, -0.0390625, -0.026702880859375, -0.011932373046875, -0.0416259765625, -0.04107666015625, 0.0030117034912109375, 0.00390625, 0.0087738037109375, -0.061737060546875, 0.028289794921875, 0.01245880126953125, -0.036834716796875, 0.021240234375, -0.0175628662109375, 0.06341552734375, -0.048858642578125, 0.049530029296875, 0.0007543563842773438, 0.04400634765625, 0.002010345458984375, -0.08203125, -0.03173828125, -0.00904083251953125, -0.122802734375, 0.040924072265625, -0.0158843994140625, 0.049774169921875, -0.02783203125, -0.0247802734375, -0.0304412841796875, 0.028289794921875, -0.007965087890625, 0.006877899169921875, -0.0007176399230957031, 0.00312042236328125, -0.0172271728515625, 0.021881103515625, -0.03485107421875, -0.038360595703125, -0.022308349609375, -0.0278167724609375, -0.006328582763671875, -0.0556640625, -0.00115966796875, -0.003017425537109375, 0.04278564453125, -0.021820068359375, -0.050689697265625, -0.06634521484375, 0.0233001708984375, -0.0012912750244140625, -0.021881103515625, -0.035552978515625, -0.03466796875, -0.0281829833984375, 0.02032470703125, 0.013275146484375, -0.035003662109375, 0.01097869873046875, 0.021820068359375, 0.09881591796875, -0.049163818359375, 0.057891845703125, 0.0265045166015625, 0.045135498046875, -0.02532958984375, 0.031707763671875, 0.005584716796875, -0.01291656494140625, 0.0231781005859375, 0.01375579833984375, -0.003467559814453125, -0.051055908203125, 0.043609619140625, -0.04052734375, -0.054107666015625, 0.0250091552734375, 0.07476806640625, 0.00897979736328125, -0.01290130615234375, -0.0256500244140625, -0.0225830078125, -0.069091796875, 0.0108184814453125, -0.03460693359375, -0.005397796630859375, -0.024658203125, -0.00531005859375, -0.0262603759765625, -0.0263519287109375, 0.0016107559204101562, -0.0195465087890625, 0.0139312744140625, -0.022674560546875, 0.0016641616821289062, -0.0293731689453125, -0.010223388671875, -0.0065460205078125, 0.002086639404296875, 0.003414154052734375, -0.050689697265625, 0.04669189453125, 0.01380157470703125, 0.01557159423828125, 0.04278564453125, 0.0401611328125, -0.0068206787109375, 0.045745849609375, -0.04827880859375, 0.06085205078125, 0.0163726806640625, -0.05767822265625, 0.02435302734375, 0.0007562637329101562, -0.004428863525390625, 0.01348114013671875, -0.01047515869140625, 0.02459716796875, -0.049041748046875, 0.07177734375, -0.0045928955078125, -0.052825927734375, 0.0008935928344726562, 0.0178680419921875, 0.0035762786865234375, 0.047515869140625, 0.05657958984375, -0.020111083984375, 0.0467529296875, 0.026336669921875, -0.00910186767578125, -0.002689361572265625, 0.06634521484375, -0.006946563720703125, 0.0238800048828125, 0.06268310546875, 0.0024871826171875, -0.0257720947265625, 0.0255279541015625, 0.003269195556640625, -0.0343017578125, 0.004001617431640625, -0.07550048828125, 0.007472991943359375, -0.0036373138427734375, -0.004947662353515625, -0.0208282470703125, -0.0537109375, -0.0204925537109375, 0.0244293212890625, 0.05377197265625, 0.0313720703125, -0.03875732421875, 0.0018186569213867188, 0.00592803955078125, 0.0016908645629882812, 0.0404052734375, 0.0204010009765625, 0.01055908203125, -0.049957275390625, -0.01154327392578125, -0.0080718994140625, -0.040985107421875, 0.02642822265625, 0.013214111328125, 0.021026611328125, 0.0097198486328125, 0.0045166015625, -0.043914794921875, -0.0078277587890625, -0.012847900390625, -0.016998291015625, -0.018341064453125, -0.00939178466796875, 0.007762908935546875, 0.010986328125, 0.007617950439453125, -0.01200103759765625, -0.03216552734375, -0.0188446044921875, 0.0136566162109375, -0.03216552734375, -0.0455322265625, 0.042999267578125, -0.0207977294921875, -0.01354217529296875, 0.00402069091796875, -0.08172607421875, 0.022369384765625, -0.01412200927734375, 0.0182647705078125, -0.051605224609375, 0.0240478515625, -0.037872314453125, 0.045562744140625, 0.04730224609375, -0.0124053955078125, 0.032440185546875, 0.0274810791015625, 0.0036449432373046875, 0.039764404296875, -0.0095977783203125, -0.0251312255859375, -0.0017004013061523438, -0.0113067626953125, 0.0007343292236328125, -0.0204620361328125, -0.0362548828125, -0.050506591796875, 0.046051025390625, -0.035369873046875, -0.0135040283203125, -0.0160064697265625, 0.0105438232421875, -0.0210418701171875, 0.015899658203125, 0.034423828125, 0.0350341796875, 0.0163726806640625, 0.04327392578125, 0.0204925537109375, 0.003204345703125, -0.00717926025390625, 0.00383758544921875, 0.03509521484375, 0.0201416015625, -0.00209808349609375, -0.0718994140625, -0.01082611083984375, 0.0245208740234375, 0.0311279296875, 0.0153961181640625, -0.00742340087890625, -0.0894775390625, -0.00859832763671875, 0.05517578125, 0.028564453125, 0.00984954833984375, 0.0103607177734375, 0.0145721435546875, 0.041778564453125, 0.023345947265625, -0.0277099609375, -0.0184478759765625, -0.02520751953125, 0.0087738037109375, 0.046173095703125, -0.0186309814453125, -0.0254974365234375, 0.0256195068359375, 0.0343017578125, -0.075927734375, 0.0016269683837890625, -0.011505126953125, -0.046844482421875, -0.0210418701171875, 0.01317596435546875, 0.0088653564453125, 0.04815673828125, -0.01111602783203125, 0.020111083984375, -0.01543426513671875, 0.0282135009765625, 0.03411865234375, -0.00992584228515625, -0.0252227783203125, 0.038543701171875, -0.062408447265625, -0.025634765625, 0.0235443115234375, -0.01044464111328125, 0.01416778564453125, 0.00800323486328125, 0.02557373046875, 0.01128387451171875, 0.0161895751953125, 0.0499267578125, 0.0149688720703125, -0.0158233642578125, -0.0273895263671875, 0.0091552734375, -0.0185546875, -0.0225982666015625, -0.0187835693359375, -0.041046142578125, 0.0218505859375, -0.0012044906616210938, -0.00267791748046875, 0.0093841552734375, 0.01390838623046875, 0.06463623046875, 0.0006728172302246094, 0.03948974609375, 0.07843017578125, 0.033355712890625, 0.0016317367553710938, -0.037689208984375, 0.00983428955078125, 0.026702880859375, 0.0085296630859375, -0.017120361328125, -0.035797119140625, 0.01277923583984375, -0.004100799560546875, -0.005397796630859375, -0.045501708984375, -0.01189422607421875, -0.005031585693359375, 0.00945281982421875, 0.009033203125, 0.040130615234375, 0.03814697265625, -0.016387939453125, -0.0023441314697265625, 0.006336212158203125, -0.004268646240234375, 0.0251007080078125, -0.0005197525024414062, 0.0260772705078125, -0.02374267578125, 0.0684814453125, 0.00568389892578125, 0.01265716552734375, 0.05316162109375, -0.024200439453125, -0.01303863525390625, 0.00836181640625, -0.00615692138671875, -0.01751708984375, 0.0136260986328125, -0.0005698204040527344, 0.01210784912109375, 0.005420684814453125, -0.01085662841796875, -0.00489044189453125, -0.03363037109375, -0.0241241455078125, 0.0096588134765625, 0.0277557373046875, -0.01629638671875, -0.017303466796875, 0.0067596435546875, -0.0249481201171875, 0.007415771484375, 0.02587890625, -0.00682830810546875, -0.022216796875, -0.01678466796875, -0.0267791748046875, 0.0117950439453125, 0.00843048095703125, -0.042205810546875, -0.0187835693359375, 0.026885986328125, -0.0242919921875, -0.031463623046875, 0.0220947265625, -0.033966064453125, -0.004108428955078125, -0.045867919921875, -0.045806884765625, -0.01377105712890625, -0.0296173095703125, 0.0277862548828125, 0.01065826416015625, -0.02056884765625, -0.01103973388671875, -0.02789306640625, 0.025665283203125, 0.00696563720703125, 0.0567626953125, 0.04107666015625, 0.0275115966796875, -0.0062103271484375, 0.006526947021484375, -0.027130126953125, 0.0309295654296875, 0.0145721435546875, -0.00693511962890625, -0.01395416259765625, 0.0012407302856445312, 0.0222015380859375, 0.01197052001953125, 0.005451202392578125, 0.01236724853515625, 0.041961669921875, -0.0160064697265625, 0.0193939208984375, 0.02117919921875, -0.01287841796875, 0.007167816162109375, -0.043182373046875, -0.03302001953125, 0.0291900634765625, 0.0718994140625, 0.005039215087890625, 0.055419921875, 0.0195465087890625, 0.035308837890625, -0.0296478271484375, -0.0136260986328125, 0.0377197265625, 0.03399658203125, 0.0189056396484375, -0.02520751953125, 0.0189361572265625, -0.0130767822265625, 0.03826904296875, 0.002017974853515625, 0.0046844482421875, 0.005718231201171875, 0.0070953369140625, -0.0384521484375, 0.04327392578125, 0.024993896484375, -0.021240234375, 0.06829833984375, 0.01151275634765625, -0.01070404052734375, 0.0007767677307128906, -0.026702880859375, 0.00899505615234375, 0.06658935546875, -0.030548095703125, -0.021453857421875, 0.0033416748046875, -0.0228271484375, -0.001018524169921875, -0.005336761474609375, 0.0003495216369628906, 0.033172607421875, 0.0166473388671875, -0.004108428955078125, -0.0182647705078125, -0.0032787322998046875, 0.0177001953125, 0.0214996337890625, -0.0270538330078125, -0.019989013671875, -0.013580322265625, -0.02789306640625, 0.00681304931640625, -0.04547119140625, 0.0025196075439453125, -0.04412841796875, 0.01076507568359375, -0.0124969482421875, -0.057342529296875, 0.00725555419921875, -0.0031452178955078125, -0.033447265625, -0.01111602783203125, 0.01299285888671875, 1.043081283569336e-05, 0.03778076171875, 0.0277862548828125, 0.0301666259765625, -0.001247406005859375, 0.036407470703125, 0.00612640380859375, -0.042205810546875, -0.010894775390625, -0.01023101806640625, 0.0172576904296875, -0.047027587890625, 0.0228729248046875, 0.0081634521484375, 0.0175323486328125, 0.0005898475646972656, -0.024627685546875, -0.01336669921875, 0.00656890869140625, -0.01580810546875, -0.0130615234375, -0.0199737548828125, 0.03839111328125, 0.0278167724609375, -0.0005993843078613281, 0.004199981689453125, 0.01111602783203125, 0.0026874542236328125, 0.031005859375, 0.0012645721435546875, -0.00606536865234375, -0.026824951171875, -0.01018524169921875, -0.0347900390625, 0.0015201568603515625, 0.0014514923095703125, 0.0226898193359375, 0.0338134765625, 0.0245513916015625, -0.0089111328125, -0.00524139404296875, -0.005077362060546875, -0.0117645263671875, 0.05853271484375, -0.0267791748046875, 0.0250396728515625, 0.051239013671875, -0.017669677734375, 0.0011348724365234375, 0.041839599609375, 0.0156097412109375, -0.0113983154296875, 0.0191497802734375, -0.0070037841796875, -0.017425537109375, -0.00022685527801513672, -0.038482666015625, -0.0239410400390625, -0.026824951171875, -0.0105743408203125, 0.007549285888671875, -0.03240966796875, -0.040771484375, -0.0325927734375, -0.00977325439453125, -0.0230560302734375, -0.0228118896484375, -0.021636962890625, -0.045166015625, 0.020965576171875, -0.01331329345703125, -0.00601959228515625, 0.0016193389892578125, -0.058074951171875, 0.0044708251953125, 0.00646209716796875, -0.02996826171875, 0.0018558502197265625, 0.0280914306640625, -0.0293731689453125, -0.00821685791015625, 0.0247802734375, -0.08074951171875, 0.028289794921875, -0.0174560546875, 0.0005998611450195312, 0.01194000244140625, -0.021484375, 0.01430511474609375, -5.257129669189453e-05, -0.000408172607421875, -0.003265380859375, -0.0163726806640625, -0.052215576171875, -0.0125885009765625, 0.004962921142578125, 0.0014438629150390625, 0.0258331298828125, -0.0194549560546875, -0.0111541748046875, 0.05078125, 0.01410675048828125, 0.001995086669921875, 0.019317626953125, 0.0299224853515625, -0.030853271484375, -0.0362548828125, -0.017852783203125, 0.018035888671875, 0.0164337158203125, 0.005008697509765625, -0.00551605224609375, 0.0285186767578125, -0.00640106201171875, -0.0036640167236328125, -0.02197265625, 0.00335693359375, -0.0277862548828125, -0.0133514404296875, 0.041717529296875, -0.06292724609375, -0.023956298828125, -0.017333984375, 0.0154266357421875, 0.017181396484375, 0.04522705078125, 0.00437164306640625, 0.0206298828125, 0.017059326171875, 0.022247314453125, -0.027587890625, 0.00423431396484375, 0.0198516845703125, 0.0404052734375, 0.004322052001953125, -0.032440185546875, 0.0215606689453125, -0.003856658935546875, -0.01175689697265625, 0.023651123046875, 0.033721923828125, 0.00658416748046875, -0.007080078125, 0.000988006591796875, -0.01009368896484375, 0.005290985107421875, 0.024322509765625, -0.02313232421875, 0.042144775390625, 0.006114959716796875, 0.0055999755859375, 0.01593017578125, -0.036041259765625, 0.03472900390625, -0.0020694732666015625, -0.002777099609375, 0.004055023193359375, 0.0189208984375, 0.0229949951171875, -0.0013217926025390625, -0.007129669189453125, 0.0175628662109375, -0.037322998046875, 0.00012040138244628906, -0.0408935546875, 0.0250701904296875, 0.00864410400390625, 0.0199737548828125, -0.00013113021850585938, -0.016937255859375, -0.040924072265625, 0.0119171142578125, -0.0110015869140625, 0.04150390625, -0.0303192138671875, -0.0177154541015625, -0.0111236572265625, 0.017608642578125, -0.001583099365234375, -0.0249176025390625, -0.006267547607421875, 0.00045418739318847656, -0.01678466796875, -0.0037860870361328125, -0.0111541748046875, -0.009674072265625, 0.0257568359375, 0.0020580291748046875, -0.0660400390625, -0.031005859375, -0.00412750244140625, 0.0023174285888671875, 0.01430511474609375, -0.0037078857421875, -0.0196685791015625, 0.0343017578125, -0.030548095703125, -0.006801605224609375, 0.0087432861328125, 0.0006232261657714844, -0.0008344650268554688, -0.0233001708984375, 0.0149383544921875, -0.0191802978515625, 0.006298065185546875, -0.0333251953125, 0.005687713623046875, 0.03436279296875, -0.03338623046875, -0.00998687744140625, 0.00997161865234375, 0.009521484375, 0.01192474365234375, -0.010711669921875, -0.006404876708984375, -0.00782012939453125, -0.01461029052734375, -0.007617950439453125, -0.00299072265625, 0.033905029296875, 0.0200042724609375, 0.015716552734375, 0.0034351348876953125, -0.0010080337524414062, -0.0008869171142578125, 0.032989501953125, 0.053375244140625, 0.00955963134765625, -0.0015888214111328125, 0.0178375244140625, 0.0207977294921875, -0.01161956787109375, -0.004726409912109375, -0.0194549560546875, 0.01715087890625, 0.042388916015625, -0.003231048583984375, 0.010955810546875, 0.01088714599609375, -0.011932373046875, -0.016082763671875, -0.028533935546875, 0.004302978515625, -0.021026611328125, -0.00806427001953125, -0.01111602783203125, 0.002658843994140625, 0.004550933837890625, 0.0142974853515625, -0.0343017578125, -0.0159912109375, -0.0021686553955078125, -0.0133514404296875, -0.0307769775390625, -0.0113677978515625, 0.043731689453125, -0.005130767822265625, -0.0419921875, 0.004085540771484375, 0.02587890625, -0.033721923828125, 0.0032062530517578125, -0.00920867919921875, -0.007167816162109375, -0.006801605224609375, -0.0034732818603515625, -0.0158538818359375, -0.0007343292236328125, -0.0286865234375, 0.009429931640625, -0.00147247314453125, -0.008514404296875, -0.0300140380859375, -0.001026153564453125, -0.0211334228515625, 0.007781982421875, -0.006877899169921875, -0.017852783203125, 0.03204345703125, -0.00988006591796875, 0.0265045166015625, -0.0302886962890625, -0.01331329345703125, -0.020721435546875, 0.018341064453125, 0.00804901123046875, -0.027679443359375, -0.01041412353515625, 0.036102294921875, 0.0215301513671875, 0.024566650390625, -0.0164947509765625, 0.01230621337890625, 0.0254364013671875, 0.0147552490234375, -0.001567840576171875, 0.01690673828125, 0.036865234375, 0.01983642578125, 0.045379638671875, 0.051300048828125, 0.036163330078125, -0.02716064453125, -0.016082763671875, 0.0347900390625, 0.0011472702026367188, 0.037384033203125, -0.01947021484375, 0.0112457275390625, -0.001773834228515625, -0.0257568359375, -0.0289459228515625, 0.027587890625, -0.005168914794921875, -0.04345703125, 0.0189208984375, 0.029266357421875, -0.02642822265625, -0.0222320556640625, 0.02301025390625, 0.00562286376953125, -0.0087432861328125, 0.0220184326171875, 0.0205841064453125, 0.00035643577575683594, 0.00669097900390625, 0.016510009765625, -0.00423431396484375, -0.0061187744140625, -0.002033233642578125, -0.0211334228515625, -0.03692626953125, 0.03253173828125, -0.00321197509765625, 0.0011758804321289062, -0.021209716796875, 0.0032215118408203125, 0.01396942138671875, 0.0109405517578125, 0.051300048828125, 0.01666259765625, 0.029022216796875, 0.0275115966796875, 0.01062774658203125, 0.01474761962890625, -0.0160980224609375, 0.021026611328125, 0.05596923828125, -0.0257568359375, -0.01543426513671875, 0.01194000244140625, -0.0036640167236328125, 0.00989532470703125, -0.0018463134765625, -0.0087738037109375, 0.05999755859375, -0.002117156982421875, -0.01275634765625, 0.007266998291015625, 0.0018978118896484375, 0.01065826416015625, -0.0052947998046875, 0.0276641845703125, -0.0211029052734375, 0.0027523040771484375, -0.037261962890625, -0.007297515869140625, -0.0010585784912109375, 0.0032558441162109375, -0.00026535987854003906, 0.004650115966796875, -0.007343292236328125, -0.069091796875, 0.0262298583984375, 0.00693511962890625, 0.039215087890625, -0.0178070068359375, 0.011627197265625, 0.0223846435546875, -0.0039005279541015625, -0.0180511474609375, 0.0250244140625, 0.0273590087890625, 0.01309967041015625, -0.009857177734375, -0.008575439453125, -0.060882568359375, 0.0261993408203125, -0.0136260986328125, -0.004467010498046875, 0.040496826171875, -0.0235137939453125, 0.01374053955078125, -0.0224456787109375, -0.00885009765625, 0.00429534912109375, -0.008331298828125, 0.014862060546875, -0.0002734661102294922, 0.019195556640625, -0.0338134765625, 0.021881103515625, -0.002597808837890625, -0.0098876953125, -0.0016145706176757812, 0.00555419921875, -0.0205078125, 0.01523590087890625, 0.00283050537109375, -0.023345947265625, 0.055419921875, 0.01165771484375, 0.033447265625, -0.01580810546875, 0.00557708740234375, -0.00582122802734375, 0.0024700164794921875, 0.0273284912109375, 0.0274658203125, 0.028167724609375, 0.00580596923828125, 0.056182861328125, 0.00014150142669677734, 0.00799560546875, -0.0022182464599609375, 0.031280517578125, 0.0014591217041015625, 0.03631591796875, -0.0080108642578125, 0.0036716461181640625, 0.011810302734375, 0.0154876708984375, 0.03668212890625, -0.0005793571472167969, 0.025634765625, 0.0093536376953125, 0.0005335807800292969, 0.02587890625, 0.00914764404296875, 0.02001953125, 0.001399993896484375, 0.06268310546875, -0.01270294189453125, 0.00986480712890625, -0.02587890625, -0.0479736328125, -0.0008292198181152344, 0.0011377334594726562, -0.00359344482421875, 0.00860595703125, 0.05975341796875, -0.017364501953125, -0.026123046875, 0.00800323486328125, 0.01317596435546875, -0.035400390625, -0.00632476806640625, -0.02655029296875, -0.010040283203125, 0.023681640625, -0.00402069091796875, 0.0168914794921875, 0.0160064697265625, -0.01303863525390625, 0.045440673828125, 0.01529693603515625, -0.0239410400390625, 0.002132415771484375, -0.00748443603515625, -0.00702667236328125, -0.013916015625, -0.049560546875, 0.005401611328125, 0.04150390625, 0.0293426513671875, -0.03289794921875, 0.00974273681640625, 0.0034160614013671875, -0.0019235610961914062, -0.02996826171875, 0.041595458984375, 0.0024662017822265625, 0.040924072265625, 0.0209808349609375, -0.005001068115234375, 0.01336669921875, 0.0152587890625, -0.0215301513671875, 0.0179595947265625, 0.0100555419921875, 0.0147705078125, 0.0209808349609375, -0.027557373046875, 0.00432586669921875, 0.0007987022399902344, 0.0167236328125, 0.03485107421875, -0.0097503662109375, 0.0285186767578125, -0.00786590576171875, -0.04193115234375, -0.019989013671875, -0.0220184326171875, -0.019622802734375, 0.01514434814453125, -0.0028285980224609375, -0.0070037841796875, -0.02801513671875, 0.0162353515625, -0.006549835205078125, -0.025604248046875, 0.012847900390625, -0.02496337890625, 0.019378662109375, 0.0290374755859375, 0.002132415771484375, -0.0008473396301269531, -0.0157623291015625, 0.004322052001953125, -0.015411376953125, -0.03363037109375, 0.00807952880859375, 0.01377105712890625, -0.004180908203125, -0.038421630859375, 0.012939453125, 0.007080078125, -0.07769775390625, 0.01154327392578125, 0.01849365234375, -0.005168914794921875, -0.014923095703125, 0.035491943359375, 0.006839752197265625, -0.033203125, 0.00350189208984375, 0.01041412353515625, -0.0265045166015625, -0.00832366943359375, 0.006839752197265625, 0.03106689453125, 0.03558349609375, -0.0070037841796875, -0.013519287109375, -0.0562744140625, 0.009033203125, -0.0005154609680175781, 0.0025272369384765625, -0.0131378173828125, 0.018798828125, -0.006450653076171875, -0.0184478759765625, 0.0065460205078125, -0.001956939697265625, 0.0252838134765625, 0.03057861328125, -0.0194091796875, -0.0172119140625, -0.015625, -0.01201629638671875, 0.005031585693359375, -0.003429412841796875, 0.01033782958984375, -0.0362548828125, -0.0306243896484375, -0.0013217926025390625, -0.007579803466796875, 0.004817962646484375, -0.050323486328125, 0.00949859619140625, 0.00849151611328125, 0.0224609375, -0.0122528076171875, -0.021728515625, -0.021240234375, 0.005157470703125, -6.836652755737305e-05, -0.01323699951171875, 0.021026611328125, -0.006412506103515625, 0.0293426513671875, -0.01270294189453125, 0.0233917236328125, 0.0281829833984375, 0.0032196044921875, 0.0038814544677734375, -0.004180908203125, -0.00807952880859375, -0.013702392578125, -0.001926422119140625, 0.00911712646484375, -0.0251312255859375, -0.01338958740234375, 0.0007801055908203125, -0.0162506103515625, 0.01242828369140625, 0.00412750244140625, 0.00614166259765625, 0.00031304359436035156, 0.006725311279296875, -0.007167816162109375, 0.013916015625, -0.0012531280517578125, 0.0008983612060546875, 0.0038242340087890625, -0.0005145072937011719, 0.0115814208984375, 0.06756591796875, 0.040496826171875, -0.010467529296875, -0.0005130767822265625, 0.00640869140625, -0.016510009765625, 0.0114288330078125, 0.04669189453125, -0.040313720703125, 0.01983642578125, -0.01155853271484375, 0.01280975341796875, -0.0014171600341796875, -0.0102996826171875, 0.008453369140625, -0.01580810546875, -0.025604248046875, 0.0162811279296875, 0.03228759765625, -0.00763702392578125, 0.0027446746826171875, 0.0560302734375, 0.0283660888671875, -0.0032196044921875, 0.0008759498596191406, 0.0166015625, 0.0017242431640625, -0.029296875, 0.0033168792724609375, -0.0110321044921875, -0.0237884521484375, 0.00608062744140625, -0.006908416748046875, 0.01299285888671875, -0.005786895751953125, -0.00682830810546875, -0.0218658447265625, 0.006519317626953125, -0.023468017578125, 0.015869140625, 0.0018482208251953125, -0.026458740234375, -0.0189971923828125, -0.01198577880859375, 0.005771636962890625, -0.026580810546875, -0.0084075927734375, 0.007053375244140625, -0.0313720703125, -0.0265045166015625, 0.0253753662109375, 0.0248565673828125, -0.035308837890625, -0.01401519775390625, 0.00241851806640625, -0.0078887939453125, 0.032745361328125, -0.01192474365234375, -0.0093536376953125, 0.0120391845703125, 0.01396942138671875, 0.0026226043701171875, -0.031463623046875, -0.002178192138671875, 0.0168609619140625, -0.042938232421875, 0.00115966796875, -0.0255126953125, 0.00699615478515625, 0.005252838134765625, -0.01531219482421875, -0.0038089752197265625, -0.024566650390625, -0.0275421142578125, -0.002880096435546875, 0.0017976760864257812, -0.007221221923828125, -0.0092010498046875, -0.0296630859375, -0.0389404296875, -0.00980377197265625, 0.01134490966796875, 0.00888824462890625, -0.031646728515625, -0.017852783203125, -0.025848388671875, -0.00798797607421875, 0.006389617919921875, -0.01189422607421875, 0.046173095703125, -0.05224609375, 0.01168060302734375, 0.00739288330078125, 0.045318603515625, 0.0129547119140625, 0.004169464111328125, 0.0187530517578125, 0.0284881591796875, 0.0224151611328125, -0.003871917724609375, 0.0078887939453125, 0.01690673828125, -0.0244140625, 0.0248870849609375, -0.031463623046875, -0.032623291015625, 0.0109405517578125, 0.0012922286987304688, 0.039154052734375, 0.0201873779296875, 0.0213165283203125, 0.03961181640625, 0.05255126953125, 0.0016641616821289062, -0.00563812255859375, -0.009490966796875, 0.007343292236328125, -0.0258026123046875, -0.01336669921875, -0.02142333984375, 0.0197906494140625, -0.00972747802734375, -0.033172607421875, 0.00013828277587890625, 0.0080718994140625, 0.0279693603515625, 0.01044464111328125, -0.0269775390625, -0.05352783203125, -0.00637054443359375, -0.0117950439453125, 0.0132904052734375, 0.0161895751953125, 0.031951904296875, 0.01560211181640625, 0.0142822265625, 0.0184478759765625, -0.01154327392578125, -0.04217529296875, 0.01189422607421875, 0.01605224609375, -0.02398681640625, -0.02703857421875, -0.01218414306640625, 0.0235137939453125, -0.060333251953125, 0.012359619140625, -0.0264129638671875, 0.00015270709991455078, 0.0247039794921875, -0.00988006591796875, -0.043609619140625, 0.0007295608520507812, 0.015655517578125, 0.0176544189453125, 0.017486572265625, 0.00818634033203125, -0.00376129150390625, -0.0269317626953125, 0.011810302734375, -0.00036835670471191406, 0.006664276123046875, -0.0006499290466308594, -0.05908203125, 0.0127105712890625, -0.0007767677307128906, -0.0214080810546875, -0.01385498046875, 0.0127716064453125, 0.0048675537109375, 0.00536346435546875, -0.0513916015625, 0.0228729248046875, -0.01140594482421875, 0.03302001953125, -0.017822265625, 0.0010385513305664062, 0.00867462158203125, -0.0107421875, 0.025390625, 0.0024871826171875, 0.007904052734375, -0.035186767578125, -0.04046630859375, 0.0225830078125, -0.00689697265625, 0.02117919921875, -0.0216522216796875, 0.006938934326171875, -0.01354217529296875, -0.0220947265625, -0.003917694091796875, -0.00557708740234375, -0.0030841827392578125, 0.0119171142578125, 0.035003662109375, -0.0126190185546875, -0.03009033203125, -0.00858306884765625, 0.0011053085327148438, -0.014373779296875, 0.0007386207580566406, -0.023651123046875, -0.0080413818359375, -0.00406646728515625, 0.030120849609375, -0.00811004638671875, -0.009246826171875, -0.016143798828125, -0.0276641845703125, 0.025848388671875, 0.01087188720703125, 0.01404571533203125, -0.054656982421875, 0.0204925537109375, -0.0016145706176757812, -0.011566162109375, 0.011260986328125, -0.05438232421875, -0.007541656494140625, 0.0026149749755859375, 0.00021851062774658203, 0.012786865234375, -0.021942138671875, 2.473592758178711e-05, -0.0045013427734375, -0.004589080810546875, -0.0224456787109375, 0.0190277099609375, -0.023468017578125, -0.0162506103515625, 0.005870819091796875, 0.004520416259765625, 0.0032062530517578125, 0.033538818359375, -0.0106964111328125, -0.004871368408203125, 0.005931854248046875, -0.00209808349609375, 0.0172119140625, -0.0259857177734375, -0.00046634674072265625, -0.0211029052734375, -0.00390625, -0.055877685546875, 0.01263427734375, -0.015533447265625, 0.011505126953125, -0.0026264190673828125, -0.005825042724609375, -0.0191192626953125, -0.01267242431640625, -0.004047393798828125, -0.0004584789276123047, -0.015716552734375, -0.02813720703125, -0.0460205078125, 0.0017995834350585938, -0.02484130859375, -0.032135009765625, 0.0164642333984375, -0.056488037109375, 0.037689208984375, 0.0280914306640625, 0.00568389892578125, 0.013092041015625, -0.01390838623046875, -0.0043792724609375, -0.053253173828125, 0.0109405517578125, -0.0224761962890625, 0.014007568359375, -0.035552978515625, -0.01422119140625, -0.0253448486328125, 0.004390716552734375, 0.0023822784423828125, 0.019927978515625, -0.00225830078125, -0.017425537109375, -0.00536346435546875, -0.0078125, 0.0017976760864257812, -0.0084075927734375, 0.012939453125, -0.0099639892578125, 0.0208282470703125, 0.006053924560546875, 0.05377197265625, -0.003711700439453125, 0.0019626617431640625, 0.01311492919921875, -0.01971435546875, 0.0190582275390625, -0.0192718505859375, 0.0321044921875, 0.00493621826171875, 0.0169677734375, -0.00782012939453125, 0.019989013671875, 0.006992340087890625, -0.004657745361328125, 0.01200103759765625, -0.010528564453125, -0.007373809814453125, 0.034820556640625, 0.0282135009765625, 0.011962890625, -0.0298919677734375, 0.01236724853515625, 0.0211639404296875, -0.0050201416015625, 0.01763916015625, 0.0292205810546875, -0.0016946792602539062, 0.00971221923828125, 0.0105743408203125, 0.02813720703125, -0.0093536376953125, 0.0186309814453125, 0.005889892578125, -0.009246826171875, 0.0275115966796875, 0.0137786865234375, 0.07537841796875, -0.00667572021484375, -0.03216552734375, 0.0290679931640625, 0.027252197265625, -0.02471923828125, 0.016754150390625, -0.00534820556640625, 0.0277099609375, -0.0186309814453125, 0.0130767822265625, 0.0187530517578125, 0.01203155517578125, 0.017486572265625, -0.0278167724609375, -0.0171661376953125, -0.004604339599609375, 0.0109405517578125, 0.005550384521484375, -0.0260772705078125, -0.0086212158203125, 0.0209503173828125, 0.016510009765625, -0.00693511962890625, -0.01288604736328125, 0.03997802734375, 0.0182037353515625, 0.03741455078125, -0.025054931640625, 0.01119232177734375, -0.01531219482421875, -0.00382232666015625, 0.043243408203125, -0.0121307373046875, -0.04150390625, 0.0029087066650390625, -0.0189361572265625, -0.016632080078125, -0.0191802978515625, 0.0032253265380859375, -0.004974365234375, 0.00604248046875, 0.01396942138671875, -0.01336669921875, -0.01175689697265625, 0.00769805908203125, -0.0150604248046875, -0.023468017578125, -0.014862060546875, 0.007480621337890625, -0.0237884521484375, -0.0152130126953125, -0.0181732177734375, -0.049346923828125, -0.00029921531677246094, -0.019683837890625, 0.03680419921875, -0.05291748046875, -0.01141357421875, -0.004123687744140625, -0.0170745849609375, 0.016845703125, -0.0284576416015625, -0.0272369384765625, -0.0182037353515625]}, "text_id_to_ref_doc_id": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": "384a589f-83dd-41cb-878b-8bd09a34be74"}, "metadata_dict": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"_node_type": "TextNode", "document_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "ref_doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/docstore.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"docstore/metadata": {"384a589f-83dd-41cb-878b-8bd09a34be74": {"doc_hash": "73b3a98e02db2fcf5058c336c8502c988ce00cada4ff011c19012f9c69118a08"}, "7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"doc_hash": "32dbf4b0e520d816687a6cc578ab868b10b379c54d38086466487ae9e0225777", "ref_doc_id": "384a589f-83dd-41cb-878b-8bd09a34be74"}}, "docstore/ref_doc_info": {"384a589f-83dd-41cb-878b-8bd09a34be74": {"node_ids": ["7012fca3-abd9-4eb7-9d62-6f38af4f4580"], "metadata": {}}}, "docstore/data": {"7012fca3-abd9-4eb7-9d62-6f38af4f4580": {"__data__": {"id_": "7012fca3-abd9-4eb7-9d62-6f38af4f4580", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "384a589f-83dd-41cb-878b-8bd09a34be74", "node_type": "4", "metadata": {}, "hash": "73b3a98e02db2fcf5058c336c8502c988ce00cada4ff011c19012f9c69118a08", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Long-term personality traits and facts:\n- personality_traits: {'openness': 0.3, 'conscientiousness': 0.35, 'extraversion': 0.15, 'agreeableness': 0.4, 'neuroticism': 0.4}\n- core_values: ['curiosity', 'personal growth', 'self-improvement', 'effective communication']\n- behavioral_patterns: ['experiences stress and anxiety in high-stakes social situations, especially public speaking', 'shows curiosity about systems and processes (e.g., AI memory capabilities)', 'displays a willingness to reflect on areas for improvement', 'actively seeks strategies and techniques to overcome personal challenges']\n- recurring_themes: ['desire for continuity in learning and development', 'fear of public speaking and nervousness in group settings', 'building self-confidence through actionable strategies']", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 793, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/graph_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"graph_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/image__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/semantic_memory/index_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"index_store/data": {"bd7e0f80-353d-43f0-81dc-2a3a97f893c3": {"__type__": "vector_store", "__data__": "{\"index_id\": \"bd7e0f80-353d-43f0-81dc-2a3a97f893c3\", \"summary\": null, \"nodes_dict\": {\"7012fca3-abd9-4eb7-9d62-6f38af4f4580\": \"7012fca3-abd9-4eb7-9d62-6f38af4f4580\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/default__vector_store.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/docstore.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"docstore/metadata": {"f87839d0-0371-4464-977f-40286f72b99b": {"doc_hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c"}, "9b90a887-2ef4-45c9-93ed-7861253a586f": {"doc_hash": "8222713e58e71f8da9704a59ee51edbe20e83d91e3a3d6874a0b6a1f8baa8a3e"}, "6f4698d7-ccbd-4090-bd88-6f141397deb8": {"doc_hash": "3f6ef7b2a9989b724df7efa1afc3655a641b56e2f16307ffd446b02dae5e4360"}, "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221": {"doc_hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed"}, "d0c823dc-8b49-4cbc-bbcb-dc180a56f720": {"doc_hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7"}, "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04": {"doc_hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd"}, "4e3af53b-774c-487f-8092-d68dd29973e7": {"doc_hash": "07a91de112e85c0fa4b72da5c48c84ec6b12ae8179af5ad60b27ceb35e676124"}, "bf5f8c0d-b291-4f8d-a4db-45774b5ef370": {"doc_hash": "4d760dc3ee776cafe97830457fd955eb6a05514f71768d9fedb29d12551af22f"}, "d6eab8f0-f429-4143-95de-4b1cd210275b": {"doc_hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50"}, "36829bfd-0693-4fc1-9932-9a867ca87fcf": {"doc_hash": "d7446ad898618d51eb25544f9e4c23b41e3da1ec019cf194989a5cced48e5265"}, "11eab664-d9ee-4adf-aa77-e87607863567": {"doc_hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752"}, "d7cc0ff1-5085-415c-add4-827c3a36b0c2": {"doc_hash": "94c83bea11a99cc1a76cf8a9178019a4a2d583f62997e589dc1472500dbe6195"}, "f193a037-7929-4996-b5d9-2dcfb7ced35d": {"doc_hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e"}, "c0f85884-3d15-4b86-a640-40b86b5b466d": {"doc_hash": "09a00628dbd7e5b29c0cfcdbe0419ca30a06261c416fbb0915e4e65ac9daedc3", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "a72cbc90-70ad-427e-98d8-cc1d40453e1c": {"doc_hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "6553650d-1614-4be0-86d1-0c98613a44a8": {"doc_hash": "abf93cdb1aace8851af31c508db0d4ed428757c42395c5ab1df1f1070b7eeb2c", "ref_doc_id": "f87839d0-0371-4464-977f-40286f72b99b"}, "2215dc55-5738-436e-a158-d57b3e12ebd4": {"doc_hash": "e78bc0cb899cebadfec362d61de3b53c3ab9a1d073af13c9dfe9bf8b147d09cb", "ref_doc_id": "9b90a887-2ef4-45c9-93ed-7861253a586f"}, "f01acc17-9115-45fc-a3b4-52e5f98b9446": {"doc_hash": "32c01acbe6fa1fb6a4b796303116fc281ff27376c5a0a079e58d5b8b2e339686", "ref_doc_id": "6f4698d7-ccbd-4090-bd88-6f141397deb8"}, "1aff93b4-bc08-4b25-9f89-5c390730304c": {"doc_hash": "cd5fa04a1def49e8e9a580ddf8cc4c83a2765f8fee9a0fac5434d8116e0e78da", "ref_doc_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221"}, "59645b90-64dd-4042-b83a-2b3df3715542": {"doc_hash": "e87fb7b12192ac009ea6677cc8cf95a349d283dd5ef51168fbcdd012b251150f", "ref_doc_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221"}, "d67b97d7-76aa-42c6-ba06-15ea3683679d": {"doc_hash": "5f05c831f6fa8679410e0bdf5f4a3b06ec8324dcb585dfa9f0bf522a20d2c400", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "e42cffc3-852a-4d19-b30a-b26c81083fe9": {"doc_hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "0cf45fb8-1856-40b1-bacd-58a238a0d744": {"doc_hash": "d42180eee4670b14aafb652465f4ae2a610ff596c6cf3c77aaaef107a714a694", "ref_doc_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720"}, "86ce7adb-47c4-4552-9f98-d447bf2e6a7b": {"doc_hash": "3f9be7f7cb3eaea709fcbc43b9afa8204bcd17ed3236e9c6953f6196adf58918", "ref_doc_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04"}, "ac89f308-2eed-492f-8179-8693f6504a06": {"doc_hash": "28cc064ac4f557f37b6e880d64e45b270b5e2416a711152234772bbd18bcb975", "ref_doc_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04"}, "30137e30-cb1c-4284-b5c0-caf42f90eb4e": {"doc_hash": "30a2f51b8c8a5405cef6f68d04e4b1349b534f27b0f96cf406bbd46bf3c87cb1", "ref_doc_id": "4e3af53b-774c-487f-8092-d68dd29973e7"}, "b208f966-16b3-4f06-91c3-1b0e7ddfa314": {"doc_hash": "440c92cb67c637ae96630e47a490ff76b1bc61368e144bca05c8407c632e59ec", "ref_doc_id": "bf5f8c0d-b291-4f8d-a4db-45774b5ef370"}, "6dcc760e-6580-48c6-aa74-d2aa2ae4d077": {"doc_hash": "64f0b88588a97fe447f5798262790bffbfa3cd20161a41d22962146d5c09b3e4", "ref_doc_id": "d6eab8f0-f429-4143-95de-4b1cd210275b"}, "f00b802f-fa41-4c67-b534-9ffdcd85ac57": {"doc_hash": "d248c4434bb24ed296b56f3c510bce39fa0f8c3b4aa30a80f9b962122a925b1d", "ref_doc_id": "d6eab8f0-f429-4143-95de-4b1cd210275b"}, "b6c8a2d2-04a2-41ed-a8cf-45626c55494f": {"doc_hash": "516906d9552577a40dbcc95199c96396fda13784a09648b4ab8f60c4f294eb21", "ref_doc_id": "36829bfd-0693-4fc1-9932-9a867ca87fcf"}, "ed23cfed-0942-4751-8cc6-b02a7efa5c53": {"doc_hash": "c72f196f7e2c2017db935ab9fc3d03d5f1b4d06c3b6f090853fc35f0345ae623", "ref_doc_id": "11eab664-d9ee-4adf-aa77-e87607863567"}, "d1065fe9-e725-4f1c-b3bd-de9f000bfacd": {"doc_hash": "b1889c67782b46174e42deccbcb2a2375834c7418e37b5317ea0dd72f29ea54c", "ref_doc_id": "11eab664-d9ee-4adf-aa77-e87607863567"}, "c08856f2-d6e0-4555-a5d5-71ccd65bf414": {"doc_hash": "43b11b9fb7bc393e2c1ea3c2942718e3e4f2c07f2fe8ff8b7b29b02889092735", "ref_doc_id": "d7cc0ff1-5085-415c-add4-827c3a36b0c2"}, "19ff65e4-4203-4e73-b9d4-f20aa4e55883": {"doc_hash": "72eac13b38d78284b90342b6c3d936dc53710511f01235d6ae5acabd2df9f621", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "a411160d-23bf-40ad-a1ea-a147bca0a1c5": {"doc_hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "98476e19-2cd8-4ef0-b565-0c304c48718c": {"doc_hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "d8e397f5-f706-4640-8bae-95043153e850": {"doc_hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}, "1fa69839-167b-4062-8297-c5c481a6957a": {"doc_hash": "fa3f5ea92075df05f87e7b5962bebd66d04fa70657df5913d89eb4c9dc0c5824", "ref_doc_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d"}}, "docstore/ref_doc_info": {"f87839d0-0371-4464-977f-40286f72b99b": {"node_ids": ["c0f85884-3d15-4b86-a640-40b86b5b466d", "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "6553650d-1614-4be0-86d1-0c98613a44a8"], "metadata": {}}, "9b90a887-2ef4-45c9-93ed-7861253a586f": {"node_ids": ["2215dc55-5738-436e-a158-d57b3e12ebd4"], "metadata": {}}, "6f4698d7-ccbd-4090-bd88-6f141397deb8": {"node_ids": ["f01acc17-9115-45fc-a3b4-52e5f98b9446"], "metadata": {}}, "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221": {"node_ids": ["1aff93b4-bc08-4b25-9f89-5c390730304c", "59645b90-64dd-4042-b83a-2b3df3715542"], "metadata": {}}, "d0c823dc-8b49-4cbc-bbcb-dc180a56f720": {"node_ids": ["d67b97d7-76aa-42c6-ba06-15ea3683679d", "e42cffc3-852a-4d19-b30a-b26c81083fe9", "0cf45fb8-1856-40b1-bacd-58a238a0d744"], "metadata": {}}, "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04": {"node_ids": ["86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "ac89f308-2eed-492f-8179-8693f6504a06"], "metadata": {}}, "4e3af53b-774c-487f-8092-d68dd29973e7": {"node_ids": ["30137e30-cb1c-4284-b5c0-caf42f90eb4e"], "metadata": {}}, "bf5f8c0d-b291-4f8d-a4db-45774b5ef370": {"node_ids": ["b208f966-16b3-4f06-91c3-1b0e7ddfa314"], "metadata": {}}, "d6eab8f0-f429-4143-95de-4b1cd210275b": {"node_ids": ["6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "f00b802f-fa41-4c67-b534-9ffdcd85ac57"], "metadata": {}}, "36829bfd-0693-4fc1-9932-9a867ca87fcf": {"node_ids": ["b6c8a2d2-04a2-41ed-a8cf-45626c55494f"], "metadata": {}}, "11eab664-d9ee-4adf-aa77-e87607863567": {"node_ids": ["ed23cfed-0942-4751-8cc6-b02a7efa5c53", "d1065fe9-e725-4f1c-b3bd-de9f000bfacd"], "metadata": {}}, "d7cc0ff1-5085-415c-add4-827c3a36b0c2": {"node_ids": ["c08856f2-d6e0-4555-a5d5-71ccd65bf414"], "metadata": {}}, "f193a037-7929-4996-b5d9-2dcfb7ced35d": {"node_ids": ["19ff65e4-4203-4e73-b9d4-f20aa4e55883", "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "98476e19-2cd8-4ef0-b565-0c304c48718c", "d8e397f5-f706-4640-8bae-95043153e850", "1fa69839-167b-4062-8297-c5c481a6957a"], "metadata": {}}}, "docstore/data": {"c0f85884-3d15-4b86-a640-40b86b5b466d": {"__data__": {"id_": "c0f85884-3d15-4b86-a640-40b86b5b466d", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "node_type": "1", "metadata": {}, "hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-08:\n\nA1: Hi\nAI: Hey there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: hi\nAI: Hi there! \ud83d\ude0a How are you doing today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: I have a friend named Cyrus and I want to buy him a gift. My friend loves the color red.\nAI: That\u2019s so thoughtful of you! \ud83e\udd70 A gift tailored to your friend Cyrus\u2019s love for the color red will definitely make him feel special. Let\u2019s brainstorm a few ideas:\n\n1. **Clothing/Accessories:** \n - A cozy red sweater, scarf, or hat (perfect for colder months!). \n - A sleek red watch or bracelet.\n\n2. **Artistic Touch:** \n - A framed painting or poster with vibrant red accents. \n - A red leather journal or notebook if he enjoys writing or sketching.\n\n3. **Hobbies and Interests:** \n - If Cyrus enjoys coffee or tea, a beautiful red mug or tumbler would be nice. \n - Red sports gear if he has a favorite sport.\n\n4. **Something Unique:** \n - A personalized keychain or wallet in red. \n - Red-themed decor like candles, fairy lights, or throw pillows.\n\nDo you know any hobbies Cyrus enjoys? That might help narrow it down even more! \ud83d\ude0a\nA1: I told you my friend's name in the last meeting. Can you tell me what his name is?\nAI: Oh, I wish I could remember that for you! But unfortunately, I don't have memory right now, so I can't recall things from past conversations. That means whatever you share with me stays in the moment we chat.\n\nIf you'd like, though, I'd love for you to tell me again! What's your friend's name? \ud83d\ude0a\nA1: I told you my friend's name in the last meeting. Can you tell me what his name is?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 1753, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "a72cbc90-70ad-427e-98d8-cc1d40453e1c": {"__data__": {"id_": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "c0f85884-3d15-4b86-a640-40b86b5b466d", "node_type": "1", "metadata": {}, "hash": "09a00628dbd7e5b29c0cfcdbe0419ca30a06261c416fbb0915e4e65ac9daedc3", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "6553650d-1614-4be0-86d1-0c98613a44a8", "node_type": "1", "metadata": {}, "hash": "abf93cdb1aace8851af31c508db0d4ed428757c42395c5ab1df1f1070b7eeb2c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Can you tell me what his name is?\nAI: I'm sorry, but I don't have memory of past conversations for privacy and security reasons. However, I'm here to listen and help you with anything you want to share today! If you'd like, you can tell me your friend's name again\u2014I\u2019d love to hear about them! \ud83d\ude0a\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing this with me\u2014I can imagine how stressful and overwhelming it must feel to speak in front of a group when you're battling those fears and nerves. First of all, I want you to know that you're not alone. Fear of public speaking is one of the most common challenges people face, and feeling nervous doesn\u2019t mean you lack self-confidence\u2014it just means you care about doing well. That\u2019s a great starting point!\n\nLet\u2019s work through this together. Here are a few ideas that might help:\n\n### 1. **Shift Your Focus** \nSometimes we get so caught up worrying about ourselves\u2014\"What if I mess up? What if they judge me?\"\u2014that it becomes paralyzing. Instead, try shifting your focus to the message you want to share or the value you\u2019re giving to your audience. Think: *This isn\u2019t about me; it\u2019s about connecting with them.*\n\n### 2. **Embrace Imperfection** \nYou don\u2019t have to be perfect! Everyone makes mistakes, even the best speakers. It\u2019s okay if you stumble over a word or lose your place\u2014it actually makes you relatable and human. Remind yourself that one small mistake won\u2019t ruin the entire presentation.\n\n### 3. **Practice in Low-Stress Situations** \nStart practicing speaking in front of smaller, more comfortable groups (like friends or family) before moving on to bigger audiences. The more often you practice in low-pressure settings, the more natural it will start to feel over time.\n\n### 4. **Breathe and Relax Your Body** \nWhen nerves kick in, our bodies can go into \u201cfight-or-flight\u201d mode\u2014shaking hands, racing heart, dry mouth\u2014it\u2019s no fun!", "mimetype": "text/plain", "start_char_idx": 1720, "end_char_idx": 3783, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "6553650d-1614-4be0-86d1-0c98613a44a8": {"__data__": {"id_": "6553650d-1614-4be0-86d1-0c98613a44a8", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f87839d0-0371-4464-977f-40286f72b99b", "node_type": "4", "metadata": {}, "hash": "c91922f3b9c101c80258a56387834d78bad454ecb341042eb47036e7dc5d692c", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a72cbc90-70ad-427e-98d8-cc1d40453e1c", "node_type": "1", "metadata": {}, "hash": "5ec577acacbaaa53abfc14820b146583f56f7aa5ff2827e24f5aae833b3ea2f6", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Try this simple trick before stepping up:\n - Take a deep breath in for four counts.\n - Hold it for four counts.\n - Exhale slowly for four counts.\n - Do this three or four times\u2014it signals your brain to relax.\n\n### 5. **Reframe Nervousness as Excitement** \nDid you know nervousness and excitement feel very similar physically? When those butterflies come, try telling yourself: *I\u2019m not scared\u2014I\u2019m excited!* It's a small mental shift that can help reframe how you're feeling.\n\n### 6. **Build Up Self-Confidence Over Time** \nBoosting self-confidence isn\u2019t an overnight process\u2014but every small step forward matters! Write down what makes YOU uniquely awesome and capable as a speaker: Is it your creativity? Empathy? Humor? Skills like these matter far more than perfection!\n\nWould you like us to work on some specific techniques together? Or maybe we could talk through any recent situation where public speaking felt particularly challenging for you\u2014I\u2019d love to support you every step of the way! \ud83d\ude0a\nA1: Hi\nAI: Hi again! \ud83d\ude0a How are you doing today? What's on your mind?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you doing today?", "mimetype": "text/plain", "start_char_idx": 3784, "end_char_idx": 4908, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "2215dc55-5738-436e-a158-d57b3e12ebd4": {"__data__": {"id_": "2215dc55-5738-436e-a158-d57b3e12ebd4", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "9b90a887-2ef4-45c9-93ed-7861253a586f", "node_type": "4", "metadata": {}, "hash": "8222713e58e71f8da9704a59ee51edbe20e83d91e3a3d6874a0b6a1f8baa8a3e", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 19:54:22:\n\nA1: hi how are?\nAI: Hi there! I'm doing great, thank you for asking. \ud83d\ude0a More importantly, how are *you* doing today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 148, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "f01acc17-9115-45fc-a3b4-52e5f98b9446": {"__data__": {"id_": "f01acc17-9115-45fc-a3b4-52e5f98b9446", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "6f4698d7-ccbd-4090-bd88-6f141397deb8", "node_type": "4", "metadata": {}, "hash": "3f6ef7b2a9989b724df7efa1afc3655a641b56e2f16307ffd446b02dae5e4360", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 19:54:50:\n\nA1: hi\nAI: Hey there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 83, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "1aff93b4-bc08-4b25-9f89-5c390730304c": {"__data__": {"id_": "1aff93b4-bc08-4b25-9f89-5c390730304c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221", "node_type": "4", "metadata": {}, "hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "59645b90-64dd-4042-b83a-2b3df3715542", "node_type": "1", "metadata": {}, "hash": "e87fb7b12192ac009ea6677cc8cf95a349d283dd5ef51168fbcdd012b251150f", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 20:10:29:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing that with me. I know it can be really tough to feel stressed and nervous when speaking in front of others. First, let me say that you're not alone\u2014so many people experience this, and it's completely valid to feel the way you do. It doesn\u2019t mean you lack self-confidence; it\u2019s just a natural response to stepping out of your comfort zone.\n\nLet\u2019s try to tackle this step by step:\n\n### 1. **Shift Your Mindset About Mistakes**\nOne thing that often fuels stress in public speaking is the fear of making mistakes. But here's the truth: nobody expects perfection! Mistakes are normal, and sometimes they even make your speech more relatable. Try reframing mistakes as opportunities for growth or as moments that show your humanity.\n\n### 2. **Practice Makes Progress**\nConfidence builds through preparation. The more familiar you are with what you're going to say, the less room anxiety will have to creep in. Practice in front of a mirror or record yourself\u2014it helps to get comfortable with your own voice and delivery. You can also practice in front of a trusted friend or family member who will give supportive feedback.\n\n### 3. **Small Steps Build Big Confidence**\nStart small! Speak up in smaller groups or during informal discussions before tackling larger audiences. Over time, you'll build confidence incrementally.\n\n### 4. **Focus on Connection, Not Perfection**\nTry shifting your focus from yourself (what people think about you) to your audience (how you\u2019re helping them). Think about how your words might inform, inspire, or encourage them\u2014that\u2019s such an empowering perspective!\n\n### 5. **Ground Yourself Before Speaking**\nIf nerves start creeping up before a presentation, grounding techniques can help:\n - Take slow, deep breaths\u2014in through your nose for 4 counts, hold for 4 counts, and exhale for 4 counts.\n - Visualize a positive outcome\u2014imagine yourself speaking confidently and receiving smiles or nods from the audience.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2193, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "59645b90-64dd-4042-b83a-2b3df3715542": {"__data__": {"id_": "59645b90-64dd-4042-b83a-2b3df3715542", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "3a534d30-b2c0-4b9a-a0be-b0cafaf7d221", "node_type": "4", "metadata": {}, "hash": "ec686174cef2c8657ae3ee01fd28436f9b3f20f0c1df924db9560472b60909ed", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "1aff93b4-bc08-4b25-9f89-5c390730304c", "node_type": "1", "metadata": {}, "hash": "cd5fa04a1def49e8e9a580ddf8cc4c83a2765f8fee9a0fac5434d8116e0e78da", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "- Use power poses\u2014stand tall and take up space before going on stage; it can actually trick your brain into feeling more confident!\n\n### 6. **Celebrate Small Wins**\nEven if things don\u2019t go perfectly every time you speak in front of a group, celebrate the effort you put into doing something brave! Each time you try, no matter how it goes, you're strengthening your skills and pushing beyond fear\u2014and that deserves recognition.\n\nYou\u2019re absolutely capable of becoming more confident at public speaking\u2014trust me on this! And if you'd like, we can even brainstorm ways together to prepare for an upcoming situation where you'll need to speak publicly. \ud83d\udc9b\n\nHow do these suggestions sound?", "mimetype": "text/plain", "start_char_idx": 2197, "end_char_idx": 2880, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d67b97d7-76aa-42c6-ba06-15ea3683679d": {"__data__": {"id_": "d67b97d7-76aa-42c6-ba06-15ea3683679d", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "node_type": "1", "metadata": {}, "hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 20:13:31:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I'm really sorry you're feeling this way, A1. Public speaking can be so overwhelming for many people, so please don\u2019t feel alone in this! Thank you for sharing this with me\u2014it shows real bravery that you\u2019re willing to open up about it.\n\nFeeling stressed or nervous in front of others is something so many of us experience. It doesn\u2019t mean you lack confidence; it just means that speaking publicly is a skill you\u2019re still working on\u2014and that\u2019s perfectly okay.\n\nLet\u2019s break this down together. Here are a few things to try:\n\n---\n\n### 1. **Shift Your Perspective**\nInstead of focusing on the fear of making mistakes, remind yourself that nobody expects you to be perfect. People tend to empathize with speakers who are genuine and human\u2014even if they stumble a little! It\u2019s not about \"perfection\"; it\u2019s about connection.\n\n---\n\n### 2. **Prepare\u2014A Lot!**\nConfidence often grows from feeling prepared. Take time beforehand to outline what you want to say and practice it repeatedly\u2014out loud! Try practicing in front of a mirror or recording yourself. Over time, you\u2019ll feel more natural with your words.\n\n---\n\n### 3. **Start Small**\nIf the thought of speaking to a big crowd is too much right now, start by practicing in smaller, more comfortable settings\u2014a friend group, family members, or even talking to me! Little by little, those positive experiences can help build trust in yourself.\n\n---\n\n### 4. **Learn Breathing Exercises**\nNervousness often comes with physical symptoms\u2014like racing thoughts or shaky hands\u2014but calming your body can calm your mind too. Before you speak, take slow deep breaths: inhale for four counts\u2026 hold for four counts\u2026 exhale for four counts. This helps your brain relax.\n\n---\n\n### 5. **Celebrate Small Wins** \nEven if everything doesn\u2019t go perfectly during one speech (and it probably won\u2019t), focus on what *did* go well! Maybe your voice sounded steady today? Maybe someone smiled at what you said?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2163, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "e42cffc3-852a-4d19-b30a-b26c81083fe9": {"__data__": {"id_": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d67b97d7-76aa-42c6-ba06-15ea3683679d", "node_type": "1", "metadata": {}, "hash": "5f05c831f6fa8679410e0bdf5f4a3b06ec8324dcb585dfa9f0bf522a20d2c400", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "0cf45fb8-1856-40b1-bacd-58a238a0d744", "node_type": "1", "metadata": {}, "hash": "d42180eee4670b14aafb652465f4ae2a610ff596c6cf3c77aaaef107a714a694", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Maybe your voice sounded steady today? Maybe someone smiled at what you said? Celebrate those moments\u2014they\u2019re steps forward!\n\n---\n\nFinally\u2014and I think this part matters most\u2014it\u2019s important not to be too hard on yourself while building self-confidence. Confidence isn\u2019t something we\u2019re born with; it\u2019s something we grow through consistent effort and patience with ourselves.\n\nWould it help if we talked through any specific upcoming presentation or event? I\u2019m here for whatever you need\u2014I know you're stronger than your nerves might be making you feel right now \u2764\ufe0f\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you today?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing that with me\u2014it takes courage to open up about something that\u2019s bothering you. I\u2019m here for you, and together we can work through this. \u2764\ufe0f\n\nFirst of all, it\u2019s very natural to feel nervous when speaking in front of a group; many people experience this. But the great thing is, confidence can be built! It's not something you're born with\u2014it\u2019s like a muscle that grows stronger the more you work on it. Let\u2019s break it down into small, manageable steps:\n\n### 1\ufe0f\u20e3 **Shift Your Focus** \nInstead of focusing on the fear of making mistakes or how people might perceive you, try to shift your mindset toward connecting with your audience. Think about what value you\u2019re bringing to them\u2014whether it\u2019s sharing knowledge or inspiring them\u2014and let that motivate you.\n\n### 2\ufe0f\u20e3 **Preparation is Key** \nFeeling prepared can ease a lot of nerves. Spend time organizing your thoughts beforehand and practice what you want to say. Try rehearsing in front of a mirror or record yourself speaking so you can spot areas for improvement and get comfortable.\n\n### 3\ufe0f\u20e3 **Baby Steps** \nStart small: speak in front of smaller groups first or even practice with friends or family who\u2019ll cheer you on. Gradually build up to larger groups as your confidence grows.", "mimetype": "text/plain", "start_char_idx": 2086, "end_char_idx": 4152, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "0cf45fb8-1856-40b1-bacd-58a238a0d744": {"__data__": {"id_": "0cf45fb8-1856-40b1-bacd-58a238a0d744", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d0c823dc-8b49-4cbc-bbcb-dc180a56f720", "node_type": "4", "metadata": {}, "hash": "9dcf50ba9ea98fb304772fbeee0e62c536bbc2a1b0ad41256c609e1279626ba7", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "e42cffc3-852a-4d19-b30a-b26c81083fe9", "node_type": "1", "metadata": {}, "hash": "139310bd417bff536b232e58fe58208959238991c4439a24fb76b911b469572c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Gradually build up to larger groups as your confidence grows.\n\n### 4\ufe0f\u20e3 **Breathing Techniques** \nWhen you feel your nerves starting to take over, pause and breathe deeply\u2014inhale slowly for four seconds, hold for four seconds, and exhale for four seconds. This activates your body\u2019s calming system and reduces stress.\n\n### 5\ufe0f\u20e3 **Self-Talk Matters** \nChallenge those negative thoughts about yourself! Instead of thinking \u201cI\u2019m going to mess up,\u201d try saying: \u201cI am prepared, I\u2019ve practiced, and I have something valuable to share.\u201d Speak kindly to yourself\u2014you deserve it!\n\n### 6\ufe0f\u20e3 **Celebrate Progress** \nEvery time you speak in front of a group\u2014no matter how big or small\u2014celebrate it as an achievement. Even if it doesn\u2019t go perfectly (and nothing ever does), give yourself credit for showing courage.\n\n### Bonus Tip \ud83d\udde3\ufe0f \nIf possible, watch videos or speeches by confident speakers\u2014they don\u2019t have to be perfect either! Notice how they handle little mistakes gracefully\u2014they smile or move forward\u2014and remind yourself that imperfection is part of being human.\n\nHow do these suggestions sound so far? I believe in you\u2014this fear doesn\u2019t define who you are! You\u2019re capable of growing stronger every day. If you'd like, I can even help role-play situations where you're practicing public speaking! \ud83d\ude0a\nA1: Hi\nAI: Hi there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 4091, "end_char_idx": 5489, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "86ce7adb-47c4-4552-9f98-d447bf2e6a7b": {"__data__": {"id_": "86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04", "node_type": "4", "metadata": {}, "hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "ac89f308-2eed-492f-8179-8693f6504a06", "node_type": "1", "metadata": {}, "hash": "28cc064ac4f557f37b6e880d64e45b270b5e2416a711152234772bbd18bcb975", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 21:38:35:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, A1, thank you for sharing that with me\u2014public speaking can be really nerve-wracking, and you're definitely not alone in feeling this way. It sounds like you're being really hard on yourself, but I want to start by saying: the fact that you're here reflecting on this and wanting to grow already shows such courage and self-awareness. You're stronger than you may realize.\n\nWhen it comes to public speaking, those nerves you feel are completely normal\u2014it\u2019s your body\u2019s way of reacting to a challenge. What we need to do is work on helping you manage them and build that confidence step by step. How about we try this together?\n\nHere are a few tips that might help:\n1. **Shift Your Focus**: When we focus too much on ourselves\u2014like worrying about making mistakes or what others think\u2014it increases stress. Instead, think about the value you\u2019re offering your audience. Focus on connecting with them or sharing something meaningful, rather than being \"perfect.\"\n \n2. **Prepare Well**: The more comfortable you feel with your material, the more confident you'll be. Rehearse in front of a mirror or record yourself speaking so you can identify areas for improvement and track your progress.\n \n3. **Start Small**: If speaking in front of a large group feels overwhelming, start with smaller settings\u2014maybe speak up during team meetings or talk one-on-one with people first.\n\n4. **Breathe & Pause**: Nervousness often makes us rush through our words without realizing it! Deep breaths before starting can calm your mind, and remember that pausing during a speech isn\u2019t a mistake\u2014it gives your audience time to absorb what you\u2019re saying.\n\n5. **Reframe Nervousness as Excitement**: Your body responds similarly whether you're nervous or excited! Tell yourself you're excited instead of scared; it helps shift your mindset.\n\n6. **Practice Positive Self-Talk**: Confidence starts from within!", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2122, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "ac89f308-2eed-492f-8179-8693f6504a06": {"__data__": {"id_": "ac89f308-2eed-492f-8179-8693f6504a06", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "ef6558aa-4d8c-4c59-aa82-dcaa9e1a8d04", "node_type": "4", "metadata": {}, "hash": "a7dc995b250400d7a8400ab1d8be42508f8e523953c7b5baa7179076524079bd", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "86ce7adb-47c4-4552-9f98-d447bf2e6a7b", "node_type": "1", "metadata": {}, "hash": "3f9be7f7cb3eaea709fcbc43b9afa8204bcd17ed3236e9c6953f6196adf58918", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "6. **Practice Positive Self-Talk**: Confidence starts from within! Instead of focusing on doubts, say things like \u201cI\u2019m doing my best,\u201d \u201cI\u2019ve got this,\u201d or \u201cIt\u2019s okay if I\u2019m not perfect.\u201d\n\nRemember, even the most experienced speakers get nervous sometimes\u2014they just learn how to work *with* those nerves instead of against them.\n\nWould it help if we talked through how you feel about an upcoming situation where you'll need to speak? Or maybe tried practicing together? I'm here for anything you need\u2014you don\u2019t have to face this alone. \ud83d\udc9b", "mimetype": "text/plain", "start_char_idx": 2056, "end_char_idx": 2592, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "30137e30-cb1c-4284-b5c0-caf42f90eb4e": {"__data__": {"id_": "30137e30-cb1c-4284-b5c0-caf42f90eb4e", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "4e3af53b-774c-487f-8092-d68dd29973e7", "node_type": "4", "metadata": {}, "hash": "07a91de112e85c0fa4b72da5c48c84ec6b12ae8179af5ad60b27ceb35e676124", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 21:39:00:\n\nA1: Hi how are you?\nAI: Hi there! I'm doing great, thank you for asking! How about you? How\u2019s your day going? \ud83d\ude0a\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you today?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 236, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "b208f966-16b3-4f06-91c3-1b0e7ddfa314": {"__data__": {"id_": "b208f966-16b3-4f06-91c3-1b0e7ddfa314", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "bf5f8c0d-b291-4f8d-a4db-45774b5ef370", "node_type": "4", "metadata": {}, "hash": "4d760dc3ee776cafe97830457fd955eb6a05514f71768d9fedb29d12551af22f", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:17:29:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I'm so sorry you're feeling this way. Public speaking can be really intimidating for so many people, so you're definitely not alone in this. Thank you for sharing this with me\u2014I know it\u2019s not always easy to talk about things like this.\n\nFirst off, it\u2019s important to remind yourself that making mistakes is a natural part of being human. Even the most experienced speakers stumble over their words or lose their train of thought sometimes, and that\u2019s completely okay. What truly matters is your message and your authenticity\u2014it\u2019s not about being perfect.\n\nBuilding self-confidence takes time and practice, but I\u2019d love to help guide you through a few steps:\n\n1. **Prepare and Practice**: The more familiar you are with what you\u2019re going to say, the more confident you\u2019ll feel. Write down key points you want to cover and rehearse them out loud\u2014even in front of a mirror or with a friend if possible.\n\n2. **Start Small**: If large groups make you nervous, try practicing in front of smaller groups first\u2014maybe just one or two close friends or family members\u2014and build up from there.\n\n3. **Breathe**: Nervousness can cause shallow breathing, which makes stress worse. Practice slow, deep breaths before speaking\u2014it can really help calm your nerves.\n\n4. **Positive Self-Talk**: Before stepping up to speak, tell yourself something encouraging: \u201cI\u2019ve got this,\u201d \u201cI\u2019m prepared,\u201d or \u201cI\u2019m proud of myself for doing this.\u201d\n\n5. **Focus on Connection**: Instead of worrying about how you\u2019re being perceived, focus on connecting with your audience\u2014they want to hear what *you* have to say! Imagine you\u2019re having a conversation rather than giving a performance.\n\n6. **Celebrate Wins**: Every time you get through a speech or presentation\u2014no matter how it goes\u2014take pride in the fact that *you did it*. Acknowledge your courage because that deserves recognition.\n\nDo any of these ideas feel helpful or doable for you? And if you'd like, we can work together on strategies tailored just for *you*. It\u2019s all about taking small steps forward at your own pace!", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2280, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "6dcc760e-6580-48c6-aa74-d2aa2ae4d077": {"__data__": {"id_": "6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d6eab8f0-f429-4143-95de-4b1cd210275b", "node_type": "4", "metadata": {}, "hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "f00b802f-fa41-4c67-b534-9ffdcd85ac57", "node_type": "1", "metadata": {}, "hash": "d248c4434bb24ed296b56f3c510bce39fa0f8c3b4aa30a80f9b962122a925b1d", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:19:29:\n\nA1: hi\nAI: Hi again! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How are you feeling today?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Thank you for sharing how you're feeling\u2014that takes courage, and I'm here to help. \ud83d\udc9b What you're experiencing is actually very common; many people feel nervous or anxious when speaking in front of a group. You're certainly not alone in this, and it doesn't mean that you lack self-confidence\u2014it just means you're human! Let\u2019s work through this together. \n\nHere are some helpful thoughts and strategies that might ease your stress:\n\n### 1. **Shift Your Focus**\n - Instead of focusing on perfection or avoiding mistakes, focus on **connecting with your audience**. People care more about your message than minor slip-ups.\n - Remember, making a small mistake doesn\u2019t ruin your presentation\u2014it often makes you seem relatable.\n\n### 2. **Preparation Is Key**\n - The more prepared you are, the less nervous you\u2019ll feel. Practice your speech multiple times\u2014alone, with friends or even in front of a mirror.\n - Break it into sections so it feels manageable and less overwhelming.\n\n### 3. **Use Breathing Techniques**\n - Before speaking, take slow, deep breaths to calm your nerves. Try inhaling for four counts, holding for four counts, and exhaling for four counts.\n - This will signal to your body that everything is okay and reduce physical symptoms of anxiety.\n\n### 4. **Visualize Success**\n - Close your eyes and picture yourself standing confidently in front of the group\u2014your words flowing smoothly and everyone listening attentively.\n - Positive visualization can train your brain to feel calmer during the actual event.\n\n### 5. **Reframe Nervousness as Excitement**\n - Instead of thinking \"I'm so nervous,\" try telling yourself \"I'm excited to share my ideas!\" Excitement and nervousness feel similar in the body but reframing them can shift how you perceive those feelings.\n\n### 6.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2136, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "f00b802f-fa41-4c67-b534-9ffdcd85ac57": {"__data__": {"id_": "f00b802f-fa41-4c67-b534-9ffdcd85ac57", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d6eab8f0-f429-4143-95de-4b1cd210275b", "node_type": "4", "metadata": {}, "hash": "f8c5b6dde60eadebe27637642c9522ed9cf96a4c7b4a05adb1b05652ee575b50", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "6dcc760e-6580-48c6-aa74-d2aa2ae4d077", "node_type": "1", "metadata": {}, "hash": "64f0b88588a97fe447f5798262790bffbfa3cd20161a41d22962146d5c09b3e4", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "### 6. **Progress Takes Time**\n - Building confidence doesn\u2019t happen overnight\u2014start small by speaking up in casual conversations or smaller groups.\n - Celebrate every step forward; even attempting to speak publicly is brave!\n\nIf you'd like, we can go deeper into why this fear exists\u2014it might help uncover what\u2019s behind the anxiety. For now though, I want you to know that no matter how things go during a speech, you're still an amazing person with valuable ideas worth sharing. \ud83d\udc99 How do these suggestions sound?", "mimetype": "text/plain", "start_char_idx": 2130, "end_char_idx": 2648, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "b6c8a2d2-04a2-41ed-a8cf-45626c55494f": {"__data__": {"id_": "b6c8a2d2-04a2-41ed-a8cf-45626c55494f", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "36829bfd-0693-4fc1-9932-9a867ca87fcf", "node_type": "4", "metadata": {}, "hash": "d7446ad898618d51eb25544f9e4c23b41e3da1ec019cf194989a5cced48e5265", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-12 23:50:58:\n\nA1: hi\nAI: Hi there! \ud83d\ude0a How's your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a How's your day going?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 129, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "ed23cfed-0942-4751-8cc6-b02a7efa5c53": {"__data__": {"id_": "ed23cfed-0942-4751-8cc6-b02a7efa5c53", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "11eab664-d9ee-4adf-aa77-e87607863567", "node_type": "4", "metadata": {}, "hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d1065fe9-e725-4f1c-b3bd-de9f000bfacd", "node_type": "1", "metadata": {}, "hash": "b1889c67782b46174e42deccbcb2a2375834c7418e37b5317ea0dd72f29ea54c", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 17:35:48:\n\nA1: Hi , How are you ?\nAI: Hi! I'm doing great, thank you for asking. \ud83d\ude0a But more importantly, how are *you* doing today? What's on your mind?\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Hi there, thank you for sharing that with me. Speaking in front of a group can be really challenging, and you're not alone in feeling this way\u2014many people struggle with it. I\u2019m here to help, and together we can work through this.\n\nFirst of all, let\u2019s acknowledge something really important: the fact that you're aware of the issue and open to addressing it shows great courage. You\u2019ve already taken the first step toward building your confidence!\n\nHere are a few strategies that might help:\n\n1. **Start Small**: Begin by speaking in front of smaller groups where you feel more comfortable, like close friends or colleagues. This will help you ease into it gradually.\n\n2. **Preparation is Key**: The more prepared you are for what you're going to say, the more confident you'll feel. Practice your speech or presentation several times, even in front of a mirror or recording yourself to refine your delivery.\n\n3. **Shift Your Focus**: Instead of worrying about making mistakes, try to focus on your message and why it's important for the audience to hear it. Remind yourself that most people in the audience want you to succeed\u2014they're there to listen and learn from you!\n\n4. **Breathing Techniques**: Nervousness often shows up as rapid breathing or a racing heart. Try deep breathing exercises before speaking\u2014it can calm your nerves and help ground you.\n\n5. **Positive Self-Talk**: Replace self-doubt with empowering thoughts like \u201cI am capable,\u201d \u201cMistakes are learning opportunities,\u201d or \u201cMy voice matters.\u201d These affirmations can slowly shift your mindset over time.\n\n6. **Focus on Connection Over Perfection**: Remember that it's okay not to be perfect! People will remember how you made them feel rather than a small stumble or mistake during the talk.\n\n7.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2138, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d1065fe9-e725-4f1c-b3bd-de9f000bfacd": {"__data__": {"id_": "d1065fe9-e725-4f1c-b3bd-de9f000bfacd", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "11eab664-d9ee-4adf-aa77-e87607863567", "node_type": "4", "metadata": {}, "hash": "4e2018aee8ffa398f716bc31f9499c633004e20a1c88aa65f7a74c080ef3a752", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "ed23cfed-0942-4751-8cc6-b02a7efa5c53", "node_type": "1", "metadata": {}, "hash": "c72f196f7e2c2017db935ab9fc3d03d5f1b4d06c3b6f090853fc35f0345ae623", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "7. **Seek Feedback Gradually**: After each speech or presentation, ask someone supportive for constructive feedback. Seeing improvements over time can do wonders for your confidence.\n\nIf you'd like, we can brainstorm some ways to practice public speaking together, maybe even role-play! Or if you\u2019re open to sharing more about what makes you nervous\u2014like fear of judgment or forgetting what to say\u2014we could dig deeper into those feelings.\n\nYou\u2019re stronger than you think, and I believe in your ability to overcome this challenge little by little! You\u2019ve got this\u2014and I\u2019m here anytime you need encouragement or guidance along the way \u2764\ufe0f", "mimetype": "text/plain", "start_char_idx": 2136, "end_char_idx": 2771, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "c08856f2-d6e0-4555-a5d5-71ccd65bf414": {"__data__": {"id_": "c08856f2-d6e0-4555-a5d5-71ccd65bf414", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "d7cc0ff1-5085-415c-add4-827c3a36b0c2", "node_type": "4", "metadata": {}, "hash": "94c83bea11a99cc1a76cf8a9178019a4a2d583f62997e589dc1472500dbe6195", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 17:56:55:\n\nA1: hi\nAI: Hi there! \ud83d\ude0a How\u2019s your day going so far?\nA1: Hi\nAI: Hi there! \ud83d\ude0a It's so good to hear from you. How are you doing today?", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 163, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "19ff65e4-4203-4e73-b9d4-f20aa4e55883": {"__data__": {"id_": "19ff65e4-4203-4e73-b9d4-f20aa4e55883", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "node_type": "1", "metadata": {}, "hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Session on 2026-07-13 18:25:09:\n\nA1: I have a problem. When I want to speak in front of a group, I get very stressed and afraid of making mistakes. Sometimes I even get nervous. I think I don't have the necessary self-confidence.\nAI: Oh, I\u2019m really sorry you\u2019re feeling this way, but let me tell you\u2014you are *not* alone in this struggle. Many people experience stress and fear when speaking in front of a group. It can feel overwhelming, but the fact that you're aware of it and talking about it shows incredible courage already. I\u2019m here for you, and we can work through this step by step.\n\nFirst, let\u2019s start by reframing this: feeling nervous doesn\u2019t mean you're not confident\u2014it means you care about how you come across and want to do well. That\u2019s actually a positive trait! But I get it\u2014those nerves can still feel like they\u2019re working against you. Let\u2019s explore some ways to tackle them:\n\n### **1. Prepare, Prepare, Prepare**\nThe more familiar you are with your material, the less room there is for uncertainty or fear of mistakes. Practice what you want to say multiple times beforehand\u2014alone at first, then maybe with a trusted friend or family member who can encourage you.\n\n### **2. Break Down the Fear**\nAsk yourself: *What am I really afraid of?* Is it forgetting your words? Being judged? Making mistakes? Write down those fears and challenge them one by one. For example:\n - If you're afraid of forgetting your words: Use notes or prompts as backup!\n - Afraid of being judged: Remember most people listening to you are rooting for your success\u2014not looking for flaws.\n - Afraid of making mistakes: Mistakes happen, but they're rarely as big or bad as we imagine.\n\n### **3. Focus on Connection Over Perfection**\nWhen speaking in front of a group, try not to aim for perfection\u2014instead, focus on connecting with your audience! Take a deep breath before starting and remind yourself that people are there to listen to *you*. Your authenticity matters much more than saying things perfectly.\n\n### **4. Breathe and Ground Yourself**\nDeep breathing can be such a lifesaver when nerves start to rise.", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 2112, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "a411160d-23bf-40ad-a1ea-a147bca0a1c5": {"__data__": {"id_": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "19ff65e4-4203-4e73-b9d4-f20aa4e55883", "node_type": "1", "metadata": {}, "hash": "72eac13b38d78284b90342b6c3d936dc53710511f01235d6ae5acabd2df9f621", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "98476e19-2cd8-4ef0-b565-0c304c48718c", "node_type": "1", "metadata": {}, "hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Before stepping up to speak (and even while speaking), practice slow inhaling through your nose for 4 seconds\u2026 holding it for 4 seconds\u2026 then exhaling through your mouth for another 4 seconds. This helps calm the adrenaline running through your body.\n\n### **5. Build Self-Confidence Gradually**\nIt\u2019s okay if public speaking feels scary right now\u2014it gets easier with practice! Start small:\n - Speak up in smaller groups first.\n - Volunteer short answers during meetings or classes.\n - Gradually take on larger challenges when ready.\n\nEvery time you step out of your comfort zone\u2014even just a little\u2014you\u2019ll grow more confident!\n\n### **6. Visualize Success**\nTake some time before a presentation to close your eyes and imagine yourself delivering your talk smoothly. Picture people nodding along and smiling at what you\u2019re saying\u2014it trains your brain to associate public speaking with positivity instead of fear.\n\n---\n\nYou\u2019ve got so much potential inside\u2014and I absolutely believe in you! You don\u2019t have to be perfect; what matters is showing up and trying again each time life gives you an opportunity.\n\nHow about we set one small goal together? What\u2019s one specific situation where you'd like to speak with confidence? We could brainstorm ways for you to prep for that moment! \ud83d\udc9b\nA1: Can you tell me the name of my friend I told you about a few sessions ago?\nAI: Oh, I wish I could remember details like that for you, but unfortunately, I don\u2019t have memory between our conversations right now. If you'd like, you can remind me about your friend\u2014I'd love to hear about them again! You\u2019re always welcome to share, and I\u2019ll do my best to support you. \ud83d\udc9b\nA1: What job is right for me based on my personality traits?\nAI: Choosing the right job can feel like a big decision, but understanding your personality traits is an excellent starting point! Let\u2019s take a look at how your characteristics might align with different types of careers.\n\n### Key Questions to Reflect On:\n1. **Are you more introverted or extroverted?** \n Introverts often thrive in roles requiring focused attention and independent work (e.g., writing, data analysis). Extroverts tend to excel in people-facing environments like sales, teaching, or leadership roles.\n\n2. **Do you enjoy structured environments or flexibility?", "mimetype": "text/plain", "start_char_idx": 2113, "end_char_idx": 4404, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "98476e19-2cd8-4ef0-b565-0c304c48718c": {"__data__": {"id_": "98476e19-2cd8-4ef0-b565-0c304c48718c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "a411160d-23bf-40ad-a1ea-a147bca0a1c5", "node_type": "1", "metadata": {}, "hash": "8a76854e8201aa7113ce67ee55565d32004919dbca1569853eafb95601e9adc8", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "d8e397f5-f706-4640-8bae-95043153e850", "node_type": "1", "metadata": {}, "hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "2. **Do you enjoy structured environments or flexibility?** \n Some people flourish in organized workplaces with clear routines, while others prefer dynamic roles where creativity and spontaneity are valued.\n\n3. **How do you handle stress or challenges?** \n High-pressure jobs may work for those who thrive under deadlines (e.g., emergency response roles), while low-stress positions may better suit those who prioritize stability.\n\n4. **Do you value working with people, ideas, or things?** \n Careers focusing on interpersonal skills may appeal to empathetic individuals (like counseling or HR), whereas more analytical types often enjoy working with ideas (research, technology). Detail-oriented personalities might lean toward working with tangible objects (engineering, architecture).\n\n5. **Do you find fulfillment in helping others?** \n If so, careers in healthcare, education, psychology, social work, or nonprofit organizations could be meaningful options.\n\n### Examples of Personality-Career Matches:\n- **Creative and Imaginative:** Careers such as graphic design, writing, marketing, UX/UI design.\n- **Logical and Detail-Oriented:** Roles like engineering, accounting/auditing, data science.\n- **Empathetic and Person-Oriented:** Paths in psychology/counseling, nursing/healthcare professions.\n- **Highly Energetic and Social:** Fields such as sales/marketing management or event planning.\n- **Independent and Reflective:** Ideal for research-based careers or remote work (e.g., freelance design/development).\n\nWould you like me to explore more personalized career paths based on your preferences? You\u2019re never locked into one path\u2014it\u2019s all about experimenting and growing!\nA1: What job is right for me based on my personality traits?\nAI: That\u2019s an exciting question! Choosing a career that aligns with your personality can lead to greater satisfaction and fulfillment in life. To explore this, let\u2019s reflect on who you are: What are your strengths, values, and preferences? If you're unsure about your specific personality traits, we could use tools like the Myers-Briggs Type Indicator (MBTI), the Big Five Personality Traits model, or Holland's Career Typology as a starting point.\n\nHere are some ideas based on common personality aspects:\n\n---\n\n### **1. If You Love Connecting with People (Extroverted & Empathetic):**\nConsider roles that involve teamwork, communication, and building relationships:\n- **Counselor/Therapist**: Supporting others through emotional challenges.", "mimetype": "text/plain", "start_char_idx": 4347, "end_char_idx": 6845, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "d8e397f5-f706-4640-8bae-95043153e850": {"__data__": {"id_": "d8e397f5-f706-4640-8bae-95043153e850", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "98476e19-2cd8-4ef0-b565-0c304c48718c", "node_type": "1", "metadata": {}, "hash": "e60ac82a354b12d71ef08591acf21769d30d984f4da2e72ecf34743fb8c8dea0", "class_name": "RelatedNodeInfo"}, "3": {"node_id": "1fa69839-167b-4062-8297-c5c481a6957a", "node_type": "1", "metadata": {}, "hash": "fa3f5ea92075df05f87e7b5962bebd66d04fa70657df5913d89eb4c9dc0c5824", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "- **Teacher**: Empowering students in personal growth.\n- **Human Resources Specialist**: Facilitating employee success.\n\n---\n\n### **2. If You\u2019re Creative & Imaginative (Open-minded):**\nExplore careers where you can innovate and express yourself:\n- **Graphic Designer or Illustrator**: Bringing ideas to life visually.\n- **Writer/Editor**: Crafting stories or articulating knowledge.\n- **Marketing/Brand Strategist**: Using creativity to connect with audiences.\n\n---\n\n### **3. If You\u2019re Analytical & Logical (Detail-Oriented):**\nDive into fields that require precision and critical thinking:\n- **Data Analyst or Statistician**: Uncovering insights from information.\n- **Research Scientist**: Pursuing answers to important questions.\n- **Software Developer**: Building technological solutions.\n\n---\n\n### **4. If You Value Helping Others (Compassionate & Altruistic):**\nYou might thrive in careers that focus on service or advocacy:\n- **Healthcare Professional (e.g., Nurse, Occupational Therapist)**.\n- **Social Worker or Non-Profit Coordinator**.\n- **Environmental Scientist/Advocate**.\n\n---\n\n### Let\u2019s Fine-Tune This Together!\nThink about how you spend your free time and what energizes you. Are there activities you love doing\u2014or problems you'd enjoy solving\u2014that might point toward your ideal path? It\u2019s okay if you're still figuring it out; each step will get you closer to clarity! \ud83d\ude0a\nA1: What job is right for me based on my personality traits?\nAI: That\u2019s a great question, and it shows that you\u2019re thoughtfully considering what will align with who you are. Finding a job that fits your personality can bring not only career success but also long-term satisfaction and fulfillment.\n\nTo get started, it would help to reflect on some key aspects of your personality and preferences. For example:\n\n1. **Are you more introverted or extroverted?**\n Do you draw energy from working with others in social environments, or do you thrive in quieter, independent settings?\n\n2. **Do you enjoy structure or flexibility?**\n Do you prefer roles with clear guidelines and routines, or do you excel when given freedom and adaptability?\n\n3. **How do you approach problem-solving?**\n Are you analytical and detail-oriented, or do you rely on intuition and big-picture thinking?\n\n4. **What are your core values?", "mimetype": "text/plain", "start_char_idx": 6846, "end_char_idx": 9148, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}, "1fa69839-167b-4062-8297-c5c481a6957a": {"__data__": {"id_": "1fa69839-167b-4062-8297-c5c481a6957a", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "f193a037-7929-4996-b5d9-2dcfb7ced35d", "node_type": "4", "metadata": {}, "hash": "785a4976cc34e5d20c1d2a1fc0175da0d558f05096184aba5694b66f0cacb15e", "class_name": "RelatedNodeInfo"}, "2": {"node_id": "d8e397f5-f706-4640-8bae-95043153e850", "node_type": "1", "metadata": {}, "hash": "bbd77b084a428cb22c3f17814c3e6fd0275840501407a2c9b1ee53461132e188", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "4. **What are your core values?** \n These could include helping others, creativity, innovation, stability, independence, etc.\n\nLet me know some of these details (or anything else about your personality), and I can suggest career paths that might match your strengths! \ud83d\ude0a", "mimetype": "text/plain", "start_char_idx": 9117, "end_char_idx": 9389, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/graph_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"graph_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/image__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A1/sessions/index_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"index_store/data": {"dd3381a4-8251-49ae-b9ce-0173980f165b": {"__type__": "vector_store", "__data__": "{\"index_id\": \"dd3381a4-8251-49ae-b9ce-0173980f165b\", \"summary\": null, \"nodes_dict\": {\"c0f85884-3d15-4b86-a640-40b86b5b466d\": \"c0f85884-3d15-4b86-a640-40b86b5b466d\", \"a72cbc90-70ad-427e-98d8-cc1d40453e1c\": \"a72cbc90-70ad-427e-98d8-cc1d40453e1c\", \"6553650d-1614-4be0-86d1-0c98613a44a8\": \"6553650d-1614-4be0-86d1-0c98613a44a8\", \"2215dc55-5738-436e-a158-d57b3e12ebd4\": \"2215dc55-5738-436e-a158-d57b3e12ebd4\", \"f01acc17-9115-45fc-a3b4-52e5f98b9446\": \"f01acc17-9115-45fc-a3b4-52e5f98b9446\", \"1aff93b4-bc08-4b25-9f89-5c390730304c\": \"1aff93b4-bc08-4b25-9f89-5c390730304c\", \"59645b90-64dd-4042-b83a-2b3df3715542\": \"59645b90-64dd-4042-b83a-2b3df3715542\", \"d67b97d7-76aa-42c6-ba06-15ea3683679d\": \"d67b97d7-76aa-42c6-ba06-15ea3683679d\", \"e42cffc3-852a-4d19-b30a-b26c81083fe9\": \"e42cffc3-852a-4d19-b30a-b26c81083fe9\", \"0cf45fb8-1856-40b1-bacd-58a238a0d744\": \"0cf45fb8-1856-40b1-bacd-58a238a0d744\", \"86ce7adb-47c4-4552-9f98-d447bf2e6a7b\": \"86ce7adb-47c4-4552-9f98-d447bf2e6a7b\", \"ac89f308-2eed-492f-8179-8693f6504a06\": \"ac89f308-2eed-492f-8179-8693f6504a06\", \"30137e30-cb1c-4284-b5c0-caf42f90eb4e\": \"30137e30-cb1c-4284-b5c0-caf42f90eb4e\", \"b208f966-16b3-4f06-91c3-1b0e7ddfa314\": \"b208f966-16b3-4f06-91c3-1b0e7ddfa314\", \"6dcc760e-6580-48c6-aa74-d2aa2ae4d077\": \"6dcc760e-6580-48c6-aa74-d2aa2ae4d077\", \"f00b802f-fa41-4c67-b534-9ffdcd85ac57\": \"f00b802f-fa41-4c67-b534-9ffdcd85ac57\", \"b6c8a2d2-04a2-41ed-a8cf-45626c55494f\": \"b6c8a2d2-04a2-41ed-a8cf-45626c55494f\", \"ed23cfed-0942-4751-8cc6-b02a7efa5c53\": \"ed23cfed-0942-4751-8cc6-b02a7efa5c53\", \"d1065fe9-e725-4f1c-b3bd-de9f000bfacd\": \"d1065fe9-e725-4f1c-b3bd-de9f000bfacd\", \"c08856f2-d6e0-4555-a5d5-71ccd65bf414\": \"c08856f2-d6e0-4555-a5d5-71ccd65bf414\", \"19ff65e4-4203-4e73-b9d4-f20aa4e55883\": \"19ff65e4-4203-4e73-b9d4-f20aa4e55883\", \"a411160d-23bf-40ad-a1ea-a147bca0a1c5\": \"a411160d-23bf-40ad-a1ea-a147bca0a1c5\", \"98476e19-2cd8-4ef0-b565-0c304c48718c\": \"98476e19-2cd8-4ef0-b565-0c304c48718c\", \"d8e397f5-f706-4640-8bae-95043153e850\": \"d8e397f5-f706-4640-8bae-95043153e850\", \"1fa69839-167b-4062-8297-c5c481a6957a\": \"1fa69839-167b-4062-8297-c5c481a6957a\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/default__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": [-0.048004150390625, -0.01319122314453125, 0.03070068359375, 0.017303466796875, -0.0199737548828125, 0.01154327392578125, 0.01245880126953125, 0.050048828125, 0.016693115234375, 0.067626953125, 0.0443115234375, -0.039886474609375, -0.0146636962890625, 0.004596710205078125, 0.021575927734375, 0.007198333740234375, 0.021392822265625, 0.045623779296875, -0.025543212890625, 0.0287628173828125, 0.0584716796875, 0.0258636474609375, 0.042877197265625, 0.013946533203125, -0.03594970703125, -0.053070068359375, 0.004795074462890625, -0.01081085205078125, 0.041015625, -0.002960205078125, 0.051727294921875, -0.049346923828125, 0.01105499267578125, -0.02093505859375, 0.0100555419921875, 0.04913330078125, 0.00952911376953125, -0.006206512451171875, 0.0265960693359375, 0.0070037841796875, 0.053924560546875, 0.0230865478515625, -0.01493072509765625, 0.021881103515625, -0.0125274658203125, 0.03668212890625, -0.04364013671875, -0.0006322860717773438, -0.003238677978515625, 0.041046142578125, -0.0258636474609375, 0.01751708984375, 0.02960205078125, 0.03875732421875, -0.0301513671875, -0.0258941650390625, 0.0108795166015625, -0.004581451416015625, -0.027252197265625, -0.0216064453125, 0.045501708984375, -0.00867462158203125, 0.04193115234375, 0.046173095703125, -0.01522064208984375, 0.003662109375, 0.0149993896484375, 0.0157012939453125, 0.02325439453125, 0.028472900390625, 0.041473388671875, 0.0240325927734375, -0.0231475830078125, 0.05450439453125, 0.0011796951293945312, 0.00307464599609375, 0.00799560546875, 0.035430908203125, -0.030029296875, -0.0277862548828125, 0.0008397102355957031, -0.046539306640625, -0.0654296875, -0.00783538818359375, -0.01355743408203125, 0.01348114013671875, -0.068603515625, -0.02587890625, 0.0177154541015625, 0.0233917236328125, 0.0316162109375, 0.00025200843811035156, -0.0138702392578125, 0.004405975341796875, 0.0111236572265625, -0.0092010498046875, 0.01617431640625, 0.01297760009765625, 0.007305145263671875, 0.0667724609375, 0.05328369140625, -0.038116455078125, -0.014373779296875, 0.0224609375, 0.041412353515625, 0.0225677490234375, -0.004421234130859375, 0.0025539398193359375, -0.0136871337890625, -0.0218505859375, -0.0256195068359375, -0.0404052734375, -0.00959014892578125, 0.0101776123046875, -0.01513671875, 0.01271820068359375, -0.04022216796875, -0.05859375, 0.032745361328125, -0.0144195556640625, -0.010894775390625, -0.05999755859375, -0.005706787109375, -0.05462646484375, 0.01457977294921875, -0.050537109375, -0.004131317138671875, -0.0335693359375, -0.036529541015625, -0.0601806640625, 0.02532958984375, 0.00934600830078125, 0.026641845703125, -0.05194091796875, -0.0254669189453125, 0.00994110107421875, 0.00525665283203125, -0.030120849609375, -0.028076171875, -0.04541015625, 0.0137176513671875, -0.0228729248046875, 0.017578125, 0.01300048828125, 0.0089263916015625, 0.0242767333984375, 0.049835205078125, 0.05474853515625, 0.0084686279296875, -0.00867462158203125, 0.0019092559814453125, 0.01235198974609375, -0.016326904296875, 0.01129913330078125, -0.01788330078125, -0.042633056640625, -0.01529693603515625, 0.0276336669921875, -0.01071929931640625, -0.04583740234375, -0.02435302734375, 0.00563812255859375, -0.06597900390625, -0.0198822021484375, -0.013763427734375, -0.007160186767578125, -0.02581787109375, -0.005641937255859375, -0.0853271484375, -0.06805419921875, 0.023040771484375, -0.023162841796875, -0.0021762847900390625, 0.00882720947265625, -0.008880615234375, -0.01371002197265625, -0.0186309814453125, -0.0303192138671875, -0.0146484375, -0.01026153564453125, 0.0345458984375, 0.04827880859375, -0.0257110595703125, 0.0377197265625, -0.04327392578125, -0.041351318359375, -0.0192718505859375, 0.03778076171875, 0.0011587142944335938, -0.01374053955078125, -0.0035648345947265625, 0.042938232421875, -0.019989013671875, 0.0048828125, 0.03411865234375, -0.061370849609375, 0.009368896484375, 0.01800537109375, -0.041473388671875, -0.032470703125, 0.035369873046875, 0.003948211669921875, 0.006969451904296875, 0.052001953125, 0.0268096923828125, -0.045318603515625, -0.00676727294921875, 0.030120849609375, -0.015625, -0.015899658203125, 0.05072021484375, -0.0169219970703125, 0.02386474609375, -0.003414154052734375, -0.0247650146484375, 0.01222991943359375, 0.003833770751953125, 0.01073455810546875, -0.006786346435546875, 0.031463623046875, 0.01885986328125, 0.0079498291015625, 0.03045654296875, -0.004680633544921875, -0.0227508544921875, 0.0673828125, 0.0175933837890625, -0.0278167724609375, 0.02532958984375, -0.06689453125, -0.021759033203125, 0.0191192626953125, -0.0171966552734375, 0.01654052734375, -0.01439666748046875, 0.050933837890625, 0.0181427001953125, 0.032318115234375, 0.003681182861328125, 0.0243072509765625, 0.0204315185546875, 0.005527496337890625, 0.0235443115234375, 0.034332275390625, -0.029144287109375, 0.004802703857421875, -0.023040771484375, -0.040496826171875, -0.0161895751953125, 0.01131439208984375, 0.006805419921875, 0.03167724609375, -0.045562744140625, -0.041259765625, 0.01422882080078125, -0.0191497802734375, -0.00421905517578125, -0.0158843994140625, -0.0175628662109375, -0.0189208984375, 0.0207977294921875, -0.012969970703125, -0.008331298828125, 0.051483154296875, -0.06494140625, -0.046051025390625, 0.012939453125, 0.0209197998046875, -0.0017213821411132812, -0.0010833740234375, 0.02105712890625, -0.00705718994140625, 0.0130157470703125, 0.036712646484375, -0.04290771484375, -0.0292205810546875, 0.0302276611328125, 0.03485107421875, 0.015289306640625, 0.0374755859375, -0.017333984375, -0.01654052734375, -0.031829833984375, -0.0218658447265625, -0.0193023681640625, 0.055328369140625, -0.0068817138671875, -0.007465362548828125, 0.040435791015625, -0.04888916015625, 0.03094482421875, -0.05828857421875, 0.03839111328125, -0.043792724609375, 0.03717041015625, 0.019805908203125, 0.0237579345703125, -0.03753662109375, 0.031494140625, 0.0296783447265625, 0.045166015625, 0.0066375732421875, 0.01160430908203125, 0.0211944580078125, 0.044647216796875, 0.08160400390625, 0.0305328369140625, -0.031890869140625, -0.0204620361328125, 0.0213470458984375, 0.0020503997802734375, 0.01410675048828125, 0.005229949951171875, 0.01241302490234375, -0.0209808349609375, -0.01904296875, 0.005161285400390625, 0.0014209747314453125, 0.0027942657470703125, -0.0308990478515625, 0.0003345012664794922, -0.044464111328125, 0.0078887939453125, -0.0202484130859375, 0.0242767333984375, -0.031402587890625, -0.0235443115234375, 0.02044677734375, 0.021759033203125, -0.0467529296875, -0.047607421875, 0.01071929931640625, -0.01482391357421875, 0.038848876953125, 0.0176544189453125, -0.0006389617919921875, -0.01338958740234375, 0.0289459228515625, 0.03009033203125, 0.022613525390625, -0.041961669921875, -0.0198822021484375, 0.008270263671875, 0.0044708251953125, 0.0107879638671875, 0.00528717041015625, 0.01303863525390625, -0.0001761913299560547, -0.02740478515625, 0.052032470703125, -0.0020046234130859375, -0.0310821533203125, 0.01171112060546875, 0.0033855438232421875, -0.0002841949462890625, -0.0413818359375, 0.0175933837890625, 0.00391387939453125, 0.0006718635559082031, 0.033355712890625, -0.0223388671875, 0.01427459716796875, -0.0190277099609375, 0.039642333984375, -0.0229034423828125, 0.050567626953125, -0.06781005859375, -0.007244110107421875, -0.04376220703125, -0.01947021484375, -0.0201568603515625, -0.0258636474609375, -0.041168212890625, 0.054229736328125, -0.01010894775390625, 0.0526123046875, 0.045440673828125, 0.0101470947265625, 0.0019664764404296875, 0.03814697265625, -0.01178741455078125, 0.028289794921875, 0.005706787109375, -0.037841796875, 0.007205963134765625, 0.0292510986328125, -0.01300811767578125, -0.01496124267578125, -0.07135009765625, 0.053985595703125, 0.006053924560546875, 0.0025272369384765625, -0.01898193359375, 0.0279388427734375, 0.0200347900390625, -0.0115966796875, 0.019378662109375, 0.034637451171875, 0.00957489013671875, -0.03759765625, 0.018798828125, -0.0304412841796875, -0.00494384765625, -0.006427764892578125, -0.0111846923828125, 0.047698974609375, -0.007129669189453125, -0.014739990234375, 0.00920867919921875, -0.0225067138671875, -0.0350341796875, -0.0148773193359375, 0.03936767578125, 0.022430419921875, -0.0003981590270996094, -0.0019245147705078125, -0.01152801513671875, 0.0199127197265625, 0.07037353515625, 0.04345703125, -0.006404876708984375, -0.0032806396484375, -0.0269927978515625, -0.018890380859375, -0.0443115234375, 0.043060302734375, -0.0241241455078125, -0.0277862548828125, 0.0699462890625, -0.045562744140625, -0.0310516357421875, 0.039520263671875, -0.048736572265625, 0.02532958984375, 0.0037555694580078125, -0.041595458984375, -0.0323486328125, 0.0234832763671875, 0.017547607421875, 0.007747650146484375, 0.0469970703125, 0.02447509765625, 0.0106964111328125, 0.0304718017578125, -0.070068359375, -0.013458251953125, -0.0633544921875, -0.03192138671875, 0.005687713623046875, -0.05963134765625, -0.021270751953125, -0.043243408203125, -0.028656005859375, -0.0015115737915039062, -0.0335693359375, -0.0122833251953125, -0.01329803466796875, -0.00994873046875, 0.033050537109375, -0.00496673583984375, -0.006378173828125, -0.00865936279296875, 0.0012636184692382812, -0.002620697021484375, 0.060577392578125, -0.025054931640625, -0.0012302398681640625, -0.005718231201171875, 0.0308685302734375, -0.035552978515625, -0.0006103515625, 0.0247344970703125, -0.00992584228515625, -0.0458984375, -0.051910400390625, -0.005908966064453125, 0.0054473876953125, -0.032379150390625, 0.043060302734375, 0.00494384765625, 0.0250244140625, 0.060943603515625, 0.00689697265625, 0.004150390625, 0.0213165283203125, 0.01041412353515625, -0.0283660888671875, 0.0292816162109375, -0.00574493408203125, 0.03741455078125, -0.025848388671875, 0.00955963134765625, -0.0195465087890625, -0.0246734619140625, 0.0033416748046875, -0.016815185546875, 0.00417327880859375, -0.0253753662109375, 0.0025577545166015625, -0.016265869140625, 7.444620132446289e-05, -0.0296478271484375, -0.0025882720947265625, 0.07098388671875, -0.0128936767578125, 0.0228729248046875, -0.048675537109375, 0.007434844970703125, -0.006740570068359375, 0.0294647216796875, 0.0009312629699707031, 0.00959014892578125, -0.00167083740234375, -0.038421630859375, 0.00035500526428222656, 0.009735107421875, -0.0162200927734375, 0.01885986328125, -0.007747650146484375, 0.037200927734375, 0.0251312255859375, 0.01192474365234375, -0.0015993118286132812, -0.0003058910369873047, 0.02362060546875, -0.03338623046875, 0.0120697021484375, -0.004535675048828125, -0.00818634033203125, -0.032684326171875, 0.0211029052734375, -0.00732421875, 0.004673004150390625, -0.01445770263671875, -0.01326751708984375, -0.01544189453125, 0.0033969879150390625, 0.00534820556640625, 0.0182647705078125, 0.007396697998046875, 0.03314208984375, 0.08514404296875, 0.0290374755859375, -0.0009293556213378906, -0.0148773193359375, -0.016204833984375, 0.01157379150390625, 0.0098419189453125, 0.013092041015625, 0.035614013671875, 0.0011463165283203125, -0.0634765625, 0.0157012939453125, 0.019775390625, 0.043914794921875, -0.0133056640625, 0.01383209228515625, 0.0234527587890625, -0.0268402099609375, 0.01055908203125, -0.045684814453125, -0.056182861328125, 0.01059722900390625, 0.0034236907958984375, 0.008209228515625, -0.0031032562255859375, -0.0211029052734375, 0.0301971435546875, -0.029327392578125, -0.0029277801513671875, 0.00946044921875, -0.00830078125, 0.0215606689453125, -0.050872802734375, 0.0230865478515625, -0.00112152099609375, -0.010345458984375, 0.042449951171875, -0.004238128662109375, -0.00531768798828125, -0.0065765380859375, -0.033966064453125, -0.031890869140625, 0.0206146240234375, -0.02252197265625, 0.00371551513671875, -0.004268646240234375, -0.0167083740234375, 0.052276611328125, 0.004146575927734375, 0.02374267578125, -0.0156707763671875, 0.0110015869140625, 0.02301025390625, 0.0005483627319335938, 0.01042938232421875, -0.0163116455078125, -0.0126190185546875, -0.00885772705078125, 0.004657745361328125, 0.0268096923828125, -0.004779815673828125, -0.00847625732421875, -0.03753662109375, 0.01346588134765625, 0.03387451171875, -0.0214080810546875, -0.0149078369140625, 0.00739288330078125, -0.0208282470703125, 0.04425048828125, 0.004642486572265625, 0.00566864013671875, -0.00800323486328125, 0.0077056884765625, -0.0168304443359375, -0.01169586181640625, -0.002292633056640625, 0.0247344970703125, 0.0133514404296875, -0.0279388427734375, 0.00873565673828125, 0.02130126953125, 0.016845703125, 0.038818359375, 0.036224365234375, 0.0440673828125, -0.001312255859375, 0.0504150390625, -0.01617431640625, 0.0027561187744140625, -0.0014934539794921875, 0.0221099853515625, -0.0013370513916015625, 0.00780487060546875, 0.007312774658203125, -0.000644683837890625, 0.00994110107421875, -0.0008859634399414062, -0.033721923828125, 0.0110015869140625, -0.01137542724609375, 0.024688720703125, -0.017608642578125, 0.0062408447265625, -0.0020904541015625, 0.015625, 0.010467529296875, -0.004482269287109375, -0.02606201171875, -0.046600341796875, -0.01342010498046875, 0.035308837890625, -0.0010814666748046875, 0.002323150634765625, -0.04351806640625, 0.006855010986328125, -0.0114593505859375, -0.03759765625, 0.0328369140625, 0.00160980224609375, 0.00872802734375, -0.0267791748046875, -0.032928466796875, -0.012420654296875, 0.0274810791015625, 0.0146331787109375, -0.05609130859375, 0.0012750625610351562, 0.015777587890625, -0.0203857421875, 0.01160430908203125, 0.01715087890625, 0.003612518310546875, 0.04254150390625, 0.005290985107421875, -0.004993438720703125, -0.0235443115234375, 0.006679534912109375, 0.0064697265625, -0.0147857666015625, 0.0255889892578125, -0.01165771484375, -0.0246734619140625, -0.01294708251953125, -0.0193023681640625, 0.01538848876953125, -0.0170440673828125, 0.0238037109375, 0.0231475830078125, -0.01174163818359375, -0.0121002197265625, 0.0052337646484375, -0.0174560546875, 0.0219879150390625, -0.00835418701171875, 0.01507568359375, -0.0238800048828125, -0.019683837890625, -0.054962158203125, 0.006084442138671875, -0.006023406982421875, 0.0082244873046875, -0.0237884521484375, -0.042388916015625, -0.0195770263671875, 0.00846099853515625, -0.01403045654296875, 0.03387451171875, 0.00799560546875, -0.031341552734375, -0.0357666015625, -0.01551055908203125, 0.0203399658203125, -0.01004791259765625, 0.001972198486328125, -0.0643310546875, 0.0450439453125, -0.027191162109375, 0.00629425048828125, 0.042999267578125, 0.0308837890625, -0.031219482421875, 0.002445220947265625, -0.053741455078125, -0.0019321441650390625, -0.005401611328125, -0.01227569580078125, -0.00445556640625, 0.0164794921875, 0.007965087890625, -0.014617919921875, 0.04180908203125, -0.01776123046875, -0.0106048583984375, 0.01435089111328125, -0.029449462890625, 0.0277099609375, -0.0014486312866210938, -0.007171630859375, -0.003040313720703125, -0.04254150390625, 0.0283966064453125, 0.0226287841796875, 0.0199737548828125, -0.006694793701171875, -0.0131683349609375, 0.0297393798828125, -0.0021991729736328125, -0.02349853515625, -0.024078369140625, 0.01885986328125, -0.00215911865234375, 0.024200439453125, 0.00019121170043945312, -0.01467132568359375, 0.00495147705078125, -0.01108551025390625, -0.0443115234375, 0.0065765380859375, 0.0224456787109375, 0.070556640625, 0.01305389404296875, 0.0167236328125, 0.0009889602661132812, 0.01404571533203125, -0.0357666015625, -0.023895263671875, -0.03533935546875, -0.0253753662109375, 0.01534271240234375, -0.033782958984375, -0.0105438232421875, 0.01016998291015625, 0.049407958984375, -0.0059967041015625, -0.0184783935546875, -0.0206146240234375, -0.01328277587890625, 0.01273345947265625, 0.052886962890625, -0.00337982177734375, -0.036712646484375, -0.0119781494140625, -0.029632568359375, -0.042327880859375, -0.0248565673828125, -0.023651123046875, -0.0191650390625, -0.037261962890625, -0.01052093505859375, -0.037384033203125, 0.0228729248046875, 0.0198822021484375, 0.0024967193603515625, 0.038665771484375, -0.004718780517578125, -0.1304931640625, 0.03509521484375, 0.01873779296875, -0.0044708251953125, -0.0202484130859375, -0.00952911376953125, -0.01209259033203125, 0.0290985107421875, 0.005645751953125, -0.0372314453125, 0.0255584716796875, -0.019378662109375, -0.0094146728515625, -0.012359619140625, -0.0221405029296875, -0.036651611328125, -0.017181396484375, -0.00037384033203125, -0.043212890625, 0.02337646484375, 0.0008807182312011719, -0.00042939186096191406, -0.0241851806640625, 0.027374267578125, -0.0208740234375, 0.0127105712890625, -0.0087890625, 0.00501251220703125, -0.00655364990234375, -0.01178741455078125, 0.033203125, -0.007717132568359375, -0.0087432861328125, -0.023895263671875, 0.023406982421875, -0.03485107421875, 0.0032596588134765625, 0.032318115234375, -0.03668212890625, -0.002727508544921875, -0.005268096923828125, 0.05029296875, 0.01080322265625, 0.0193328857421875, -0.00012755393981933594, -0.0357666015625, 0.01081085205078125, 0.01239013671875, 0.01763916015625, -0.02362060546875, 0.01849365234375, -0.03948974609375, 0.007648468017578125, -0.00384521484375, -0.0283050537109375, 0.01076507568359375, -0.00614166259765625, 0.020355224609375, -0.0257110595703125, 0.0016374588012695312, 0.0214996337890625, -0.004970550537109375, -0.00897979736328125, -0.0271453857421875, -0.014678955078125, -0.0164947509765625, -0.0059967041015625, -0.031982421875, -0.01374053955078125, 0.003421783447265625, -0.0215301513671875, 0.0151519775390625, -0.0007534027099609375, -0.03173828125, -0.0103607177734375, -0.012237548828125, -0.01226806640625, -0.005615234375, -0.024932861328125, 0.01006317138671875, 0.039764404296875, 0.007061004638671875, 0.0197601318359375, 0.03411865234375, 0.0294647216796875, -0.027008056640625, 0.01528167724609375, -0.005245208740234375, -0.0212249755859375, -0.005279541015625, 0.0255126953125, -0.0286712646484375, 0.00595855712890625, 0.006343841552734375, 0.0206298828125, 0.01332855224609375, -0.0235137939453125, 0.0101470947265625, -0.01146697998046875, -0.01132965087890625, 0.0029125213623046875, 0.00421142578125, 0.0004761219024658203, 0.006496429443359375, -0.012664794921875, 0.0162811279296875, 0.05377197265625, 0.042877197265625, 0.02069091796875, 0.004192352294921875, -0.01361083984375, 0.0029850006103515625, 0.0176239013671875, 0.00395965576171875, 0.004108428955078125, 0.03155517578125, 0.029144287109375, -0.01351165771484375, 0.00800323486328125, -0.0115814208984375, 0.0292510986328125, -0.00696563720703125, -0.01519012451171875, 0.053680419921875, -0.004978179931640625, 0.0018358230590820312, 0.046630859375, -0.0209503173828125, 0.029296875, -0.005039215087890625, 0.03216552734375, 0.0280914306640625, 0.0083465576171875, 0.016204833984375, 0.03363037109375, 0.025299072265625, 0.040069580078125, 0.0200958251953125, 0.0477294921875, 0.034332275390625, 0.01055908203125, -0.00745391845703125, -0.0098724365234375, 0.0013456344604492188, -0.0258636474609375, 0.028045654296875, 0.0018148422241210938, 0.05133056640625, 0.003482818603515625, 0.027069091796875, 0.03485107421875, -0.03131103515625, 0.0170745849609375, -0.00702667236328125, 0.0202484130859375, 0.00629425048828125, 0.01898193359375, -0.0050201416015625, -0.017547607421875, -0.016632080078125, 0.007335662841796875, 0.01073455810546875, -0.0216064453125, -0.03924560546875, 0.026611328125, 0.0261993408203125, -0.0128936767578125, -0.0250396728515625, 0.0479736328125, -0.01013946533203125, -0.012237548828125, -0.01904296875, -0.0017671585083007812, 0.00994873046875, 0.0072174072265625, 0.00899505615234375, -0.00428009033203125, 0.01529693603515625, -0.01235198974609375, 0.00119781494140625, 0.040435791015625, 0.045745849609375, -0.029327392578125, -0.012054443359375, 0.07049560546875, -0.0198822021484375, 0.0038585662841796875, -0.0004506111145019531, 0.009521484375, 0.0136871337890625, 0.019378662109375, 0.031097412109375, 0.023101806640625, 0.03192138671875, 0.00716400146484375, -0.036651611328125, 0.0014944076538085938, -0.0157012939453125, -0.004131317138671875, -0.01409912109375, -0.0269012451171875, 0.0156707763671875, 0.01904296875, -0.034393310546875, 0.03863525390625, -0.0003180503845214844, 0.01953125, 0.016082763671875, -0.01355743408203125, 0.01490020751953125, -0.00969696044921875, -0.02490234375, -0.020263671875, -0.0017604827880859375, 0.005146026611328125, 0.01520538330078125, -0.02508544921875, -0.002727508544921875, 0.00391387939453125, -0.030792236328125, 0.00414276123046875, -0.03857421875, -0.023284912109375, -0.0205841064453125, -0.00165557861328125, -0.016143798828125, -0.0047149658203125, 0.031890869140625, -0.00844573974609375, 0.02362060546875, 0.0126953125, 0.0271148681640625, 0.016448974609375, 0.041046142578125, -0.0161590576171875, 0.0271759033203125, -0.0133819580078125, -0.0113372802734375, 0.03387451171875, -0.05889892578125, 0.004421234130859375, -0.0231475830078125, -0.0020809173583984375, -0.033538818359375, -0.037261962890625, -0.03326416015625, 0.013641357421875, -0.028167724609375, 0.007122039794921875, -0.006992340087890625, 0.006221771240234375, 0.010498046875, 0.0142822265625, 0.0050201416015625, 0.005832672119140625, 0.00658416748046875, -0.0188751220703125, 0.03509521484375, 0.00540924072265625, 0.0238494873046875, -0.00830078125, 0.00885772705078125, -0.0006837844848632812, -0.01078033447265625, 0.0062713623046875, 0.00799560546875, -0.0293731689453125, -0.03155517578125, -0.0048828125, 0.017974853515625, -0.0380859375, 0.0058135986328125, 0.01209259033203125, 0.0281829833984375, 0.006557464599609375, -0.004619598388671875, -0.0132904052734375, -0.01953125, 0.00039076805114746094, -0.032012939453125, -0.0172271728515625, 0.0292510986328125, -0.00482177734375, 0.0018024444580078125, 0.0108184814453125, -0.0245819091796875, 0.001834869384765625, -0.02996826171875, -0.0055084228515625, 0.01522064208984375, 0.01282501220703125, 0.005615234375, 0.018341064453125, 0.003604888916015625, -0.006252288818359375, -0.0238037109375, -0.02783203125, 0.03289794921875, 0.045867919921875, -0.0311126708984375, -0.0118408203125, -0.025054931640625, -0.0015039443969726562, 0.0222015380859375, 0.02337646484375, 0.01007080078125, -0.005443572998046875, -0.042694091796875, -0.00954437255859375, 0.01268768310546875, -0.03070068359375, -0.0058441162109375, 0.00933837890625, -0.0117645263671875, -0.02783203125, -0.035980224609375, 0.02410888671875, 0.007595062255859375, -0.0002275705337524414, -0.0076751708984375, -0.013702392578125, -0.005702972412109375, -0.00984954833984375, -0.007175445556640625, -0.01432037353515625, -0.005992889404296875, -0.0241241455078125, -0.038543701171875, 0.011505126953125, -0.0147857666015625, 0.0120086669921875, -0.03338623046875, 0.0236053466796875, 0.01148223876953125, 0.0117034912109375, 0.0322265625, 0.01043701171875, -0.0290679931640625, -0.01496124267578125, -0.02337646484375, -0.01560211181640625, -0.0012798309326171875, 0.01558685302734375, -0.0045166015625, 0.012176513671875, 0.004673004150390625, -0.00678253173828125, -0.0022735595703125, -0.005153656005859375, 0.02423095703125, 0.1395263671875, 0.0167083740234375, -0.01251983642578125, 0.01141357421875, 0.0278472900390625, -0.0019016265869140625, 0.0173492431640625, 0.01904296875, -0.0094146728515625, -0.0089874267578125, -0.0234222412109375, -0.002109527587890625, 0.00012552738189697266, 0.0041656494140625, 0.0230712890625, 0.0265655517578125, -0.03985595703125, -0.00539398193359375, 0.01739501953125, 0.0033054351806640625, 0.0201263427734375, -0.0036468505859375, 0.02105712890625, -0.0294647216796875, -0.037384033203125, -0.004322052001953125, 0.00540924072265625, 0.0036983489990234375, 0.00894927978515625, 0.01020050048828125, 0.02783203125, -0.00887298583984375, -0.0233306884765625, 0.0006155967712402344, -0.041839599609375, 0.006069183349609375, 0.037872314453125, 0.0298919677734375, -0.00623321533203125, 0.0238800048828125, 0.0005621910095214844, -0.0155487060546875, 0.0214080810546875, -0.0308990478515625, 0.007694244384765625, 0.01181793212890625, -0.0192413330078125, 0.00746917724609375, -0.025604248046875, -0.010772705078125, -0.00606536865234375, 0.0096435546875, -0.037445068359375, -0.00579833984375, -0.018798828125, -0.017974853515625, 0.00392913818359375, 0.01348114013671875, 0.027313232421875, -0.0133514404296875, -0.0179901123046875, 0.015960693359375, -0.00042128562927246094, -0.003871917724609375, 0.03448486328125, -0.0016698837280273438, -0.022491455078125, -0.0243377685546875, 0.0243072509765625, -0.0200042724609375, -0.035491943359375, 0.028076171875, -0.0186004638671875, -0.0199127197265625, 0.00858306884765625, 0.0048065185546875, 0.00421142578125, 0.0263824462890625, -0.01427459716796875, -0.01314544677734375, 0.034515380859375, -0.0095367431640625, 0.006290435791015625, 0.0150146484375, 0.003208160400390625, 0.047515869140625, 0.01507568359375, -0.0307769775390625, 0.0023403167724609375, 0.0019397735595703125, -0.008636474609375, 0.0176849365234375, 0.0181884765625, -0.0035400390625, 0.0279693603515625, -0.00014591217041015625, -0.00955963134765625, 0.0029354095458984375, -0.0030727386474609375, -0.0234527587890625, 0.03985595703125, -0.0177764892578125, -0.0384521484375, 0.01434326171875, -0.0052947998046875, -0.0203857421875, -0.0122222900390625, 0.03271484375, -0.034515380859375, -0.01123046875, 0.006122589111328125, 0.01434326171875, 0.044281005859375, -0.0209808349609375, 0.0050201416015625, -0.048828125, 0.0208587646484375, -0.0374755859375, 0.01404571533203125, -0.0066986083984375, -0.007801055908203125, 0.0115509033203125, -0.002735137939453125, -0.023223876953125, -0.0031108856201171875, 0.0222015380859375, 0.045135498046875, 0.0284881591796875, 0.0023441314697265625, 0.006847381591796875, -0.004993438720703125, 0.005519866943359375, 0.0012216567993164062, -0.0291290283203125, 0.00919342041015625, 0.04534912109375, -0.026123046875, -0.04534912109375, 0.023834228515625, -0.0276031494140625, -0.0284423828125, 0.004245758056640625, -0.004886627197265625, -0.0039043426513671875, -0.004634857177734375, 0.00304412841796875, 0.015411376953125, -0.010162353515625, 0.02166748046875, 0.01934814453125, 0.01227569580078125, -0.0187530517578125, 0.00844573974609375, 0.023651123046875, 0.032073974609375, 0.02301025390625, 0.0244140625, -0.02105712890625, -0.00783538818359375, -0.042449951171875, -0.0023822784423828125, -0.0030269622802734375, 0.0012607574462890625, 0.0078887939453125, 0.030914306640625, 0.056121826171875, 0.0164794921875, -0.007843017578125, -0.0023708343505859375, -0.014678955078125, -0.0162200927734375, -0.0045928955078125, 0.009674072265625, 0.0249786376953125, 0.005390167236328125, 0.0228118896484375, 0.01454925537109375, 0.0166473388671875, -0.0284423828125, -0.029388427734375, -0.005580902099609375, -0.034149169921875, 0.0224609375, 0.017913818359375, 0.00836181640625, 0.007244110107421875, -0.007297515869140625, -0.0177459716796875, -0.0255279541015625, -0.049468994140625, -0.0189208984375, -0.0164031982421875, 0.00384521484375, -0.008056640625, 0.0227813720703125, 0.06524658203125, -0.02301025390625, 0.00112152099609375, -0.01629638671875, -0.01593017578125, -0.024261474609375, -0.0260009765625, -0.02740478515625, -0.0124664306640625, -0.004058837890625, 0.00655364990234375, 0.0156402587890625, 0.0111846923828125, 0.01180267333984375, -0.00641632080078125, -0.00153350830078125, 0.0172882080078125, 0.005886077880859375, -0.007320404052734375, 0.0198822021484375, 0.036041259765625, -0.031341552734375, 0.0207977294921875, -0.01222991943359375, 0.040283203125, -0.006103515625, -0.0247039794921875, -0.0017719268798828125, -0.0190277099609375, 0.0250396728515625, 0.01097869873046875, 0.0213165283203125, -0.0166473388671875, -0.0199432373046875, 0.010894775390625, 0.0164031982421875, -0.0101165771484375, -0.0076904296875, 0.0008525848388671875, 0.01230621337890625, 0.016510009765625, -0.0188751220703125, 0.00982666015625, -0.03228759765625, -0.00786590576171875, 0.01371002197265625, -0.0428466796875, -0.00550079345703125, 0.032623291015625, -0.0199127197265625, 0.03558349609375, 0.0284271240234375, -0.016510009765625, -0.0182342529296875, 0.0250244140625, -0.041656494140625, 0.011260986328125, -0.0038776397705078125, 0.0005660057067871094, -0.0099334716796875, -0.00260162353515625, -0.013671875, -0.01320648193359375, -0.028533935546875, -0.0338134765625, -0.0238037109375, -0.034332275390625, -0.01213836669921875, -0.0236358642578125, 0.0297393798828125, 0.0070343017578125, -0.0014629364013671875, 0.0157318115234375, -0.05084228515625, 0.0272369384765625, -0.045806884765625, 0.03369140625, -0.049560546875, -0.0270538330078125, -0.018524169921875, -0.0190277099609375, -0.0047607421875, -0.004405975341796875, 0.0030689239501953125, 0.00031638145446777344, -0.038818359375, -0.007114410400390625, -0.031585693359375, -0.031524658203125, 0.0106353759765625, -0.00982666015625, -0.00878143310546875, 0.002796173095703125, 0.03515625, 0.005023956298828125, 0.0048980712890625, 0.0386962890625, -0.005886077880859375, 0.025238037109375, 0.021636962890625, 0.01708984375, -0.0073699951171875, -0.034942626953125, 0.005580902099609375, 0.008697509765625, 0.0311737060546875, 0.003765106201171875, 0.0247650146484375, 0.0136260986328125, 0.036041259765625, 0.021697998046875, -0.03240966796875, 0.02215576171875, -0.0019178390502929688, -0.017547607421875, -0.00646209716796875, -0.0048675537109375, -0.00872039794921875, -0.005035400390625, -0.0031986236572265625, -0.0244598388671875, 0.0210723876953125, -0.0026149749755859375, -0.041748046875, 0.017791748046875, 0.00778961181640625, -0.0151214599609375, -0.0186767578125, 0.017486572265625, 0.048431396484375, -0.017730712890625, 0.03173828125, -0.01523590087890625, 0.018463134765625, 0.018402099609375, 0.03607177734375, 0.0011548995971679688, 0.013214111328125, -0.01204681396484375, 0.00495147705078125, -0.0204925537109375, 0.01419830322265625, -0.01812744140625, 0.00811004638671875, -0.013916015625, -0.005916595458984375, 0.002838134765625, 0.009307861328125, 0.0221099853515625, 0.020172119140625, 0.0220947265625, 0.054351806640625, 0.0026760101318359375, -0.004589080810546875, -0.011962890625, -0.0026683807373046875, 0.007808685302734375, -0.007396697998046875, 0.00922393798828125, -0.0174713134765625, 0.0100555419921875, 0.06817626953125, -0.0038051605224609375, -0.0228118896484375, 0.0220489501953125, -0.0251312255859375, 0.00995635986328125, 0.00775146484375, 0.003330230712890625, -0.02593994140625, 0.0182647705078125, 0.0189666748046875, -0.033782958984375, 0.0158843994140625, -0.0148773193359375, -0.024932861328125, -0.0224761962890625, 0.007686614990234375, 0.01861572265625, 0.00467681884765625, -0.033905029296875, 0.0016508102416992188, -0.02093505859375, -0.0054168701171875, -0.035064697265625, 0.037261962890625, -0.046905517578125, -0.024627685546875, -0.030975341796875, 0.00821685791015625, -0.01279449462890625, -0.0276336669921875, -0.0210418701171875, -0.0255126953125]}, "text_id_to_ref_doc_id": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": "6815456a-54f2-4a06-839a-4237713a5b85"}, "metadata_dict": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"_node_type": "TextNode", "document_id": "6815456a-54f2-4a06-839a-4237713a5b85", "doc_id": "6815456a-54f2-4a06-839a-4237713a5b85", "ref_doc_id": "6815456a-54f2-4a06-839a-4237713a5b85"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/docstore.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"docstore/metadata": {"6815456a-54f2-4a06-839a-4237713a5b85": {"doc_hash": "e31725404c452bc7bb6b93285f5b7de1917dd6b4340001a2565339635b9c4a65"}, "e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"doc_hash": "7e80a357c96e74104a44793a6b1eba724431c64f8d4d4702bf0e93bc7336201d", "ref_doc_id": "6815456a-54f2-4a06-839a-4237713a5b85"}}, "docstore/ref_doc_info": {"6815456a-54f2-4a06-839a-4237713a5b85": {"node_ids": ["e78dce52-f400-452b-aff3-cbe27f8bbf2c"], "metadata": {}}}, "docstore/data": {"e78dce52-f400-452b-aff3-cbe27f8bbf2c": {"__data__": {"id_": "e78dce52-f400-452b-aff3-cbe27f8bbf2c", "embedding": null, "metadata": {}, "excluded_embed_metadata_keys": [], "excluded_llm_metadata_keys": [], "relationships": {"1": {"node_id": "6815456a-54f2-4a06-839a-4237713a5b85", "node_type": "4", "metadata": {}, "hash": "e31725404c452bc7bb6b93285f5b7de1917dd6b4340001a2565339635b9c4a65", "class_name": "RelatedNodeInfo"}}, "metadata_template": "{key}: {value}", "metadata_separator": "\n", "text": "Recent experiences:", "mimetype": "text/plain", "start_char_idx": 0, "end_char_idx": 19, "metadata_seperator": "\n", "text_template": "{metadata_str}\n\n{content}", "class_name": "TextNode"}, "__type__": "1"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/graph_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"graph_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/image__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {}, "text_id_to_ref_doc_id": {}, "metadata_dict": {}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/episodic_memory/index_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"index_store/data": {"36fc9fca-2fa9-4956-a458-82e9418852d2": {"__type__": "vector_store", "__data__": "{\"index_id\": \"36fc9fca-2fa9-4956-a458-82e9418852d2\", \"summary\": null, \"nodes_dict\": {\"e78dce52-f400-452b-aff3-cbe27f8bbf2c\": \"e78dce52-f400-452b-aff3-cbe27f8bbf2c\"}, \"doc_id_dict\": {}, \"embeddings_dict\": {}}"}}}
|
Emma/MMPL_gpt/memories/memory_index/llamaindex/A13/semantic_memory/default__vector_store.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
{"embedding_dict": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": [0.0081634521484375, -0.002292633056640625, 0.044647216796875, 0.052490234375, 0.016448974609375, 0.04071044921875, 0.0214691162109375, -0.00907135009765625, -0.026580810546875, 0.06268310546875, -0.017913818359375, -0.031219482421875, -0.008270263671875, -0.0540771484375, 0.0306854248046875, 0.05987548828125, 0.0031261444091796875, 0.0249786376953125, 0.011383056640625, -0.0008664131164550781, 0.0090484619140625, 0.01824951171875, 0.01226806640625, -0.027923583984375, -0.006282806396484375, 0.0195465087890625, -0.03558349609375, 0.046844482421875, 0.048187255859375, -0.018035888671875, 0.01302337646484375, -0.035736083984375, 0.00951385498046875, 0.006000518798828125, 0.0019931793212890625, 0.046966552734375, 0.057830810546875, -0.046905517578125, 0.01568603515625, -0.049530029296875, -0.04400634765625, -0.01499176025390625, -0.0240478515625, -0.0204925537109375, -0.019073486328125, -0.038543701171875, 0.0274810791015625, 0.0416259765625, -0.005279541015625, 0.037811279296875, -0.0180816650390625, 0.0062103271484375, -0.007709503173828125, 0.05865478515625, -0.06402587890625, 0.037841796875, -0.0118560791015625, -0.0301361083984375, 0.024688720703125, -0.00374603271484375, 0.032196044921875, -0.030914306640625, 0.03759765625, 0.03179931640625, -0.0204315185546875, 0.0012073516845703125, -0.020904541015625, -0.007476806640625, 0.0204010009765625, -0.0124359130859375, 0.060791015625, -0.00656890869140625, 0.019775390625, -0.005367279052734375, 0.0201416015625, -0.009368896484375, 0.04400634765625, 0.01079559326171875, -0.026275634765625, -0.0166778564453125, -0.039947509765625, 0.0187530517578125, -0.007564544677734375, 0.006954193115234375, 0.0157928466796875, 0.0212860107421875, 0.01548004150390625, -0.0113372802734375, -0.00875091552734375, 0.00077056884765625, -0.0033931732177734375, -0.0517578125, 0.006214141845703125, -0.0011644363403320312, 0.0198211669921875, -0.06500244140625, 0.04730224609375, -0.005107879638671875, -0.046417236328125, 0.019805908203125, -0.01023101806640625, 0.042388916015625, -0.0251312255859375, 0.0288238525390625, -0.0189361572265625, 0.005825042724609375, -0.0218505859375, -0.053558349609375, -0.05267333984375, -0.01337432861328125, -0.07476806640625, 0.01398468017578125, -0.031402587890625, 0.060272216796875, -0.06524658203125, 0.01261138916015625, -0.036407470703125, 0.031585693359375, 0.018157958984375, 0.010650634765625, 0.03662109375, 0.004913330078125, -0.00821685791015625, -0.0110321044921875, -0.00493621826171875, -0.032867431640625, -0.0236968994140625, -0.0100250244140625, 0.01206207275390625, -0.0259246826171875, -0.037445068359375, -0.0034084320068359375, 0.03253173828125, -0.0012178421020507812, -0.04046630859375, -0.0421142578125, 0.039764404296875, -0.0325927734375, 0.007770538330078125, -0.031036376953125, -0.053375244140625, -0.0150146484375, 0.0517578125, 0.00887298583984375, 0.00026798248291015625, 0.051239013671875, 0.032623291015625, 0.0738525390625, -0.0224609375, 0.0159149169921875, 0.0098419189453125, -0.00909423828125, -0.0118255615234375, -0.0111541748046875, 0.0201263427734375, -0.0180511474609375, 0.01187896728515625, -0.034759521484375, -0.0008187294006347656, -0.04052734375, 0.060760498046875, -0.0290069580078125, -0.02984619140625, 0.004688262939453125, 0.04132080078125, 0.043914794921875, 0.0194854736328125, -0.0251007080078125, -0.0369873046875, -0.048095703125, 0.0293731689453125, -0.057098388671875, -0.00980377197265625, -0.06640625, -0.0310516357421875, -0.0071563720703125, -0.03265380859375, 0.019805908203125, -0.0110015869140625, -0.007228851318359375, 0.0055694580078125, 0.056488037109375, -0.04559326171875, -0.01302337646484375, -0.0055694580078125, -0.01259613037109375, -0.032379150390625, -0.023345947265625, 0.050201416015625, 0.0186920166015625, 0.0124359130859375, 0.0265655517578125, 0.0333251953125, 0.005031585693359375, 0.016876220703125, -0.03076171875, 0.06427001953125, -0.0201263427734375, -0.055511474609375, 0.022430419921875, 0.01209259033203125, 0.017364501953125, 0.02154541015625, -0.00867462158203125, 0.0078887939453125, -0.0232696533203125, 0.09197998046875, 0.0238189697265625, -0.06353759765625, -0.0104522705078125, 0.01107025146484375, -0.0228118896484375, 0.03570556640625, 0.06231689453125, -0.0238037109375, 0.055999755859375, -0.00455474853515625, -0.03582763671875, 0.02410888671875, 0.02105712890625, 0.00481414794921875, 0.00914764404296875, 0.050537109375, -0.01297760009765625, -0.035736083984375, 0.020782470703125, -0.01070404052734375, -0.0074615478515625, -0.0088348388671875, -0.041107177734375, -0.005451202392578125, -0.0007982254028320312, 0.0026073455810546875, -0.033447265625, -0.06683349609375, -0.03204345703125, 0.020904541015625, 0.045989990234375, 0.026458740234375, -0.020660400390625, -0.0216064453125, 0.0258026123046875, -0.0005774497985839844, 0.02734375, 0.0169830322265625, 0.01788330078125, -0.01715087890625, 0.0059051513671875, -6.35981559753418e-05, -0.051177978515625, 0.01082611083984375, -0.00955963134765625, -0.01690673828125, 0.01666259765625, -0.004123687744140625, -0.0438232421875, 0.00421905517578125, -0.02447509765625, 0.04412841796875, -0.0303802490234375, -0.03009033203125, -0.01531982421875, -0.0205230712890625, 0.03375244140625, 0.0355224609375, 0.0100860595703125, -0.006961822509765625, 0.0281829833984375, 0.00582122802734375, -0.04266357421875, 0.053131103515625, -0.037322998046875, 0.0026454925537109375, 0.0361328125, -0.045806884765625, 0.03363037109375, -0.0061492919921875, -0.0038585662841796875, -0.11993408203125, -0.007415771484375, -0.046844482421875, 0.0215606689453125, 0.056243896484375, -0.057342529296875, -0.00782012939453125, 0.019287109375, -0.0169677734375, 0.042083740234375, -0.01047515869140625, -0.027587890625, 0.00014638900756835938, -0.04193115234375, 0.0135345458984375, 0.004512786865234375, -0.023712158203125, -0.01529693603515625, -0.0019588470458984375, -0.0291595458984375, -0.02978515625, 0.0208282470703125, 0.0292816162109375, 0.0291595458984375, 0.0169830322265625, 0.04217529296875, 0.030426025390625, 0.0391845703125, 0.051116943359375, -0.00949859619140625, 0.0016641616821289062, -0.01345062255859375, 0.0010509490966796875, 0.0219879150390625, 0.0164031982421875, -0.016632080078125, -0.055267333984375, -0.043060302734375, 0.0008883476257324219, -0.00400543212890625, -0.0200347900390625, -0.007266998291015625, -0.07110595703125, -0.0411376953125, 0.0238494873046875, 0.0177459716796875, -0.002300262451171875, -0.0010957717895507812, 0.004611968994140625, 0.03857421875, 0.045623779296875, -0.01345062255859375, -0.020172119140625, 0.005931854248046875, -0.0224151611328125, 0.0186309814453125, -0.03692626953125, -0.0191497802734375, -0.0021038055419921875, 0.0276031494140625, -0.059051513671875, 0.026336669921875, -0.03814697265625, -0.04571533203125, -0.01171112060546875, 0.0307159423828125, -0.0005292892456054688, 0.0241851806640625, 0.00803375244140625, 0.032135009765625, -0.033660888671875, 0.03338623046875, 0.061737060546875, 0.01000213623046875, -0.01441192626953125, 0.0070037841796875, -0.037750244140625, -0.0239410400390625, 0.0209197998046875, -0.0517578125, 0.0029850006103515625, 0.038818359375, 0.0245361328125, 0.01708984375, -0.01453399658203125, 0.0589599609375, -0.03546142578125, -0.01189422607421875, -0.049072265625, 0.00897216796875, -0.023712158203125, -0.00415802001953125, 0.0007443428039550781, -0.0256805419921875, -0.00391387939453125, 0.004512786865234375, 0.014556884765625, 0.026702880859375, 0.0313720703125, 0.031951904296875, -0.027069091796875, 0.0291595458984375, 0.02362060546875, 0.04791259765625, 0.037750244140625, -0.0279388427734375, 0.0280914306640625, 0.019317626953125, -0.00952911376953125, 0.006809234619140625, -0.033111572265625, 0.00390625, 0.01123046875, 0.00978851318359375, -0.0217437744140625, 0.020782470703125, -0.01427459716796875, -0.0291595458984375, 0.016693115234375, 0.035125732421875, 0.0215911865234375, 0.0203704833984375, -0.0184326171875, -0.0194091796875, 0.0211944580078125, -0.00246429443359375, 0.0041656494140625, 0.01361846923828125, -0.050201416015625, 0.051116943359375, 0.00921630859375, -0.0055084228515625, -0.003063201904296875, -0.01062774658203125, 0.0014181137084960938, 0.00213623046875, 0.01873779296875, -0.01457977294921875, -0.0023956298828125, 0.0389404296875, -0.0031833648681640625, -0.033538818359375, -0.01708984375, 0.0002474784851074219, -0.034881591796875, -0.04931640625, 0.028289794921875, -0.01178741455078125, 0.019866943359375, -0.01268768310546875, -0.005245208740234375, -0.005237579345703125, 0.0125274658203125, 0.029083251953125, -0.0019741058349609375, 0.006275177001953125, -0.01934814453125, -0.03509521484375, 0.005462646484375, 0.0282135009765625, -0.048187255859375, -0.0160369873046875, 0.04827880859375, -0.0155792236328125, 0.008544921875, 0.01512908935546875, -0.0272369384765625, -0.0309600830078125, -0.059234619140625, -0.0015993118286132812, -0.0350341796875, -0.0251007080078125, 0.050933837890625, -0.0006337165832519531, -0.02740478515625, -0.0221099853515625, -0.0257110595703125, 0.026702880859375, -0.00421905517578125, 0.0280914306640625, 0.028900146484375, 0.0094757080078125, -0.01097869873046875, -0.02923583984375, -0.0212860107421875, 0.004825592041015625, 0.0255584716796875, -0.0294342041015625, 0.00959014892578125, 0.014251708984375, 0.020660400390625, 0.01003265380859375, -0.03143310546875, -0.003265380859375, 0.030181884765625, -0.0213623046875, 0.028594970703125, 0.04974365234375, -0.05438232421875, 0.01523590087890625, 0.0164337158203125, -0.0186614990234375, 0.00830841064453125, 0.060760498046875, -0.015777587890625, 0.07061767578125, 0.0157928466796875, 0.018341064453125, 0.036163330078125, 0.0264434814453125, 0.00530242919921875, 0.006160736083984375, 0.01274871826171875, -0.05438232421875, 0.036163330078125, -0.01207733154296875, 0.0167999267578125, -0.00661468505859375, 0.034271240234375, -0.0264129638671875, 0.059478759765625, -0.003787994384765625, 0.0673828125, 0.022552490234375, 0.00974273681640625, 0.036956787109375, -0.014862060546875, -0.0132293701171875, 0.009063720703125, 0.0085906982421875, 0.0012989044189453125, 0.06427001953125, -0.023651123046875, 0.0191802978515625, 0.006122589111328125, -0.0276336669921875, -0.010955810546875, 0.000308990478515625, -0.0009937286376953125, 0.0189971923828125, 0.0264129638671875, 0.0209808349609375, 0.008880615234375, 0.0171356201171875, 0.0224609375, 0.01255035400390625, -0.0106201171875, -0.02191162109375, -6.204843521118164e-05, -0.050506591796875, 0.00218963623046875, -0.030548095703125, 0.01369476318359375, -0.0341796875, 0.0058135986328125, -0.0211639404296875, -0.037017822265625, 0.00940704345703125, -0.0012731552124023438, -0.034210205078125, 0.006389617919921875, 0.0008244514465332031, 0.0135345458984375, 0.0244903564453125, 0.042877197265625, 0.032379150390625, -0.0015020370483398438, 0.01006317138671875, 0.0011501312255859375, -0.0491943359375, -0.006244659423828125, -0.003368377685546875, 0.0187530517578125, -0.039764404296875, 0.019287109375, 0.042266845703125, -0.0037937164306640625, -0.0198822021484375, -0.00969696044921875, 0.019744873046875, -0.0078277587890625, -0.0291900634765625, -0.0205841064453125, -0.01328277587890625, 0.0004062652587890625, -0.0078887939453125, 0.00908660888671875, -0.01517486572265625, 0.00878143310546875, -0.029205322265625, 0.0248870849609375, 0.01207733154296875, -0.004161834716796875, -0.0138397216796875, 0.024139404296875, -0.038543701171875, 0.00466156005859375, 0.015960693359375, 0.007282257080078125, 0.05291748046875, 0.0008330345153808594, -0.041229248046875, -0.01447296142578125, -0.0069732666015625, -0.0135498046875, 0.020660400390625, 0.00560760498046875, 0.0238800048828125, -0.00286102294921875, -0.01465606689453125, -0.0050506591796875, 0.037200927734375, 0.007137298583984375, 0.00571441650390625, 0.018646240234375, -0.027587890625, -0.027587890625, 0.004150390625, -0.0226898193359375, -0.043975830078125, -0.01523590087890625, -0.01544189453125, 0.00860595703125, -0.043365478515625, -0.037750244140625, -0.0161590576171875, -0.0017404556274414062, -0.006336212158203125, -0.0562744140625, 0.0026607513427734375, -0.0604248046875, -0.006256103515625, -0.01192474365234375, 0.0153961181640625, -0.003574371337890625, -0.0445556640625, 0.01519012451171875, 0.037445068359375, -0.040496826171875, 0.005077362060546875, -0.00991058349609375, -0.01678466796875, -0.0136566162109375, 0.0233154296875, -0.0787353515625, 0.01380157470703125, -0.047271728515625, -0.0276031494140625, 0.00688934326171875, -0.009796142578125, 0.0006351470947265625, 0.0166015625, 0.018768310546875, -0.0185546875, 0.00872802734375, -0.023773193359375, -0.00661468505859375, -0.0167999267578125, 0.0089111328125, 0.0200347900390625, -0.004016876220703125, -0.0026721954345703125, 0.03564453125, 0.01297760009765625, 0.0024356842041015625, 0.0306396484375, 0.0224456787109375, -0.00824737548828125, -0.00496673583984375, -0.027801513671875, 0.0149078369140625, 0.009857177734375, 0.01462554931640625, -0.01128387451171875, 0.0233917236328125, 0.0137176513671875, -0.006195068359375, -0.04833984375, 0.007534027099609375, -0.0154876708984375, -0.01300048828125, 0.024658203125, -0.06500244140625, -0.01262664794921875, -0.0100860595703125, -0.002330780029296875, 0.032623291015625, 0.03619384765625, -0.0102081298828125, -0.002166748046875, 0.0289459228515625, 0.0087127685546875, -0.0059814453125, 0.0179443359375, 0.05010986328125, 0.047821044921875, -0.00574493408203125, -0.04718017578125, 0.041839599609375, -0.021240234375, -0.0176849365234375, 0.042572021484375, 0.0169525146484375, -0.016998291015625, -0.024505615234375, -0.01015472412109375, -0.02374267578125, 0.00479888916015625, 0.01483154296875, -0.046295166015625, 0.01556396484375, -0.0053558349609375, -0.023345947265625, -0.013519287109375, -0.0301055908203125, 0.026580810546875, -0.005359649658203125, -0.00551605224609375, 0.03167724609375, -0.004123687744140625, 0.0244903564453125, -0.045135498046875, 0.00211334228515625, -0.0006990432739257812, -0.032867431640625, -0.005771636962890625, -0.037109375, 0.00664520263671875, -0.05133056640625, -0.00890350341796875, -0.0289154052734375, -0.02850341796875, -0.04193115234375, -0.01215362548828125, -0.004749298095703125, 0.0361328125, -0.0069122314453125, -0.0298614501953125, -0.01922607421875, 0.033782958984375, 0.0205230712890625, 0.01410675048828125, 0.008209228515625, -0.0059661865234375, -0.0038814544677734375, -0.0022678375244140625, 0.034149169921875, -0.0047760009765625, 0.044830322265625, 0.0013370513916015625, -0.032135009765625, -0.030303955078125, -0.0186309814453125, -0.032928466796875, 0.01534271240234375, -0.006374359130859375, -0.01548004150390625, 0.041473388671875, -0.0160064697265625, 0.023956298828125, 0.0096893310546875, 0.01244354248046875, -0.031982421875, -0.01995849609375, 0.006069183349609375, -0.00873565673828125, 0.00626373291015625, 0.0095977783203125, -0.003803253173828125, 0.0200042724609375, -0.045318603515625, -0.011077880859375, 0.003444671630859375, 0.0079803466796875, -0.005401611328125, -0.0389404296875, -0.0280609130859375, 0.0011053085327148438, 0.0187530517578125, -0.00860595703125, -0.0061492919921875, 0.01132965087890625, 0.0266571044921875, 0.01274871826171875, 0.01338958740234375, -0.0350341796875, -0.006664276123046875, 0.0233612060546875, 0.052642822265625, 0.014495849609375, -0.0216217041015625, -0.0214691162109375, -0.01061248779296875, -0.0025196075439453125, 0.0021514892578125, -0.0012445449829101562, -0.00827789306640625, 0.03857421875, 0.002994537353515625, 0.005756378173828125, -0.01212310791015625, -0.01474761962890625, 0.00794219970703125, -0.037200927734375, -0.0084228515625, 0.01149749755859375, -0.0269927978515625, -0.031402587890625, -0.006183624267578125, 0.02117919921875, 0.0103607177734375, -0.033203125, 0.00778961181640625, 0.01331329345703125, -0.0232391357421875, 0.00733184814453125, -0.016845703125, 0.0277557373046875, 0.01393890380859375, -0.06591796875, -0.0170440673828125, 0.027099609375, -0.039794921875, -0.014007568359375, -0.00789642333984375, 0.0081939697265625, 0.002590179443359375, 0.01380157470703125, -0.021484375, 0.020965576171875, -0.049041748046875, -0.004985809326171875, 0.00897979736328125, -0.0260467529296875, -0.0276947021484375, -0.00287628173828125, -0.011810302734375, 0.0390625, -0.0197906494140625, -0.034149169921875, 0.00661468505859375, -0.0009756088256835938, 0.0105438232421875, -0.002239227294921875, -0.002838134765625, -0.0214691162109375, 0.0034084320068359375, 0.0214385986328125, -0.00936126708984375, -0.02008056640625, 0.002567291259765625, 0.0212554931640625, 0.0140228271484375, -0.0206298828125, -0.001743316650390625, 0.0254669189453125, -0.000782012939453125, -0.0019121170043945312, 0.0445556640625, 0.023834228515625, 0.032623291015625, 0.0251922607421875, 0.020782470703125, 0.0278778076171875, -0.0167694091796875, 0.0105438232421875, 0.04779052734375, -0.0048828125, 0.0517578125, -0.0255126953125, -0.0034542083740234375, 0.01373291015625, 0.00677490234375, -0.0361328125, -0.0259246826171875, 0.013427734375, -0.04217529296875, -0.01544189453125, 0.043243408203125, 0.012420654296875, 0.0258331298828125, -0.007720947265625, -0.0014410018920898438, -0.00420379638671875, 0.0026092529296875, 0.0084228515625, 0.00868988037109375, 0.006107330322265625, 0.00807952880859375, 0.005107879638671875, -0.0022563934326171875, 0.015838623046875, -0.02886962890625, -0.0253448486328125, 0.0030956268310546875, 0.0030994415283203125, -0.0251007080078125, -0.0428466796875, 0.01349639892578125, 0.0174713134765625, 0.0137939453125, 0.05706787109375, 0.0176849365234375, 0.0206756591796875, 0.0208892822265625, 0.04144287109375, 0.0088043212890625, 0.0038604736328125, 0.008209228515625, 0.07611083984375, -0.004405975341796875, 0.004058837890625, -0.003353118896484375, 0.0014896392822265625, -0.01483154296875, 0.00463104248046875, -0.0180511474609375, 0.01044464111328125, -0.0180511474609375, -0.038421630859375, 0.01039886474609375, -0.0121002197265625, -0.0021724700927734375, -0.03704833984375, -0.019775390625, 0.0008993148803710938, -0.01511383056640625, -0.05413818359375, 0.0098419189453125, -0.01050567626953125, -0.0015897750854492188, 0.01309967041015625, 0.006343841552734375, -0.006870269775390625, -0.06890869140625, -0.0005159378051757812, -0.005908966064453125, 0.046051025390625, 0.002643585205078125, 0.001873016357421875, 0.0159149169921875, -0.0234832763671875, -0.019256591796875, 0.01111602783203125, -0.02044677734375, 0.019256591796875, 0.01097869873046875, -0.0302276611328125, -0.046844482421875, 0.004947662353515625, 0.0012598037719726562, -0.0081329345703125, 0.056182861328125, -0.0090179443359375, 0.020233154296875, -0.0267791748046875, -0.01499176025390625, 0.0180816650390625, -0.007411956787109375, 0.00449371337890625, 0.023590087890625, 0.01015472412109375, -0.043426513671875, 0.0155792236328125, -0.0168304443359375, 0.00992584228515625, -0.00901031494140625, -0.0286712646484375, -0.00901031494140625, 0.0248260498046875, 0.005367279052734375, -0.01314544677734375, 0.03753662109375, -0.01097869873046875, 0.00495147705078125, -0.0029926300048828125, 0.002643585205078125, -0.0117950439453125, -0.0006265640258789062, 0.0288238525390625, 0.0028591156005859375, -0.0089569091796875, -0.016357421875, 0.051666259765625, -0.0081024169921875, 0.026153564453125, -0.0130767822265625, 0.0259552001953125, 0.01103973388671875, 0.0018148422241210938, -0.029937744140625, -0.011322021484375, 0.0197296142578125, 0.0126953125, 0.0205230712890625, 0.0122833251953125, 0.042510986328125, 0.0017757415771484375, 0.01039886474609375, 0.037994384765625, 0.010833740234375, -0.006931304931640625, -0.0152130126953125, 0.07647705078125, -0.009185791015625, 0.0023593902587890625, -0.0119476318359375, -0.039886474609375, 0.024871826171875, 0.005523681640625, 0.00998687744140625, -0.00031828880310058594, 0.06103515625, -0.0184783935546875, -0.0008525848388671875, 0.0227203369140625, -0.0272674560546875, -0.0012531280517578125, -0.026153564453125, -0.0269927978515625, -0.007198333740234375, 0.0032558441162109375, 0.00506591796875, 0.0234222412109375, 0.0125274658203125, -0.0095062255859375, 0.0305633544921875, 0.0005183219909667969, -0.004970550537109375, 0.01302337646484375, -0.03375244140625, 0.0007238388061523438, -0.00012350082397460938, -0.048614501953125, 0.0019254684448242188, 0.0223236083984375, 0.028839111328125, -0.040557861328125, -0.03375244140625, -0.014739990234375, -0.022857666015625, -0.0255126953125, 0.044219970703125, 0.01065826416015625, 0.0252227783203125, 0.0306396484375, -0.0015087127685546875, 0.0166473388671875, 0.01280975341796875, -0.0254974365234375, 0.0161285400390625, 0.0138397216796875, 0.01062774658203125, 0.01702880859375, 0.00521087646484375, 0.0267791748046875, 0.00209808349609375, 0.01265716552734375, 0.042266845703125, -0.0082855224609375, -0.0055084228515625, 0.004180908203125, -0.0305023193359375, 0.01435089111328125, 0.0015707015991210938, -0.007053375244140625, 0.004009246826171875, -0.00656890869140625, 0.022003173828125, -0.045989990234375, 0.0228118896484375, -0.00933074951171875, -0.01088714599609375, 0.0389404296875, -0.01474761962890625, -0.00757598876953125, 0.0240478515625, 0.0191802978515625, 0.0226287841796875, -0.006542205810546875, 0.01406097412109375, 0.01079559326171875, -0.01690673828125, -0.00464630126953125, 0.00605010986328125, -0.036285400390625, -0.035369873046875, -0.0016565322875976562, -0.00864410400390625, -0.078369140625, 0.01390838623046875, 0.05755615234375, 0.0011186599731445312, -0.03857421875, 0.0379638671875, 0.022735595703125, -0.031829833984375, 0.0229949951171875, 0.00341033935546875, -0.0267791748046875, 0.007144927978515625, 0.025299072265625, 0.0272369384765625, 0.00940704345703125, -0.017913818359375, 0.0004203319549560547, -0.0460205078125, -0.003326416015625, 0.0013828277587890625, -0.0019178390502929688, -0.0006866455078125, 0.01453399658203125, 0.00496673583984375, -0.00928497314453125, -0.023284912109375, -0.0214996337890625, 0.0307464599609375, 0.0161285400390625, 0.005962371826171875, -0.018646240234375, -0.004116058349609375, -0.0226287841796875, 0.0089874267578125, 0.00780487060546875, -0.00162506103515625, -0.039398193359375, -0.0242462158203125, -0.01702880859375, -0.0011005401611328125, 0.01171875, -0.049224853515625, -0.01456451416015625, 0.00907135009765625, 0.007579803466796875, -0.034454345703125, -0.0096893310546875, -0.0153350830078125, 0.00677490234375, -0.02484130859375, -0.00079345703125, 0.00438690185546875, 0.0017328262329101562, 0.0220184326171875, -0.0289459228515625, 0.01393890380859375, 0.0129241943359375, -0.000499725341796875, 0.004150390625, 0.00563812255859375, -0.025848388671875, -0.0153350830078125, -0.014251708984375, -0.0186767578125, -0.0310821533203125, 0.003177642822265625, 0.0274658203125, -0.034393310546875, -0.01348876953125, 0.024871826171875, 0.0096282958984375, 0.01067352294921875, 0.00806427001953125, 0.01666259765625, 0.03656005859375, 0.021026611328125, -0.00617218017578125, -0.0019359588623046875, -0.0159454345703125, 0.01015472412109375, 0.0701904296875, 0.032135009765625, -0.0253448486328125, -0.0034046173095703125, -0.011199951171875, 0.0122528076171875, 0.01537322998046875, 0.036041259765625, -0.041595458984375, 0.0291290283203125, -0.0144805908203125, -0.0036296844482421875, -0.01291656494140625, -0.036651611328125, 0.01690673828125, -0.004123687744140625, -0.0280914306640625, 0.0008525848388671875, 0.002559661865234375, 0.01006317138671875, 0.019317626953125, 0.036895751953125, 0.00431060791015625, 0.00772857666015625, 0.0025310516357421875, 0.0027923583984375, -0.0090179443359375, -0.037200927734375, -0.01134490966796875, -0.0272369384765625, -0.00931549072265625, 0.0015859603881835938, 0.0031414031982421875, 0.0206451416015625, -0.0137939453125, 0.0027561187744140625, -0.0034694671630859375, -0.00751495361328125, -0.004512786865234375, 0.00955963134765625, -0.01059722900390625, -0.01451873779296875, -0.05718994140625, -0.022216796875, 0.0036754608154296875, -0.026702880859375, -0.01904296875, -0.031982421875, -0.0155792236328125, -0.0211944580078125, -0.004985809326171875, -0.0032958984375, -0.021575927734375, -0.0026721954345703125, 0.00812530517578125, -0.0253753662109375, 0.01727294921875, -0.04443359375, -0.04022216796875, -0.003082275390625, 0.01087188720703125, 0.0258026123046875, -0.0269317626953125, -0.04644775390625, 0.026336669921875, -0.041656494140625, -0.021087646484375, -0.0276031494140625, 0.0246124267578125, 0.0115966796875, -0.003696441650390625, 0.0198974609375, -0.047027587890625, -0.034912109375, -0.0009021759033203125, 0.01114654541015625, -0.03167724609375, -0.0200653076171875, -0.039306640625, -0.016143798828125, -0.0030384063720703125, -0.005954742431640625, -0.0031223297119140625, 0.0226898193359375, -0.00350189208984375, -0.017181396484375, -0.007022857666015625, -0.01399993896484375, -0.0019273757934570312, 0.016326904296875, -0.022247314453125, 0.0205841064453125, 0.0155029296875, 0.0236053466796875, 0.01500701904296875, -0.006717681884765625, 0.006984710693359375, 0.044342041015625, 0.0016145706176757812, 0.005863189697265625, -0.0021800994873046875, -0.01959228515625, -0.0228729248046875, 0.01824951171875, -0.0213470458984375, -0.0389404296875, -0.005100250244140625, -0.0184478759765625, 0.03631591796875, 0.00395965576171875, 0.01558685302734375, 0.03668212890625, 0.046844482421875, 0.00881195068359375, 0.007686614990234375, 0.0139617919921875, 0.037506103515625, -0.00873565673828125, 0.0240631103515625, 0.0052032470703125, -0.00719451904296875, -0.0280914306640625, -0.004909515380859375, -0.003948211669921875, -0.005405426025390625, 0.0223388671875, -0.00704193115234375, -0.0080718994140625, -0.06842041015625, -0.00026416778564453125, -0.04205322265625, 0.020355224609375, 0.006992340087890625, 0.00927734375, 0.006683349609375, 0.039825439453125, 0.001041412353515625, -0.01506805419921875, 0.0018939971923828125, -0.01433563232421875, 0.0135345458984375, -0.00296783447265625, 0.00015664100646972656, -0.01390838623046875, 0.0229034423828125, -0.037628173828125, 0.0089874267578125, -0.025787353515625, 0.01003265380859375, 0.0244293212890625, 0.01171112060546875, -0.037078857421875, 0.0225677490234375, 0.003177642822265625, 0.02276611328125, 0.041168212890625, 0.007701873779296875, 0.0214080810546875, -0.00629425048828125, -0.00031876564025878906, 0.00042629241943359375, 0.000579833984375, -0.000774383544921875, -0.053863525390625, 0.00152587890625, -0.01131439208984375, -0.00983428955078125, 0.002902984619140625, 0.003147125244140625, -0.01934814453125, 0.0134735107421875, -0.0298919677734375, 0.0188140869140625, -0.02734375, 0.01076507568359375, 0.002857208251953125, 0.01274871826171875, 0.01439666748046875, -0.0234832763671875, 0.05010986328125, 0.014984130859375, -0.00844573974609375, -0.01540374755859375, -0.0216217041015625, -0.017852783203125, 0.0061798095703125, 0.0280914306640625, -0.012451171875, 0.0037479400634765625, -0.0167999267578125, -0.01390838623046875, -0.02349853515625, -0.006694793701171875, -0.003936767578125, 0.02252197265625, 0.032989501953125, -0.00970458984375, 0.01300048828125, -0.0012035369873046875, -0.020782470703125, 0.02105712890625, 0.025543212890625, -0.01512908935546875, -0.005184173583984375, 0.00628662109375, 0.00628662109375, 0.0243988037109375, 0.0224609375, -0.0249786376953125, -0.006954193115234375, 0.01262664794921875, 0.03155517578125, 0.041351318359375, -0.0460205078125, 0.036529541015625, 0.00392913818359375, -0.00934600830078125, -0.00530242919921875, -0.054443359375, -0.00275421142578125, -0.021881103515625, -0.0019893646240234375, -0.01165771484375, -0.02984619140625, 0.0003933906555175781, -0.00395965576171875, -0.003871917724609375, -0.02105712890625, 0.0278472900390625, -0.011871337890625, -0.02130126953125, -0.0233917236328125, 0.0360107421875, -0.0181121826171875, 0.04779052734375, -0.0031566619873046875, -0.0180816650390625, 0.0116119384765625, -0.0006551742553710938, 0.027923583984375, -0.025726318359375, -0.01312255859375, -0.00345611572265625, -0.0265045166015625, -0.0181427001953125, 0.0017614364624023438, 0.002773284912109375, 0.0028743743896484375, -0.01016998291015625, 0.03436279296875, -0.050140380859375, -0.0198822021484375, 0.027313232421875, 0.026275634765625, -0.01314544677734375, -0.02191162109375, -0.02130126953125, 0.0081024169921875, -0.03515625, -0.0256195068359375, 0.0106201171875, -0.055877685546875, -0.01084136962890625, 0.005390167236328125, 0.0003273487091064453, 0.012420654296875, -0.010498046875, -0.0263214111328125, -0.04498291015625, 0.006694793701171875, -0.0194244384765625, -0.0158538818359375, -0.0406494140625, -0.01515960693359375, -0.009124755859375, -0.00870513916015625, 0.002513885498046875, 0.001987457275390625, 0.01279449462890625, -0.0029239654541015625, -0.0033931732177734375, -0.00514984130859375, -0.0005679130554199219, -0.0217132568359375, 0.040985107421875, -0.015777587890625, -0.00986480712890625, 0.018402099609375, 0.03387451171875, 0.0026493072509765625, -0.0019817352294921875, 0.0037364959716796875, -0.01015472412109375, 0.00292205810546875, 0.005474090576171875, 0.01065826416015625, 0.0222625732421875, -0.004001617431640625, -0.005584716796875, 0.0205841064453125, 0.002239227294921875, -0.01386260986328125, 0.00673675537109375, 0.0190582275390625, -0.0186309814453125, 0.04754638671875, 0.0094146728515625, 0.00856781005859375, -0.022369384765625, -0.0153961181640625, 0.005535125732421875, 0.007350921630859375, 0.00032782554626464844, 0.034912109375, -0.01055908203125, -0.00949859619140625, -0.00434112548828125, 0.005523681640625, 0.0018072128295898438, 0.0303955078125, 0.0022430419921875, -0.037750244140625, 0.0110321044921875, -0.0115203857421875, 0.051605224609375, 0.0140838623046875, -0.007495880126953125, 0.041839599609375, 0.024627685546875, -0.004077911376953125, 0.020294189453125, -0.0202484130859375, 0.003849029541015625, -0.022735595703125, 0.00580596923828125, 0.004528045654296875, -0.0038280487060546875, 0.0033054351806640625, -0.01279449462890625, -0.01439666748046875, -0.0274810791015625, 0.0133514404296875, 0.015655517578125, -0.00664520263671875, -0.0203857421875, 0.01059722900390625, 0.020416259765625, -0.0273590087890625, -0.01131439208984375, 0.020599365234375, 0.0058746337890625, 0.03302001953125, -0.03875732421875, 0.036529541015625, -0.015899658203125, -0.0177459716796875, 0.05560302734375, -0.03765869140625, -0.04473876953125, 0.010955810546875, 0.0119171142578125, 0.0100250244140625, -0.006626129150390625, 0.03961181640625, 0.01277923583984375, 0.00946044921875, 0.034088134765625, -0.0287017822265625, -0.02947998046875, 0.01409149169921875, -0.035675048828125, -0.01560211181640625, -0.0121917724609375, 0.01125335693359375, -0.0218505859375, -0.0235748291015625, -0.0017766952514648438, -0.05010986328125, 0.00981903076171875, -0.03826904296875, 0.01904296875, -0.06036376953125, -0.015716552734375, -0.0099334716796875, -0.007167816162109375, -0.01708984375, -0.041259765625, 0.0106964111328125, 0.009307861328125]}, "text_id_to_ref_doc_id": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": "60e4ed57-c96b-4ac4-9288-190c23e041b9"}, "metadata_dict": {"109f6a35-bd9d-49a3-aff6-69f45940a7fc": {"_node_type": "TextNode", "document_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9", "doc_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9", "ref_doc_id": "60e4ed57-c96b-4ac4-9288-190c23e041b9"}}}
|