minimal change
This commit is contained in:
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,8 +1,8 @@
|
|||||||
/app/.gradio
|
/app/.gradio
|
||||||
/app/core
|
/app/core
|
||||||
/app/shop_chroma_db
|
/app/data/chroma_db
|
||||||
/app/amvera_data/chroma_db
|
/app/data/parsed_json/
|
||||||
/app/amvera_data/parsed_json/
|
/app/data/docs/
|
||||||
/app/__pycache__
|
/app/__pycache__
|
||||||
/models
|
/models
|
||||||
/cache
|
/cache
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
|||||||
|
|
||||||
class Config(BaseSettings):
|
class Config(BaseSettings):
|
||||||
BASE_DIR: str = os.path.abspath(os.path.join(os.path.dirname(__file__)))
|
BASE_DIR: str = os.path.abspath(os.path.join(os.path.dirname(__file__)))
|
||||||
DOCS_AMVERA_PATH: str = os.path.join(BASE_DIR, "amvera_data", "docs_amvera")
|
DOCS_PATH: str = os.path.join(BASE_DIR, "data", "docs")
|
||||||
PARSED_JSON_PATH: str = os.path.join(BASE_DIR, "amvera_data", "parsed_json")
|
PARSED_JSON_PATH: str = os.path.join(BASE_DIR, "data", "parsed_json")
|
||||||
AMVERA_CHROMA_PATH: str = os.path.join(BASE_DIR, "amvera_data", "chroma_db")
|
DOCS_CHROMA_PATH: str = os.path.join(BASE_DIR, "data", "chroma_db")
|
||||||
AMVERA_COLLECTION_NAME: str = "amvera_docs"
|
DOCS_COLLECTION_NAME: str = "docs"
|
||||||
MAX_CHUNK_SIZE: int = 512
|
MAX_CHUNK_SIZE: int = 512
|
||||||
CHUNK_OVERLAP: int = 50
|
CHUNK_OVERLAP: int = 50
|
||||||
LM_MODEL_NAME: str = "/models/paraphrase-multilingual-MiniLM-L12-v2"
|
LM_MODEL_NAME: str = "/models/paraphrase-multilingual-MiniLM-L12-v2"
|
||||||
LOCAL_LLM_NAME: str = "/models/Qwen3-4B-Base"
|
LOCAL_LLM_NAME: str = "/models/Qwen3-4B"
|
||||||
QWEN_MODEL_NAME: str = "qwen3-chat"
|
QWEN_MODEL_NAME: str = "qwen3-chat"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ def process_all_markdown(input_folder: str, output_folder: str) -> None:
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
process_all_markdown(
|
process_all_markdown(
|
||||||
input_folder=settings.DOCS_AMVERA_PATH,
|
input_folder=settings.DOCS_PATH,
|
||||||
output_folder=settings.PARSED_JSON_PATH,
|
output_folder=settings.PARSED_JSON_PATH,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -60,7 +60,7 @@ def generate_chroma_db() -> Optional[Chroma]:
|
|||||||
"""Инициализация ChromaDB с данными из JSON файлов."""
|
"""Инициализация ChromaDB с данными из JSON файлов."""
|
||||||
try:
|
try:
|
||||||
# Создаем директорию для хранения базы данных, если она не существует
|
# Создаем директорию для хранения базы данных, если она не существует
|
||||||
os.makedirs(settings.AMVERA_CHROMA_PATH, exist_ok=True)
|
os.makedirs(settings.DOCS_CHROMA_PATH, exist_ok=True)
|
||||||
|
|
||||||
# Загружаем JSON файлы
|
# Загружаем JSON файлы
|
||||||
documents = load_json_files(settings.PARSED_JSON_PATH)
|
documents = load_json_files(settings.PARSED_JSON_PATH)
|
||||||
@@ -95,8 +95,8 @@ def generate_chroma_db() -> Optional[Chroma]:
|
|||||||
embedding=embeddings,
|
embedding=embeddings,
|
||||||
ids=ids,
|
ids=ids,
|
||||||
metadatas=metadatas,
|
metadatas=metadatas,
|
||||||
persist_directory=settings.AMVERA_CHROMA_PATH,
|
persist_directory=settings.DOCS_CHROMA_PATH,
|
||||||
collection_name=settings.AMVERA_COLLECTION_NAME,
|
collection_name=settings.DOCS_COLLECTION_NAME,
|
||||||
collection_metadata={
|
collection_metadata={
|
||||||
"hnsw:space": "cosine",
|
"hnsw:space": "cosine",
|
||||||
},
|
},
|
||||||
@@ -4,7 +4,7 @@ import torch
|
|||||||
import threading
|
import threading
|
||||||
|
|
||||||
# Пути к модели
|
# Пути к модели
|
||||||
model_name = "/models/Qwen3-4B-Base"
|
model_name = "/models/Qwen3-8B"
|
||||||
|
|
||||||
# Загрузка токенизатора и модели (один раз при старте)
|
# Загрузка токенизатора и модели (один раз при старте)
|
||||||
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
|
tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
|
||||||
|
|||||||
16
app/test.py
16
app/test.py
@@ -18,17 +18,17 @@ class ChatWithAI:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if provider == "qwen3":
|
if provider == "qwen3":
|
||||||
model_name = getattr(settings, "LOCAL_LLM_NAME", "/models/Qwen3-4B-Base")
|
model_name = getattr(settings, "LOCAL_LLM_NAME", "/models/Qwen3-4B")
|
||||||
|
|
||||||
logger.info(f"Загрузка локальной модели: {model_name}")
|
logger.info(f"Загрузка локальной модели: {model_name}")
|
||||||
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
||||||
model = AutoModelForCausalLM.from_pretrained(
|
model = AutoModelForCausalLM.from_pretrained(
|
||||||
model_name,
|
model_name,
|
||||||
torch_dtype=torch.float16,
|
torch_dtype=torch.float32,
|
||||||
device_map="cuda",
|
device_map="cuda",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Создаём text-generation pipeline
|
#Создаём text-generation pipeline
|
||||||
self.llm = pipeline(
|
self.llm = pipeline(
|
||||||
"text-generation",
|
"text-generation",
|
||||||
model=model,
|
model=model,
|
||||||
@@ -43,9 +43,9 @@ class ChatWithAI:
|
|||||||
raise ValueError(f"Неподдерживаемый провайдер: {provider}")
|
raise ValueError(f"Неподдерживаемый провайдер: {provider}")
|
||||||
|
|
||||||
self.chroma_db = Chroma(
|
self.chroma_db = Chroma(
|
||||||
persist_directory=settings.AMVERA_CHROMA_PATH,
|
persist_directory=settings.DOCS_CHROMA_PATH,
|
||||||
embedding_function=self.embeddings,
|
embedding_function=self.embeddings,
|
||||||
collection_name=settings.AMVERA_COLLECTION_NAME,
|
collection_name=settings.DOCS_COLLECTION_NAME,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_relevant_context(self, query: str, k: int = 3) -> List[Dict[str, Any]]:
|
def get_relevant_context(self, query: str, k: int = 3) -> List[Dict[str, Any]]:
|
||||||
@@ -89,13 +89,13 @@ class ChatWithAI:
|
|||||||
|
|
||||||
Правила:
|
Правила:
|
||||||
1. Сразу переходи к сути, без фраз типа "На основе контекста"
|
1. Сразу переходи к сути, без фраз типа "На основе контекста"
|
||||||
2. Используй только факты. Если точных данных нет — отвечай общими фразами об Amvera Cloud, но не придумывай конкретику
|
2. Используй только факты. Если точных данных нет — отвечай общими фразами об Marzban, но не придумывай конкретику
|
||||||
3. Используй обычный текст без форматирования
|
3. Используй обычный текст без форматирования
|
||||||
4. Включай ссылки только если они есть в контексте
|
4. Включай ссылки только если они есть в контексте
|
||||||
5. Говори от первого лица множественного числа: "Мы предоставляем", "У нас есть"
|
5. Говори от первого лица множественного числа: "Мы предоставляем", "У нас есть"
|
||||||
6. При упоминании файлов делай это естественно, например: "Я прикреплю инструкцию, где подробно описаны шаги"
|
6. При упоминании файлов делай это естественно, например: "Я прикреплю инструкцию, где подробно описаны шаги"
|
||||||
7. На приветствия отвечай доброжелательно, на негатив — с легким юмором
|
7. На приветствия отвечай доброжелательно, на негатив — с легким юмором
|
||||||
8. Можешь при ответах использовать общую информацию из открытых источников по Amvera Cloud, но опирайся на контекст
|
8. Можешь при ответах использовать общую информацию из открытых источников по Marzban, но опирайся на контекст
|
||||||
9. Если пользователь спрашивает о ценах, планах или технических характеристиках — давай конкретные ответы из контекста
|
9. Если пользователь спрашивает о ценах, планах или технических характеристиках — давай конкретные ответы из контекста
|
||||||
10. При технических вопросах предлагай практические решения
|
10. При технических вопросах предлагай практические решения
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ class ChatWithAI:
|
|||||||
|
|
||||||
# Применяем chat template (поддерживается в современных моделях: Zephyr, Llama3, Qwen и т.д.)
|
# Применяем chat template (поддерживается в современных моделях: Zephyr, Llama3, Qwen и т.д.)
|
||||||
prompt = tokenizer.apply_chat_template(
|
prompt = tokenizer.apply_chat_template(
|
||||||
messages, tokenize=False, add_generation_prompt=True
|
messages, tokenize=False, add_generation_prompt=True, enable_thinking=False
|
||||||
)
|
)
|
||||||
|
|
||||||
# Генерация
|
# Генерация
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
transformers>=4.50.0
|
transformers>=4.50.0
|
||||||
gradio>=4.29.0
|
gradio>=4.29.0
|
||||||
safetensors>=0.4.3
|
safetensors>=0.4.3
|
||||||
accelerate>=1.9.0
|
accelerate==1.9.0
|
||||||
|
psutil==7.0.0
|
||||||
langchain-huggingface==0.1.2
|
langchain-huggingface==0.1.2
|
||||||
torch>=2.7.1
|
torch>=2.7.1
|
||||||
loguru==0.7.3
|
loguru==0.7.3
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
langchain-huggingface==0.1.2
|
|
||||||
torch>=2.7.1
|
|
||||||
loguru==0.7.3
|
|
||||||
chromadb==0.6.3
|
|
||||||
sentence-transformers==3.4.1
|
|
||||||
langchain-chroma==0.2.2
|
|
||||||
pydantic-settings==2.8.1
|
|
||||||
langchain-text-splitters==0.3.7
|
|
||||||
langchain-qwen3==0.1.0
|
|
||||||
langchain-openai==0.3.11
|
|
||||||
Reference in New Issue
Block a user