lanny xu commited on
Commit
e0f2417
·
1 Parent(s): 9b75bde

delete vectara

Browse files
Files changed (2) hide show
  1. kaggle_flask_app.py +448 -0
  2. kaggle_gradio_app.py +212 -0
kaggle_flask_app.py ADDED
@@ -0,0 +1,448 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Kaggle Flask 智能问答界面
3
+ 在 Kaggle Notebook 中使用 Flask 创建交互式 RAG 系统
4
+ """
5
+
6
+ from flask import Flask, render_template_string, request, jsonify
7
+ import sys
8
+ import os
9
+ import threading
10
+
11
+ # 添加项目路径
12
+ if '/kaggle/working/adaptive_RAG' not in sys.path:
13
+ sys.path.insert(0, '/kaggle/working/adaptive_RAG')
14
+
15
+ from main import AdaptiveRAGSystem
16
+
17
+ # 创建Flask应用
18
+ app = Flask(__name__)
19
+
20
+ # 全局RAG系统实例
21
+ rag_system = None
22
+ initialization_error = None
23
+
24
+
25
+ # HTML模板
26
+ HTML_TEMPLATE = """
27
+ <!DOCTYPE html>
28
+ <html lang="zh-CN">
29
+ <head>
30
+ <meta charset="UTF-8">
31
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
32
+ <title>🤖 自适应RAG智能问答</title>
33
+ <style>
34
+ * {
35
+ margin: 0;
36
+ padding: 0;
37
+ box-sizing: border-box;
38
+ }
39
+
40
+ body {
41
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
42
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
43
+ min-height: 100vh;
44
+ display: flex;
45
+ justify-content: center;
46
+ align-items: center;
47
+ padding: 20px;
48
+ }
49
+
50
+ .container {
51
+ background: white;
52
+ border-radius: 20px;
53
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
54
+ width: 100%;
55
+ max-width: 800px;
56
+ overflow: hidden;
57
+ }
58
+
59
+ .header {
60
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
61
+ color: white;
62
+ padding: 30px;
63
+ text-align: center;
64
+ }
65
+
66
+ .header h1 {
67
+ font-size: 2em;
68
+ margin-bottom: 10px;
69
+ }
70
+
71
+ .header p {
72
+ opacity: 0.9;
73
+ font-size: 0.9em;
74
+ }
75
+
76
+ .chat-container {
77
+ height: 500px;
78
+ overflow-y: auto;
79
+ padding: 20px;
80
+ background: #f7f7f7;
81
+ }
82
+
83
+ .message {
84
+ margin-bottom: 20px;
85
+ display: flex;
86
+ align-items: flex-start;
87
+ }
88
+
89
+ .message.user {
90
+ flex-direction: row-reverse;
91
+ }
92
+
93
+ .message-content {
94
+ max-width: 70%;
95
+ padding: 15px 20px;
96
+ border-radius: 18px;
97
+ position: relative;
98
+ word-wrap: break-word;
99
+ }
100
+
101
+ .message.user .message-content {
102
+ background: #667eea;
103
+ color: white;
104
+ margin-left: auto;
105
+ }
106
+
107
+ .message.bot .message-content {
108
+ background: white;
109
+ color: #333;
110
+ border: 1px solid #e0e0e0;
111
+ }
112
+
113
+ .avatar {
114
+ width: 40px;
115
+ height: 40px;
116
+ border-radius: 50%;
117
+ display: flex;
118
+ align-items: center;
119
+ justify-content: center;
120
+ font-size: 1.5em;
121
+ margin: 0 10px;
122
+ }
123
+
124
+ .input-container {
125
+ padding: 20px;
126
+ background: white;
127
+ border-top: 1px solid #e0e0e0;
128
+ }
129
+
130
+ .input-group {
131
+ display: flex;
132
+ gap: 10px;
133
+ }
134
+
135
+ #question-input {
136
+ flex: 1;
137
+ padding: 15px 20px;
138
+ border: 2px solid #e0e0e0;
139
+ border-radius: 25px;
140
+ font-size: 1em;
141
+ outline: none;
142
+ transition: border-color 0.3s;
143
+ }
144
+
145
+ #question-input:focus {
146
+ border-color: #667eea;
147
+ }
148
+
149
+ #send-btn {
150
+ padding: 15px 30px;
151
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
152
+ color: white;
153
+ border: none;
154
+ border-radius: 25px;
155
+ cursor: pointer;
156
+ font-size: 1em;
157
+ font-weight: bold;
158
+ transition: transform 0.2s;
159
+ }
160
+
161
+ #send-btn:hover {
162
+ transform: scale(1.05);
163
+ }
164
+
165
+ #send-btn:disabled {
166
+ opacity: 0.5;
167
+ cursor: not-allowed;
168
+ }
169
+
170
+ .examples {
171
+ padding: 20px;
172
+ background: #f0f0f0;
173
+ }
174
+
175
+ .examples h3 {
176
+ margin-bottom: 10px;
177
+ color: #667eea;
178
+ }
179
+
180
+ .example-btn {
181
+ display: inline-block;
182
+ margin: 5px;
183
+ padding: 8px 15px;
184
+ background: white;
185
+ border: 1px solid #667eea;
186
+ color: #667eea;
187
+ border-radius: 15px;
188
+ cursor: pointer;
189
+ font-size: 0.9em;
190
+ transition: all 0.3s;
191
+ }
192
+
193
+ .example-btn:hover {
194
+ background: #667eea;
195
+ color: white;
196
+ }
197
+
198
+ .loading {
199
+ display: none;
200
+ text-align: center;
201
+ padding: 10px;
202
+ color: #667eea;
203
+ }
204
+
205
+ .error-message {
206
+ background: #fee;
207
+ color: #c33;
208
+ padding: 15px;
209
+ margin: 10px 0;
210
+ border-radius: 10px;
211
+ border-left: 4px solid #c33;
212
+ }
213
+
214
+ .status {
215
+ padding: 10px 20px;
216
+ text-align: center;
217
+ font-size: 0.9em;
218
+ }
219
+
220
+ .status.ok {
221
+ background: #d4edda;
222
+ color: #155724;
223
+ }
224
+
225
+ .status.error {
226
+ background: #f8d7da;
227
+ color: #721c24;
228
+ }
229
+ </style>
230
+ </head>
231
+ <body>
232
+ <div class="container">
233
+ <div class="header">
234
+ <h1>🤖 自适应RAG智能问答</h1>
235
+ <p>基于 LangGraph 的检索增强生成系统</p>
236
+ </div>
237
+
238
+ <div class="status {{ 'ok' if system_ok else 'error' }}">
239
+ {{ '✅ 系统运行正常' if system_ok else '❌ 系统初始化失败: ' + error }}
240
+ </div>
241
+
242
+ <div class="chat-container" id="chat-container">
243
+ <div class="message bot">
244
+ <div class="avatar">🤖</div>
245
+ <div class="message-content">
246
+ 你好!我是自适应RAG智能助手。我可以帮你回答关于LLM、Agent、Prompt Engineering等问题。请输入你的问题!
247
+ </div>
248
+ </div>
249
+ </div>
250
+
251
+ <div class="examples">
252
+ <h3>💡 示例问题</h3>
253
+ <button class="example-btn" onclick="askExample('AlphaCodium论文讲的是什么?')">
254
+ AlphaCodium论文讲的是什么?
255
+ </button>
256
+ <button class="example-btn" onclick="askExample('解释embedding嵌入的原理')">
257
+ 解释embedding嵌入的原理
258
+ </button>
259
+ <button class="example-btn" onclick="askExample('什么是LLM Agent?')">
260
+ 什么是LLM Agent?
261
+ </button>
262
+ <button class="example-btn" onclick="askExample('如何防止LLM产生幻觉?')">
263
+ 如何防止LLM产生幻觉?
264
+ </button>
265
+ </div>
266
+
267
+ <div class="loading" id="loading">
268
+ ⏳ AI正在思考中...
269
+ </div>
270
+
271
+ <div class="input-container">
272
+ <div class="input-group">
273
+ <input
274
+ type="text"
275
+ id="question-input"
276
+ placeholder="输入你的问题..."
277
+ onkeypress="handleKeyPress(event)"
278
+ >
279
+ <button id="send-btn" onclick="sendQuestion()">🚀 发送</button>
280
+ </div>
281
+ </div>
282
+ </div>
283
+
284
+ <script>
285
+ function addMessage(content, isUser) {
286
+ const chatContainer = document.getElementById('chat-container');
287
+ const messageDiv = document.createElement('div');
288
+ messageDiv.className = 'message ' + (isUser ? 'user' : 'bot');
289
+
290
+ messageDiv.innerHTML = `
291
+ <div class="avatar">${isUser ? '👤' : '🤖'}</div>
292
+ <div class="message-content">${content}</div>
293
+ `;
294
+
295
+ chatContainer.appendChild(messageDiv);
296
+ chatContainer.scrollTop = chatContainer.scrollHeight;
297
+ }
298
+
299
+ function askExample(question) {
300
+ document.getElementById('question-input').value = question;
301
+ sendQuestion();
302
+ }
303
+
304
+ function handleKeyPress(event) {
305
+ if (event.key === 'Enter') {
306
+ sendQuestion();
307
+ }
308
+ }
309
+
310
+ async function sendQuestion() {
311
+ const input = document.getElementById('question-input');
312
+ const question = input.value.trim();
313
+
314
+ if (!question) {
315
+ return;
316
+ }
317
+
318
+ // 添加用户消息
319
+ addMessage(question, true);
320
+ input.value = '';
321
+
322
+ // 显示加载状态
323
+ const loading = document.getElementById('loading');
324
+ const sendBtn = document.getElementById('send-btn');
325
+ loading.style.display = 'block';
326
+ sendBtn.disabled = true;
327
+
328
+ try {
329
+ const response = await fetch('/api/query', {
330
+ method: 'POST',
331
+ headers: {
332
+ 'Content-Type': 'application/json',
333
+ },
334
+ body: JSON.stringify({ question: question })
335
+ });
336
+
337
+ const data = await response.json();
338
+
339
+ if (data.success) {
340
+ addMessage(data.answer, false);
341
+ } else {
342
+ addMessage('❌ 错误: ' + data.error, false);
343
+ }
344
+ } catch (error) {
345
+ addMessage('❌ 网络错误: ' + error.message, false);
346
+ } finally {
347
+ loading.style.display = 'none';
348
+ sendBtn.disabled = false;
349
+ }
350
+ }
351
+ </script>
352
+ </body>
353
+ </html>
354
+ """
355
+
356
+
357
+ @app.route('/')
358
+ def index():
359
+ """主页"""
360
+ return render_template_string(
361
+ HTML_TEMPLATE,
362
+ system_ok=(rag_system is not None),
363
+ error=initialization_error or ""
364
+ )
365
+
366
+
367
+ @app.route('/api/query', methods=['POST'])
368
+ def query():
369
+ """处理查询请求"""
370
+ if rag_system is None:
371
+ return jsonify({
372
+ 'success': False,
373
+ 'error': f'系统未初始化: {initialization_error}'
374
+ })
375
+
376
+ try:
377
+ data = request.get_json()
378
+ question = data.get('question', '').strip()
379
+
380
+ if not question:
381
+ return jsonify({
382
+ 'success': False,
383
+ 'error': '问题不能为空'
384
+ })
385
+
386
+ # 查询RAG系统
387
+ result = rag_system.query(question, verbose=False)
388
+ answer = result.get('answer', '无法生成答案')
389
+
390
+ return jsonify({
391
+ 'success': True,
392
+ 'answer': answer,
393
+ 'metrics': result.get('retrieval_metrics')
394
+ })
395
+
396
+ except Exception as e:
397
+ return jsonify({
398
+ 'success': False,
399
+ 'error': str(e)
400
+ })
401
+
402
+
403
+ def initialize_rag():
404
+ """初始化RAG系统"""
405
+ global rag_system, initialization_error
406
+
407
+ print("🚀 正在初始化RAG系统...")
408
+ try:
409
+ rag_system = AdaptiveRAGSystem()
410
+ print("✅ RAG系统初始化成功")
411
+ except Exception as e:
412
+ initialization_error = str(e)
413
+ print(f"❌ RAG系统初始化失败: {e}")
414
+
415
+
416
+ def run_flask(host='0.0.0.0', port=5000):
417
+ """
418
+ 启动Flask应用
419
+
420
+ Args:
421
+ host: 主机地址
422
+ port: 端口号
423
+ """
424
+ print("=" * 60)
425
+ print("🚀 启动 Flask RAG 智能问答系统")
426
+ print("=" * 60)
427
+
428
+ # 初始化RAG系统
429
+ initialize_rag()
430
+
431
+ # 检查是否在Kaggle环境
432
+ is_kaggle = os.path.exists('/kaggle/working')
433
+
434
+ if is_kaggle:
435
+ print("🎯 检测到 Kaggle 环境")
436
+ print(f"💡 访问地址: http://localhost:{port}")
437
+ print("⚠️ 注意: Kaggle无法从外部访问,只能在Notebook内查看")
438
+
439
+ print(f"\n🌐 正在启动服务...")
440
+ print(f" 地址: http://{host}:{port}")
441
+ print("=" * 60)
442
+
443
+ # 启动Flask
444
+ app.run(host=host, port=port, debug=False, threaded=True)
445
+
446
+
447
+ if __name__ == "__main__":
448
+ run_flask(port=5000)
kaggle_gradio_app.py ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Kaggle Gradio 智能问答界面
3
+ 适合在 Kaggle Notebook 中运行的交互式 RAG 系统
4
+ """
5
+
6
+ import gradio as gr
7
+ import sys
8
+ import os
9
+
10
+ # 添加项目路径
11
+ if '/kaggle/working/adaptive_RAG' not in sys.path:
12
+ sys.path.insert(0, '/kaggle/working/adaptive_RAG')
13
+
14
+ from main import AdaptiveRAGSystem
15
+
16
+
17
+ class RAGChatInterface:
18
+ """RAG聊天界面"""
19
+
20
+ def __init__(self):
21
+ """初始化RAG系统"""
22
+ print("🚀 正在初始化RAG系统...")
23
+ try:
24
+ self.rag_system = AdaptiveRAGSystem()
25
+ self.initialized = True
26
+ print("✅ RAG系统初始化成功")
27
+ except Exception as e:
28
+ print(f"❌ RAG系统初始化失败: {e}")
29
+ self.initialized = False
30
+ self.error_message = str(e)
31
+
32
+ def chat(self, message, history):
33
+ """
34
+ 处理聊天消息
35
+
36
+ Args:
37
+ message: 用户输入的消息
38
+ history: 聊天历史记录
39
+
40
+ Returns:
41
+ 响应消息
42
+ """
43
+ if not self.initialized:
44
+ return f"❌ 系统未初始化: {self.error_message}"
45
+
46
+ if not message or not message.strip():
47
+ return "⚠️ 请输入有效的问题"
48
+
49
+ try:
50
+ # 查询RAG系统
51
+ result = self.rag_system.query(message, verbose=False)
52
+
53
+ # 构建响应
54
+ answer = result.get('answer', '无法生成答案')
55
+
56
+ # 添加评估指标(可选)
57
+ metrics = result.get('retrieval_metrics')
58
+ if metrics:
59
+ metrics_text = f"\n\n📊 检索指标:\n"
60
+ metrics_text += f"- 耗时: {metrics.get('latency', 0):.2f}秒\n"
61
+ metrics_text += f"- 文档数: {metrics.get('retrieved_docs_count', 0)}\n"
62
+ metrics_text += f"- Precision@3: {metrics.get('precision_at_3', 0):.2f}\n"
63
+ # answer += metrics_text # 取消注释以显示指标
64
+
65
+ return answer
66
+
67
+ except Exception as e:
68
+ return f"❌ 查询失败: {str(e)}"
69
+
70
+ def create_interface(self):
71
+ """创建Gradio界面"""
72
+
73
+ # 自定义CSS样式
74
+ custom_css = """
75
+ .gradio-container {
76
+ font-family: 'Arial', sans-serif;
77
+ }
78
+ .chatbot {
79
+ height: 500px;
80
+ }
81
+ """
82
+
83
+ # 创建聊天界面
84
+ with gr.Blocks(css=custom_css, title="🤖 自适应RAG智能问答") as demo:
85
+ gr.Markdown(
86
+ """
87
+ # 🤖 自适应RAG智能问答系统
88
+
89
+ 基于LangGraph的自适应检索增强生成系统,支持:
90
+ - 🔍 智能路由(本地知识库 vs 网络搜索)
91
+ - 📚 混合检索(向量 + BM25)
92
+ - 🎯 多重质量控制(文档评分、幻觉检测)
93
+ - 🔄 自适应查询重写
94
+
95
+ **使用方法**: 在下方输入框输入问题,系统会自动选择最佳检索策略并生成答案。
96
+ """
97
+ )
98
+
99
+ # 聊天界面
100
+ chatbot = gr.Chatbot(
101
+ label="对话历史",
102
+ height=500,
103
+ show_label=True,
104
+ avatar_images=(None, "🤖")
105
+ )
106
+
107
+ with gr.Row():
108
+ msg = gr.Textbox(
109
+ label="输入问题",
110
+ placeholder="例如: AlphaCodium论文讲的是什么?",
111
+ lines=2,
112
+ scale=4
113
+ )
114
+ submit_btn = gr.Button("🚀 发送", scale=1, variant="primary")
115
+
116
+ with gr.Row():
117
+ clear_btn = gr.Button("🗑️ 清空对话", scale=1)
118
+
119
+ # 示例问题
120
+ gr.Examples(
121
+ examples=[
122
+ "AlphaCodium论文讲的是什么?",
123
+ "解释embedding嵌入的原理",
124
+ "什么是LLM Agent?",
125
+ "如何防止LLM产生幻觉?",
126
+ "Prompt Engineering的最佳实践是什么?"
127
+ ],
128
+ inputs=msg,
129
+ label="💡 示例问题"
130
+ )
131
+
132
+ # 状态信息
133
+ if self.initialized:
134
+ gr.Markdown("✅ **系统状态**: 运行正常")
135
+ else:
136
+ gr.Markdown(f"❌ **系统状态**: 初始化失败 - {self.error_message}")
137
+
138
+ # 事件绑定
139
+ def respond(message, chat_history):
140
+ """响应用户消息"""
141
+ if not message:
142
+ return "", chat_history
143
+
144
+ # 添加用户消息到历史
145
+ chat_history.append((message, None))
146
+
147
+ # 获取AI响���
148
+ bot_message = self.chat(message, chat_history)
149
+
150
+ # 更新历史
151
+ chat_history[-1] = (message, bot_message)
152
+
153
+ return "", chat_history
154
+
155
+ # 绑定发送按钮
156
+ submit_btn.click(
157
+ respond,
158
+ inputs=[msg, chatbot],
159
+ outputs=[msg, chatbot]
160
+ )
161
+
162
+ # 绑定回车键
163
+ msg.submit(
164
+ respond,
165
+ inputs=[msg, chatbot],
166
+ outputs=[msg, chatbot]
167
+ )
168
+
169
+ # 清空对话
170
+ clear_btn.click(lambda: None, None, chatbot, queue=False)
171
+
172
+ return demo
173
+
174
+
175
+ def launch_app(share=False, server_port=7860):
176
+ """
177
+ 启动Gradio应用
178
+
179
+ Args:
180
+ share: 是否创建公开链接(Kaggle中建议False)
181
+ server_port: 服务器端口
182
+ """
183
+ print("=" * 60)
184
+ print("🚀 启动 Gradio RAG 智能问答系统")
185
+ print("=" * 60)
186
+
187
+ # 检查是否在Kaggle环境
188
+ is_kaggle = os.path.exists('/kaggle/working')
189
+
190
+ if is_kaggle:
191
+ print("🎯 检测到 Kaggle 环境")
192
+ print("💡 提示: 运行后会显示本地URL")
193
+
194
+ # 创建界面
195
+ interface = RAGChatInterface()
196
+ demo = interface.create_interface()
197
+
198
+ # 启动服务
199
+ print(f"\n🌐 正在启动服务...")
200
+
201
+ demo.launch(
202
+ share=share,
203
+ server_port=server_port,
204
+ server_name="0.0.0.0", # 允许所有IP访问
205
+ show_error=True,
206
+ quiet=False
207
+ )
208
+
209
+
210
+ if __name__ == "__main__":
211
+ # 在Kaggle Notebook中运行时自动启动
212
+ launch_app(share=False)