LevinAleksey commited on
Commit
26f1d37
·
verified ·
1 Parent(s): 3a9dec5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -53
app.py CHANGED
@@ -4,99 +4,114 @@ from huggingface_hub import InferenceClient
4
  from qdrant_client import QdrantClient
5
  from sentence_transformers import SentenceTransformer
6
 
7
- # --- КОНФИГУРАЦИЯ ---
8
- st.set_page_config(page_title="AI Assistant RAG", page_icon="🤖", layout="centered")
 
 
9
 
10
- # Настройки API (Берем из секретов)
11
  HF_TOKEN = os.getenv("HF_TOKEN")
12
  QDRANT_URL = os.getenv("QDRANT_URL")
13
  QDRANT_API_KEY = os.getenv("QDRANT_API_KEY")
14
 
15
- # Модель для чата
16
- MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
 
17
 
18
- # --- ИНИЦИАЛИЗАЦИЯ ---
19
  @st.cache_resource
20
  def load_resources():
21
- # 1. Клиент HF (Чат)
22
- hf_client = InferenceClient(MODEL_ID, token=HF_TOKEN)
23
 
24
- # 2. Клиент Qdrant (База знаний) - инициализируем, если есть ключи
25
  q_client = None
26
  if QDRANT_URL and QDRANT_API_KEY:
27
  try:
28
  q_client = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY)
29
- except:
30
- pass
 
31
 
32
- # 3. Модель для векторизации (чтобы искать в базе)
33
- # Используем маленькую и быструю модель, она скачается сама
34
  encoder = SentenceTransformer('all-MiniLM-L6-v2')
35
 
36
  return hf_client, q_client, encoder
37
 
38
  client, qdrant, encoder = load_resources()
39
 
40
- # --- ЛОГИКА RAG (ПОИСК) ---
41
  def get_context(query):
42
- if not qdrant:
43
- return "" # Если база не подключена, возвращаем пустоту
44
-
45
  try:
46
- # Превращаем вопрос пользователя в цифры (вектор)
47
  vector = encoder.encode(query).tolist()
48
 
49
- # Ищем похожие куски в базе (коллекция должна называться "knowledge_base")
50
  search_result = qdrant.search(
51
- collection_name="knowledge_base",
52
- query_vector=vector,
53
  limit=3
54
  )
55
-
56
- # Собираем найденный текст
57
- context_text = "\n\n".join([hit.payload.get("text", "") for hit in search_result])
58
- return context_text
59
  except Exception as e:
 
60
  return ""
61
 
62
- # --- ИНТЕРФЕЙС (КАК ПО ССЫЛКЕ) ---
63
- st.title("🤖 AI Assistant (RAG)")
64
- st.caption("Чат с базой знаний на Qwen 2.5")
65
-
66
  if "messages" not in st.session_state:
67
- st.session_state.messages = [{"role": "assistant", "content": "Привет! Я готов к работе. Чем помочь?"}]
68
 
69
  # Показываем историю
70
  for msg in st.session_state.messages:
71
- st.chat_message(msg["role"]).write(msg["content"])
 
72
 
73
- # Поле ввода
74
- if prompt := st.chat_input():
 
75
  st.session_state.messages.append({"role": "user", "content": prompt})
76
- st.chat_message("user").write(prompt)
 
77
 
78
- # 1. ИЩЕМ ИНФУ В QDRANT
79
  context = get_context(prompt)
80
 
81
- # 2. ФОРМИРУЕМ ПРОМПТ
82
- system_msg = """Ты полезный ассистент.
83
- Используй информацию из КОНТЕКСТА ниже, чтобы ответить на вопрос.
84
- Если в контексте нет ответа, отвечай опираясь на свои знания, но предупреди об этом.
85
- """
86
-
87
  if context:
88
- final_prompt = f"КОНТЕКСТ:\n{context}\n\nВОПРОС: {prompt}"
89
- else:
90
- final_prompt = prompt
91
 
92
- messages_api = [
93
- {"role": "system", "content": system_msg},
94
- {"role": "user", "content": final_prompt}
95
- ]
96
 
97
- # 3. ГЕНЕРИРУЕМ ОТВЕТ
98
  with st.chat_message("assistant"):
99
- stream = client.chat_completion(messages_api, max_tokens=1024, stream=True)
100
- response = st.write_stream(stream)
101
-
102
- st.session_state.messages.append({"role": "assistant", "content": response})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  from qdrant_client import QdrantClient
5
  from sentence_transformers import SentenceTransformer
6
 
