栏目分类

热点资讯

产品展示

你的位置:百家号官方网站 > 产品展示 > Python开发个人Ai搜索引擎

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>
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报。

Powered by 百家号官方网站 @2013-2022 RSS地图 HTML地图