栏目分类
热点资讯
Python开发个人Ai搜索引擎
发布日期:2024-11-04 09:44 点击次数:176
Python,学霸 简洁
大家好!今天给你们带来了python flask AI搜索引擎,主要功能是搜索和通过ai摘要。使用的是阿里云qwen-max。
图片
演示地址https://ai.zhizhuya.cn/后端
from flask import Flask, render_template, request, jsonifyfrom http import HTTPStatusimport dashscopeimport mechanicalsoupfrom bs4 import BeautifulSoupfrom urllib.parse import urlparse, parse_qs, quoteapp = Flask(__name__)dashscope.api_key = "sk-XXX"history = []def crawl_pages(query_text, page_num=2): browser = mechanicalsoup.Browser() query_text_encoded = quote(query_text) results = [] for page_index in range(1, page_num+1): url = f"https://search.cctv.com/search.php?qtext={query_text_encoded}&type=web&page={page_index}" page = browser.get(url) soup = BeautifulSoup(page.text, 'html.parser') web_content_links = soup.find_all('a', id=lambda x: x and x.startswith('web_content_')) for i, link in enumerate(web_content_links): target_page = parse_qs(urlparse(link['href']).query).get('targetpage', [None])[0] results.append({'title': link.text, 'url': target_page}) return resultsdef generate_text(model, prompt, seed=1234, top_p=0.8, result_format='message', enable_search=False, max_tokens=1500, temperature=1.0, repetition_penalty=1.0): response = dashscope.Generation.call( model=model, prompt=prompt, seed=seed, top_p=top_p, result_format=result_format, enable_search=enable_search, max_tokens=max_tokens, temperature=temperature, repetition_penalty=repetition_penalty, history=history ) if response.status_code == HTTPStatus.OK: generated_text = response['output']['choices'][0]['message']['content'] history.append({"user": prompt, "bot": generated_text}) # 将用户输入和模型输出添加到历史记录中 return {"status": "success", "response": generated_text} else: return {"status": "error", "message": 'Request id: %s, Status code: %s, error code: %s, error message: %s' % ( response.request_id, response.status_code, response.code, response.message )}@app.route('/', methods=['GET'])def index(): chat_history = history return render_template('index.html', history=chat_history)@app.route('/generate-text', methods=['POST'])def generate_text_api(): prompt = request.json['prompt'] result = generate_text('qwen-max', prompt) return jsonify(result)@app.route('/clear', methods=['POST'])def clear(): global history history = [] return '', HTTPStatus.NO_CONTENT@app.route('/search', methods=['GET', 'POST'])def search(): if request.method == 'POST': keyword = request.form['keyword'] elif request.method == 'GET': keyword = request.args.get('keyword', '') else: keyword = '' results = crawl_pages(keyword) output = "" for result in results: output += f"<li><a id='myID' href='javascript:void(0);' onclick='handleLinkClick(\"{result['url']}\")'>{result['title']}</a></li><br>" return output@app.route('/page_content')def page_content(): url = request.args.get('url', '') if not url: return '缺少 url 参数' browser = mechanicalsoup.Browser() page = browser.get(url) page.encoding = 'utf-8' # 指定页面的编码为 utf-8 soup = BeautifulSoup(page.text, 'html.parser') all_text = '' all_images = [] # 获取页面中所有文本内容 for element in soup.find_all(['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'span']): all_text += element.get_text() + ' ' # 获取页面中所有图片链接 for img in soup.find_all('img'): img_src = img.get('src') if img_src: all_images.append("https:"+img_src) return f"文本内容: {all_text}<br>图片链接: {', '.join(all_images)}"if __name__ == '__main__': app.run(debug=True)前端
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Chat with AI</title> <style> body { display: flex; flex-direction: column; height: 100vh; margin: 0; font-family: Arial, sans-serif; } .website-container { position: fixed; top: 0; right: 0; width: 350px; height: 100%; border: 1px solid #ccc; overflow-y: auto; background-color: #f9f9f9; padding: 10px; } .chat-container { height: 100%; width: 85%; overflow: hidden; overflow-y: auto; padding: 10px; margin-right: 220px; /* 腾出右侧栏的宽度 */ } .chat-container::-webkit-scrollbar { display: none; } .avatar-user { width: 40px; height: 40px; background-color: #7fb8e7; /* 设置用户头像颜色 */ border-radius: 50%; /* 将头像设置为圆形 */ margin-left: 10px; /* 调整头像与消息之间的间距 */ } .avatar-bot { width: 40px; height: 40px; right: 0; background-color: #28a745; /* 设置机器人头像颜色 */ border-radius: 50%; /* 将头像设置为圆形 */ margin-right: 10px; /* 调整头像与消息之间的间距 */ object-fit: cover; /* 防止头像变形 */ } .message { display: flex; align-items: center; /* 垂直居中消息和头像 */ margin-bottom: 1rem; } .message-text { padding: 10px; word-wrap: break-word; border-radius: 6px; max-width: 70%; margin:100px; } .message-text-user { padding: 10px; border-radius: 6px; max-width: 70%; margin:100px; word-wrap: break-word; background-color: #ececec; } .user-message { display: flex; justify-content: flex-end; } .bot-message .message-text { background-color: #2ea44f; color: white; } .input-container { position: fixed; bottom: 0; left: 0; width: calc(100% - 220px); /* 考虑右侧栏的宽度 */ display: flex; align-items: center; background-color: #f9f9f9; padding: 10px; } .input-field { flex-grow: 1; padding: 0.75rem; border: 1px solid #d1d5da; border-radius: 6px; margin-right: 1rem; } .send-button { padding: 0.75rem 1rem; background-color: #2ea44f; color: white; border: none; border-radius: 6px; cursor: pointer; } .del-button { padding: 0.75rem 1rem; background-color: #aeaeae; color: white; border: none; margin-right: 10px; border-radius: 6px; cursor: pointer; } .send-button:disabled { opacity: 0.5; cursor: not-allowed; } .typing-indicator { position: absolute; margin-bottom:50px font-size: 0.8rem; color: #586069; } .typing:before, .typing:after { content: ''; display: inline-block; width: 0.75rem; height: 0.75rem; border-radius: 50%; margin-right: 0.25rem; animation: typing 1s infinite; } @keyframes typing { 0% { transform: scale(0); } 50% { transform: scale(1); } 100% { transform: scale(0); } } /* 样式定义 */.listView { list-style-type: none; margin: 0; padding: 0;}.listView li { background-color: #f4f4f4; padding: 10px; margin-bottom: 5px; box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); transition: box-shadow 0.3s ease;}.listView li:hover { box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.2);}.listView li a { text-decoration: none; color: #333; display: block; transition: color 0.3s ease;}.listView li a:hover { color: #ff6600;} </style></head><body style="display: flex; flex-direction: column; height: 100vh;"> <div id="website-container" class="website-container"> <ul class="listView" id="listView"></ul> </div> <div style="height: 90%; width:80%; overflow-y: auto; display: flex;"> <ul class="chat-container" id="chat-container"> {% for item in history %} {% if loop.index == 1 %} <li class="message user-message"> <div class="message-text-user">{{ item.user }}</div> <div class="avatar-user"></div> </li> <li class="message bot-message"> <div class="avatar-bot"></div> <div class="message-text">{{ item.bot }}</div> </li> {% else %} <li class="message user-message"> <div class="message-text-user">{{ item.user }}</div> <div class="avatar-user"></div> </li> <li class="message bot-message"> <div class="avatar-bot"></div> <div class="message-text">{{ item.bot }}</div> </li> {% endif %} {% endfor %} </ul> </div> <form class="input-container" id="input-form" method="POST" style="position: fixed; bottom: 0; left: 0; width: 65%;"> <button type="button" class="del-button" id="del-button" style="width: 100px;"onclick='del()'>清除</button> <input type="text" placeholder="你负责搜,我负责找" class="input-field" id="input-field" name="prompt" autocomplete="off" style="width: calc(100% - 100px);"> <button type="submit" class="send-button" id="send-button" disabled style="width: 100px;">搜索</button> </form> <script> const inputForm = document.getElementById('input-form'); const inputField = document.getElementById('input-field'); const chatContainer = document.getElementById('chat-container'); inputField.addEventListener('input', () => { const userInput = inputField.value.trim(); document.getElementById('send-button').disabled = !userInput; }); inputForm.addEventListener('submit', async (event) => { event.preventDefault(); const userInput = inputField.value.trim(); const chatContainer = document.getElementById('chat-container'); if (!userInput) { return; } const userMessage = createMessageElement(userInput, 'user-message',"message-text-user","avatar-user"); chatContainer.appendChild(userMessage); inputField.value = ''; chatContainer.scrollTop = chatContainer.scrollHeight; inputField.disabled = true; document.getElementById('send-button').disabled = true; showTypingAnimation(userMessage); const aa = document.getElementById('listView'); aa.innerHTML = await getA(userInput); const response = await generateText(userInput); hideTypingAnimation(userMessage); if (response.status === 'success') { const botResponse = createMessageElement(response.response, 'bot-message',"message-text","avatar-bot"); chatContainer.appendChild(botResponse); printMessageText(botResponse); } else { alert(response.message); } inputField.disabled = false; inputField.focus(); }); async function generateText(prompt) { const response = await fetch('/generate-text', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt }) }); return await response.json(); } async function getA(prompt) { const response = await fetch(`/search?keyword=${prompt}`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); return await response.text();} function createMessageElement(text, className,name,bot) { const message = document.createElement('li'); message.classList.add('message', className, 'typing'); if (bot=="avatar-bot"){ message.innerHTML = ` <div class=${bot}></div> <div class=${name}>${text}</div> `; }else{ message.innerHTML = ` <div class=${name}>${text}</div> <div class=${bot}></div> `; } return message; } function showTypingAnimation(element) { const chatContainer = document.getElementById('chat-container'); chatContainer.scrollTop = chatContainer.scrollHeight+10 ; const rect = element.getBoundingClientRect(); const topPosition = rect.top + window.scrollY + rect.height; const leftPosition = rect.left + window.scrollX; const typingIndicator = document.createElement('div'); typingIndicator.classList.add('typing-indicator'); typingIndicator.style.top = `${topPosition}px`; typingIndicator.style.left = `${leftPosition}px`; typingIndicator.innerHTML = '思考中...'; document.body.appendChild(typingIndicator); } function hideTypingAnimation(element) { const typingIndicator = document.querySelector('.typing-indicator'); if (typingIndicator) { typingIndicator.remove(); } element.classList.remove('typing'); } // 添加逐字打印效果 function printMessageText(message) { const chatContainer = document.getElementById('chat-container'); const text = message.querySelector('.message-text'); const textContent = text.textContent; text.textContent = ''; for (let i = 0; i < textContent.length; i++) { setTimeout(() => { text.textContent += textContent.charAt(i); chatContainer.scrollTop = chatContainer.scrollHeight ; }, i * 10); // 控制打印速度 } } async function handleLinkClick(link) { const content = await getPageContent(link); console.log(link); console.log(content); const userMessage = createMessageElement("总结中:"+link, 'user-message',"message-text-user","avatar-user"); showTypingAnimation(userMessage); const chatContainer = document.getElementById('chat-container'); chatContainer.appendChild(userMessage); const response = await generateText("总结内容:"+content); hideTypingAnimation(userMessage); if (response.status === 'success') { const botResponse = createMessageElement(response.response, 'bot-message',"message-text","avatar-bot"); chatContainer.appendChild(botResponse); printMessageText(botResponse); } else { alert(response.message); }} function del(url) { const response = fetch(`/clear`, { method: 'POST' }); location.replace("/"); return 0;}// 获取页面内容async function getPageContent(url) { const response = await fetch(`/page_content?url=${url}`, { method: 'GET' }); return await response.text();} </script></body></html>本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。
上一篇:我是如何在5分钟之内写出AI爆文结构化提示词(附50条优化指令)
下一篇:没有了