7
+ # --- НАСТРОЙКИ ---
8
+ st.set_page_config(page_title="Sales AI + RAG", page_icon="💼", layout="centered")
9
+ st.title("💼 Виртуальный Отдел Продаж")
10
+ st.caption("Чат с базой знаний (RAG) на Qwen 2.5")
11
 
12
+ # --- КЛЮЧИ ---
13
  HF_TOKEN = os.getenv("HF_TOKEN")
14
  QDRANT_URL = os.getenv("QDRANT_URL")
15
  QDRANT_API_KEY = os.getenv("QDRANT_API_KEY")
16
 
17
+ if not HF_TOKEN:
18
+ st.error("⚠️ Нет HF_TOKEN!")
19
+ st.stop()
20
 
21
+ # --- ЗАГРУЗКА РЕСУРСОВ (ОДИН РАЗ) ---
22
  @st.cache_resource
23
  def load_resources():
24
+ # 1. Чат-модель
25
+ hf_client = InferenceClient("Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
26
 
27
+ # 2. База знаний (Qdrant)
28
  q_client = None
29
  if QDRANT_URL and QDRANT_API_KEY:
30
  try:
31
  q_client = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY)
32
+ print("✅ Qdrant подключен")
33
+ except Exception as e:
34
+ print(f"❌ Ошибка Qdrant: {e}")
35
 
36
+ # 3. Модель для поиска (Embeddings)
 
37
  encoder = SentenceTransformer('all-MiniLM-L6-v2')
38
 
39
  return hf_client, q_client, encoder
40
 
41
  client, qdrant, encoder = load_resources()
42
 
43
+ # --- ФУНКЦИЯ ПОИСКА В БАЗЕ (RAG) ---
44
  def get_context(query):
45
+ if not qdrant:
46
+ return ""
 
47
  try:
48
+ # Превращаем вопрос в вектор
49
  vector = encoder.encode(query).tolist()
50
 
51
+ # Ищем в коллекции "sales_knowledge" (или создадим её позже)
52
  search_result = qdrant.search(
53
+ collection_name="sales_knowledge",
54
+ query_vector=vector,
55
  limit=3
56
  )
57
+ # Собираем текст из найденного
58
+ return "\n\n".join([hit.payload.get("text", "") for hit in search_result])
 
 
59
  except Exception as e:
60
+ print(f"Ошибка поиска: {e}")
61
  return ""
62
 
63
+ # --- ЧАТ ---
 
 
 
64
  if "messages" not in st.session_state:
65
+ st.session_state.messages = []
66
 
67
  # Показываем историю
68
  for msg in st.session_state.messages:
69
+ with st.chat_message(msg["role"]):
70
+ st.markdown(msg["content"])
71
 
72
+ # Обработка ввода
73
+ if prompt := st.chat_input("Ваш вопрос..."):
74
+ # 1. Сохраняем вопрос юзера
75
  st.session_state.messages.append({"role": "user", "content": prompt})
76
+ with st.chat_message("user"):
77
+ st.markdown(prompt)
78
 
79
+ # 2. ИЩЕМ КОНТЕКСТ В QDRANT
80
  context = get_context(prompt)
81
 
82
+ # 3. Формируем системный промпт
83
+ system_instruction = "Ты — менеджер по продажам. Отвечай коротко и по делу."
 
 
 
 
84
  if context:
85
+ system_instruction += f"\n\nИспользуй эту информацию из базы знаний для ответа:\n{context}"
86
+ print(f"Нашел в базе: {context[:100]}...") # Для отладки в логах
 
87
 
88
+ # Собираем сообщения для API
89
+ api_messages = [{"role": "system", "content": system_instruction}]
90
+ for m in st.session_state.messages:
91
+ api_messages.append({"role": m["role"], "content": m["content"]})
92
 
93
+ # 4. Генерируем ответ
94
  with st.chat_message("assistant"):
95
+ message_placeholder = st.empty()
96
+ full_response = ""
97
+
98
+ try:
99
+ stream = client.chat_completion(
100
+ messages=api_messages,
101
+ max_tokens=512,
102
+ stream=True,
103
+ temperature=0.7
104
+ )
105
+
106
+ for chunk in stream:
107
+ content = chunk.choices[0].delta.content
108
+ if content:
109
+ full_response += content
110
+ message_placeholder.markdown(full_response + "▌")
111
+
112
+ message_placeholder.markdown(full_response)
113
+
114
+ except Exception as e:
115
+ st.error(f"Ошибка API: {e}")
116
+
117
+ st.session_state.messages.append({"role": "assistant", "content": full_response})