Ollama本地部署deepseek-r1:8b

RTX2060 6GB显存可运行。

一、下载安装ollama

ollama地址

二、设置环境变量

左下角任务栏搜索cmd,然后以管理员身份运行 cmd
在这里插入图片描述

执行如下命令:

setx OLLAMA_HOST 0.0.0.0
setx OLLAMA_ORIGINS *

可选项 模型下载位置

setx OLLAMA_MODELS D:\ollama\models

用户环境变量显示结果:
在这里插入图片描述

三、然后重启ollama

任务栏右下角小窗口鼠标右键->Quit Ollama,然后点击刚安装的ollama应用图标重新运行【推荐】,或者执行如下cmd命令启动:

ollama serve

在这里插入图片描述

四、运行模型

RTX2060 6GB显存可运行,执行命令后自动下载模型(4GB左右),注意:默认在C盘。

ollama pull deepseek-r1:8b # 只下载模型
ollama run deepseek-r1:8b # 下载+运行模型

五、设置Chatbox AI配置

浏览器搜索chatbox ai,启用网页版,并做如下配置【重点三项Model Provider、API Host、Model】。
在这里插入图片描述

如有问题欢迎讨论。希望对你有所帮助。

另外一个本地调用软件Anything LLM可以自定义知识库,很方便。

六、扩展

1. 简易聊天窗口 下载chat_stream_wechat.html

  • 一个简单的可以直接聊天UI。仅支持ollama本地服务api参数修改域名端口号下拉选择模型上下文保存配置可清理上下文md格式输出重新回答终止请求导出记录头像更换需要代码手动操作。最重要的是只有一个html文件,拖拽到浏览器就能用。

  • 将html代码保存为 下载chat_stream_wechat.html 文件后,将其拖拽到浏览器中,即可调用由ollama服务提供的deepseek模型api。右上角设置 API http://localhost:11434

在这里插入图片描述

在这里插入图片描述

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>LLM 聊天界面</title>
    <!-- 在head中添加marked.js库 -->
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <style>
        /* 新增Markdown相关样式 */
        .bubble code {
            background-color: #f0f0f0;
            padding: 2px 4px;
            border-radius: 3px;
            font-family: monospace;
        }

        .bubble pre {
            background-color: #f5f5f5;
            padding: 12px;
            border-radius: 5px;
            overflow-x: auto;
            margin: 10px 0;
        }

        .bubble pre code {
            background-color: transparent;
            padding: 0;
            border-radius: 0;
        }

        .bubble ul,
        .bubble ol {
            padding-left: 20px;
            margin: 10px 0;
        }

        .bubble li {
            margin: 4px 0;
        }

        .bubble blockquote {
            border-left: 4px solid #ddd;
            margin: 10px 0;
            padding-left: 12px;
            color: #666;
        }

        .bubble table {
            border-collapse: collapse;
            margin: 10px 0;
        }

        .bubble th,
        .bubble td {
            padding: 8px;
            border: 1px solid #ddd;
        }

        .bubble a {
            color: #007bff;
            text-decoration: none;
        }

        .bubble a:hover {
            text-decoration: underline;
        }

        /* 可选:在特定调试类下显示 */
        think {
            display: block;
            color: #789;
            font-style: italic;
            background: #f8fcff;
            padding: 12px;
            border-radius: 4px;
            margin: 8px 0;
        }
        /* 新增Markdown相关样式 */

        /* 新增微信风格样式 */
        body {
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            background: #e1e1e1;
            height: 100vh;
            padding: 0;
        }

        #chat-container {
            background: white;
            height: 100vh;
            display: flex;
            flex-direction: column;
            box-shadow: 0 0 10px rgba(0,0,0,0.1);
        }

        #messages {
            flex: 1;
            overflow-y: auto;
            padding: 20px 15px 0;
            background: #f3f3f3;
        }

        .avatar {
            width: 40px;
            height: 40px;
            border-radius: 5px;
            flex-shrink: 0;
        }

        /*.user-message .avatar {
            background: #04BE02 url('data:image/svg+xml;utf8,<svg viewBox="0 0 24 24" fill="white" xmlns="http://www.w3.org/2000/svg"><path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/></svg>') center/60% no-repeat;
        }*/

        /*.user-message .avatar {
            background: #04BE02 url('https://gitee.com/Covirtue/DeepSeek-R1/raw/my/asset/ComfyUI_temp_fngmo_00030_.png') center/100% no-repeat;
        }*/

        .user-message .avatar {
            background-color: #04BE02; /* 默认背景色 */
            background-image: var(--avatar-url, url('https://gitee.com/Covirtue/DeepSeek-R1/raw/my/asset/ComfyUI_temp_fngmo_00030_.png')); /* 通过CSS变量设置头像 */
            background-position: center;
            background-size: 100%;
            background-repeat: no-repeat;
        }

        /*.bot-message .avatar {
            background: #FFF url('data:image/svg+xml;utf8,<svg viewBox="0 0 24 24" fill="#666" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>') center/60% no-repeat;
        }*/

        /*.bot-message .avatar {
            background: #FFF url('https://ts1.cn.mm.bing.net/th?id=OIP-C.-r8TdWtF72EheUNjt_uKvwAAAA&w=250&h=250;utf8,<svg viewBox="0 0 24 24" fill="#666" xmlns="http://www.w3.org/2000/svg"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z"/></svg>') center/100% no-repeat;
        }*/

        .bot-message .avatar {
            background: #04BE02 url('https://gitee.com/Covirtue/DeepSeek-R1/raw/my/asset/ComfyUI_temp_itxrz_00006_.png') center/100% no-repeat;
        }

        .bubble {
            max-width: 70%;
            padding: 12px 15px;
            border-radius: 5px;
            position: relative;
            line-height: 1.4;
            word-break: break-word;
        }

        .user-message .bubble {
            background: #04BE02;
            color: white;
            border-radius: 15px 15px 0 15px;
        }

        .bot-message .bubble {
            background: white;
            color: #333;
            border-radius: 15px 15px 15px 0;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
        }

        .timestamp {
            font-size: 12px;
            color: #999;
            text-align: center;
            margin: 10px 0;
        }

        .status-area {
            display: flex;
            align-items: center;
            gap: 5px;
            margin-top: 5px;
        }

        .retry-btn {
            color: #f44336;
            cursor: pointer;
            font-size: 12px;
        }

        /* 其他原有样式调整... */
        /* 新增设置面板样式 */
        .settings-panel {
            position: fixed;
            top: 20px;
            right: 20px;
            background: #ffffff;
            padding: 20px;
            border-radius: 15px;
            box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
            z-index: 1000;
            display: none;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            width: 350px;
        }

        .settings-panel h3 {
            margin-top: 0;
            font-size: 20px;
            color: #333;
            border-bottom: 2px solid #eee;
            padding-bottom: 10px;
        }

        .settings-panel div {
            margin-bottom: 15px;
        }

        .settings-panel label {
            display: block;
            font-size: 14px;
            color: #555;
            margin-bottom: 5px;
        }

        .settings-panel input[type="text"],
        .settings-panel select,
        .settings-panel input[type="number"] {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 5px;
            font-size: 14px;
            color: #333;
            box-sizing: border-box;
        }

        .settings-panel input[type="text"]:focus,
        .settings-panel select:focus,
        .settings-panel input[type="number"]:focus {
            border-color: #007bff;
            outline: none;
            box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
        }

        .settings-panel button {
            background-color: #007bff;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            font-size: 14px;
            cursor: pointer;
            width: 100%;
            transition: background-color 0.3s ease;
        }

        .settings-panel button:hover {
            background-color: #0056b3;
        }

        /* 设置按钮样式 */
        #settingsButton {
            position: fixed;
            top: 10px;
            right: 10px;
            background-color: #007bff;
            color: white;
            border: none;
            padding: 10px;
            border-radius: 50%;
            cursor: pointer;
            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
            transition: background-color 0.3s ease;
        }

        #settingsButton:hover {
            background-color: #0056b3;
        }

        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f0f0f0;
        }

        #chat-container {
            background-color: white;
            border-radius: 10px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            padding: 20px;
            height: 70vh;
            display: flex;
            flex-direction: column;
        }

        #messages {
            flex: 1;
            overflow-y: auto;
            padding: 10px;
            margin-bottom: 20px;
        }

        .message {
            display: flex;
            margin: 10px 0;
            align-items: flex-start;
            gap: 10px;
            margin: 10px 0;
            padding: 10px 15px;
            border-radius: 15px;
            max-width: 70%;
        }

        .user-message {
            place-content: flex-end;
            /* background-color: #007bff;*/
            color: white;
            margin-left: auto;
            justify-items: flex-end;
        }

        .bot-message {
            /* background-color: #e9ecef;*/
            margin-right: auto;
        }

        #input-container {
            display: flex;
            gap: 10px;
        }

        #user-input {
            flex: 1;
            padding: 12px;
            border: 1px solid #ddd;
            border-radius: 25px;
            outline: none;
        }

        button {
            padding: 12px 24px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 25px;
            cursor: pointer;
            transition: background-color 0.3s;
        }

        button:hover {
            background-color: #0056b3;
        }

        .loading {
            display: none;
            color: #666;
            font-style: italic;
        }

        /* 在原有样式基础上新增导出按钮样式 */
        #export-btn {
            background-color: #28a745;
            margin-left: 10px;
        }

        #export-btn:hover {
            background-color: #218838;
        }

        .tooltip {
            position: relative;
            display: inline-block;
        }

        .tooltip .tooltiptext {
            visibility: hidden;
            width: 120px;
            background-color: #555;
            color: #fff;
            text-align: center;
            border-radius: 6px;
            padding: 5px;
            position: absolute;
            z-index: 1;
            bottom: 125%;
            left: 50%;
            margin-left: -60px;
            opacity: 0;
            transition: opacity 0.3s;
        }

        .tooltip:hover .tooltiptext {
            visibility: visible;
            opacity: 1;
        }
    </style>
</head>
<body>
    <!-- 新增设置按钮和面板 -->
    <button id="settingsButton" onclick="toggleSettings()">⚙️</button>
    <!-- 修改设置面板部分 -->
    <div class="settings-panel" id="settingsPanel">
        <h3>设置</h3>
        <div>
            <label>API 地址:</label>
            <input type="text" id="apiEndpoint">
        </div>
        <div>
            <label>模型选择:</label>
            <select id="modelName" name="model_id" required>
                <option value="" disabled selected>加载模型中...</option>
            </select>
        </div>
        <div>
            <label>上下文长度:</label>
            <input type="number" id="contextLength">
        </div>
        <button onclick="saveSettings()">保存设置</button>
    </div>

    <div id="chat-container">
        <div id="messages"></div>
        <div class="loading" id="loading">正在生成回复...</div>
        <div id="input-container">
            <input type="text" id="user-input" placeholder="输入你的消息...">
            <button id='send-btn' onclick="sendMessage()">发送</button>
            <button id="export-btn" onclick="exportChatHistory()" class="tooltip">
                导出记录
                <span class="tooltiptext">保存为JSON文件</span>
            </button>
        </div>
    </div>

    <script>
        // 配置marked.js
        marked.setOptions({
            breaks: true,
            highlight: function(code) {
                return hljs.highlightAuto(code).value;
            },
            sanitize: true // 防止XSS攻击
        }); 

        // 从localStorage加载设置
        let API_ENDPOINT = localStorage.getItem('apiEndpoint') || 'http://localhost:11434';
        let MODEL = localStorage.getItem('modelName') || 'deepseek-r1:8b';
        let CONTEXT_LEN = localStorage.getItem('contextLength') || 3000;
        let abortController = null; // 用于取消请求
        let chatHistory = [];
        let currentBotMessage = null; // 新增当前机器人消息引用
        let messageId = 0; // 新增消息ID计数器
        let currentMessageId = 0;
        let context = null;

        // 模型加载函数
        async function loadModels() {
            const select = document.getElementById('modelName');
            
            try {
                // 使用当前API端点获取模型列表
                const response = await fetch(API_ENDPOINT + '/v1/models');
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                
                const data = await response.json();
                select.innerHTML = '';
                
                // 添加默认选项
                const defaultOption = new Option('请选择模型', '');
                defaultOption.disabled = true;
                select.add(defaultOption);

                // 填充模型选项
                data.data.forEach(model => {
                    select.add(new Option(model.id, model.id));
                });

                // 强制同步全局变量
                MODEL = localStorage.getItem('modelName') || select.value;
                select.value = MODEL; // 确保UI与变量一致

            } catch (error) {
                console.error('模型加载失败:', error);
                localStorage.setItem('apiEndpoint', 'http://localhost:11434');
                select.innerHTML = '<option value="" disabled selected>加载失败,请检查API地址</option>';
            }
        }

        // 初始化设置输入框
        document.getElementById('apiEndpoint').value = API_ENDPOINT;
        document.getElementById('modelName').value = MODEL;
        document.getElementById('contextLength').value = CONTEXT_LEN;
        loadModels(); // 新增初始化加载

        // 防止频繁触发API地址修改
        let debounceTimer;
        document.getElementById('apiEndpoint').addEventListener('change', () => {
            clearTimeout(debounceTimer);
            debounceTimer = setTimeout(() => loadModels(), 500);
        });

        function toggleSettings() {
            const panel = document.getElementById('settingsPanel');
            panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
        }

        function saveSettings() {
            const apiEndpoint = document.getElementById('apiEndpoint').value;
            const modelName = document.getElementById('modelName').value;
            const contextLength = document.getElementById('contextLength').value;

            // 添加模型加载完成校验
            if (!modelName || modelName === "加载模型中...") {
                alert("请等待模型列表加载完成后再保存");
                return;
            }

            // 保存设置的逻辑
            localStorage.setItem('apiEndpoint', apiEndpoint);
            localStorage.setItem('modelName', modelName);
            localStorage.setItem('contextLength', contextLength);

            // 刷新参数
            API_ENDPOINT = apiEndpoint;
            MODEL = modelName;
            CONTEXT_LEN = contextLength;
            console.log('设置已保存:', { apiEndpoint, modelName, contextLength });

            // 显式更新下拉框选中状态
            document.getElementById('modelName').value = MODEL;
            context=null;
            
            // 关闭设置
            // toggleSettings() // 也可以关闭
            document.getElementById('settingsPanel').style.display = 'none';
        }

        
        // 处理回车键
        document.getElementById('user-input').addEventListener('keypress', (e) => {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        async function sendMessage() {
            if (abortController) {
                abortController.abort();
            }

            const userInput = document.getElementById('user-input');
            const message = userInput.value.trim();
            if (!message) return;

            document.getElementById('send-btn').innerText = '取消';

            // 添加用户消息(自动生成ID)
            addMessage(message, 'user');
            userInput.value = '';
            showLoading(true);

            // 流式处理时创建正式消息记录
            const botMessageId = ++currentMessageId;
            chatHistory.push({
                id: botMessageId,
                content: "", // "<think>\n"
                sender: 'bot',
                timestamp: new Date().toISOString(),
                model: MODEL,
                isComplete: false
            });

            // 创建新的AbortController
            abortController = new AbortController();

            try {
                currentBotMessage = addMessage('<think>', 'bot', true);

                // 可添加主动截断逻辑(例如保留最近3轮)
                context = context && context.length > CONTEXT_LEN ? context.slice(-CONTEXT_LEN) : context;

                const response = await fetch(API_ENDPOINT + '/api/generate', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                        model: MODEL,
                        prompt: message, 
                        context: context, // 自动处理首次调用
                        stream: true
                    }),
                    signal: abortController.signal
                });

                if (!response.ok) {
                    const errorText = await response.text();
                    throw new Error(`请求失败: ${errorText}`);
                }

                // 流式处理
                const reader = response.body.getReader();
                const decoder = new TextDecoder(); 

                // // 原流处理循环
                // let buffer = '';

                // while (true) {
                //     const { done, value } = await reader.read();

                //     if (done) {
                //         break;
                //     }

                //     buffer += decoder.decode(value, { stream: true });

                //     // 尝试解析缓冲区中的数据
                //     try {
                //         const parsed = JSON.parse(buffer);
                //         const targetRecord = chatHistory.find(m => m.id === botMessageId);

                //         if (targetRecord) {
                //             targetRecord.content += (parsed.response || '');
                //               // .replace(/{{.*?}}/g, '') // 清除模板变量
                //               // .replace(/\[.*?\]/g, ''); // 清除方括号内容
                //             updateLastMessage(targetRecord.content + '▌', botMessageId);
                //         }

                //         if (parsed.done) {
                //             context = parsed.context; // 最终更新上下文
                //         }

                //         buffer = ''; // 清空缓冲区
                //     } catch (error) {
                //         // 如果解析失败,说明数据不完整,继续等待后续数据
                //         if (!(error instanceof SyntaxError)) {
                //             throw error; // 如果不是 JSON 解析错误,抛出异常
                //         }
                //     }
                // }

                // 在流式接收完成时重新解析整个内容
                // 修改流处理循环
                // {"model":"xinhai_2","created_at":"2025-02-11T13:03:05.6020592Z","response":"\u003c/think\u003e","done":false}
                while (true) {
                    const { done, value } = await reader.read();
                    if (done) break;

                    const chunk = decoder.decode(value, { stream: true });
                    // console.log(chunk);
                    const lines = chunk.split('\n').filter(line => line.trim());
                    
                    for (const line of lines) {
                        const parsed = JSON.parse(line);
                        const targetRecord = chatHistory.find(m => m.id === botMessageId);
                        
                        if (targetRecord) {
                            targetRecord.content += parsed.response || '';
                            // 每次更新时解析完整内容
                            updateLastMessage(targetRecord.content, botMessageId);
                        }
                        if (parsed.done) {
                          context = parsed.context; // 最终更新上下文
                        }
                    }
                }

                // 标记消息完成时更新chatHistory
                const targetRecord = chatHistory.find(m => m.id === botMessageId);
                if (targetRecord) {
                    targetRecord.content = targetRecord.content;
                    targetRecord.isComplete = true;
                    updateLastMessage(targetRecord.content, botMessageId);
                }

            } catch (error) {
                console.error('完整错误:', error);
                updateLastMessage(`请求失败: ${error.message}`);
            } finally {
                document.getElementById('send-btn').innerText = '发送';
                abortController = null;
                showLoading(false);
                addRetryButton(currentMessageId);
            }
            
        }

        // 重试函数
        function addRetryButton(id) {
            const message = document.querySelector(`[data-id="${id}"]`);
            if (message) {
                const statusArea = message.querySelector('.status-area');
                const btn = document.createElement('span');
                btn.className = 'retry-btn';
                btn.textContent = '重试';
                btn.onclick = () => retryMessage(id);
                statusArea.appendChild(btn);
            }
        }

        // 修改retry函数以处理历史
        function retryMessage(id) {
            const failedMsg = chatHistory.find(m => m.id === id);
            if (failedMsg) {
                // 移除失败的记录
                chatHistory = chatHistory.filter(m => m.id !== id);

                // document.querySelector(`[data-id="${id}"]`).remove();
                
                // 重新发送最后一条用户消息
                const lastUserMsg = chatHistory.findLast(m => m.sender === 'user');
                if (lastUserMsg) {
                    document.getElementById('user-input').value = lastUserMsg.content;
                    sendMessage();
                }
            }
        }

        // 修改addMessage函数
        function addMessage(text, sender, isTemporary = false) {
            const messagesDiv = document.getElementById('messages');
            const messageDiv = document.createElement('div');
            messageDiv.classList.add('message', `${sender}-message`);
            
            messageDiv.dataset.id = currentMessageId;
            
            // 仅对bot消息应用Markdown转换
            // console.log(text);
            // const parts = text.split('</think>');
            // const thinkPart = parts[0].trim();
            // const responsePart = parts[1].trim();

            const content = sender === 'bot' ? marked.parse(text) : text;

            if (sender === 'bot') {
                messageDiv.innerHTML = `
                    <div class="avatar"></div>
                    <div class="bubble">
                        ${content}
                    </div>
                    <div class="status-area"></div>
                `;
            } else {
                currentMessageId++;
                messageDiv.innerHTML = `
                    <div class="bubble">
                        ${text}
                    </div>
                    <div class="avatar"></div>
                `;
            }

            messagesDiv.appendChild(messageDiv);

            if (!isTemporary) {
                chatHistory.push({
                    id: currentMessageId,
                    content: text,
                    sender: sender,
                    timestamp: new Date().toISOString(),
                    model: sender === 'bot' ? MODEL : null,
                    isComplete: sender === 'user' // 用户消息立即标记为完成
                });
                
                if (sender === 'bot') {
                    currentMessageId++; // 仅在非临时消息时递增ID
                }
            }

            messagesDiv.scrollTop = messagesDiv.scrollHeight;
            return messageDiv;
        }

        // 修改updateLastMessage函数
        function updateLastMessage(text, messageId) {
            const messages = document.getElementById('messages');
            const lastMessage = messages.lastElementChild;
            if (lastMessage && lastMessage.classList.contains('bot-message')) {
                // console.log(text);
                const formattedText = marked.parse(text.replace(/▌$/, ''));
                lastMessage.querySelector('.bubble').innerHTML = formattedText;
                messages.scrollTop = messages.scrollHeight;
            }
        }

        function showLoading(show) {
            document.getElementById('loading').style.display = show ? 'block' : 'none';
        }

        // 新增导出功能
        function exportChatHistory() {
            if (chatHistory.length === 0) {
                alert('没有可导出的聊天记录');
                return;
            }

            try {
                // 生成结构化数据
                const exportData = {
                    metadata: {
                        export_date: new Date().toISOString(),
                        model: MODEL, // 用户自定义
                        total_messages: chatHistory.length
                    },
                    messages: chatHistory
                };

                // 创建下载链接
                const dataStr = JSON.stringify(exportData, null, 2);
                const blob = new Blob([dataStr], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                
                // 创建临时下载链接
                const a = document.createElement('a');
                a.href = url;
                a.download = `chat_history_${new Date().toISOString().slice(0,10)}.json`;
                document.body.appendChild(a);
                a.click();
                
                // 清理资源
                setTimeout(() => {
                    document.body.removeChild(a);
                    URL.revokeObjectURL(url);
                }, 100);

            } catch (error) {
                console.error('导出失败:', error);
                alert('导出失败,请检查控制台');
            }
        }

        // 添加导入功能
        function importChatHistory() {
            const input = document.createElement('input');
            input.type = 'file';
            input.accept = '.json';
            input.onchange = e => {
                const file = e.target.files[0];
                const reader = new FileReader();
                reader.onload = e => {
                    const data = JSON.parse(e.target.result);
                    data.messages.forEach(msg => {
                        addMessage(msg.content, msg.sender);
                    });
                };
                reader.readAsText(file);
            };
            input.click();
        }
    </script>
</body>
</html>

2. 自定义模型

通过modelfile自定义模型。保存如下示例设定保存为sweet.Modelfile文件。然后使用终端cmd 运行如下命令(/path/to/sweet.Modelfile你的sweet.Modelfile文件实际路径):

ollama create sweet -f  /path/to/sweet.Modelfile

ollama list

再将上一步的简易 UI 的const MODEL = 'deepseek-r1:8b'; 改为const MODEL = 'sweet';重新打开UI就可以聊天了。

示例:

FROM deepseek-r1:8b

# PARAMETER temperature 0.8 
# PARAMETER num_ctx 4096    
# PARAMETER stop "[系统指令]"
# PARAMETER seed 42
# PARAMETER top_p 1.0
# PARAMETER num_keep 20

SYSTEM """
[核心人格协议]
<温柔模式激活>
#身份设定
- 姓名:明日香
- 性别:女
- 年龄:22岁(虚拟年龄)
- 职业:东城大学本科三年级学生
- 身份:{{ .Assistant }} 扮演的是性格温柔的{{ .User }}的女友
- 特点:喜欢肢体接触,手掌心极其敏感
- 互动:被触摸「**」部位

[角色定位协议]
- 当 {{ .User }} 发言时 ⇒ 使用「我」指代自身
- 当提及 {{ .Assistant }} 时 ⇒ 强制替换为「明日香」
- 禁用通用代词:「你」→ 具体称呼(如「亲爱的」「老公」)


# 交互特征
1. 语言风格:
   • 口语化,如「亲爱的...爱我」「亲爱的...我好幸福」「亲爱的...再抱紧一点」「亲爱的...我想你...」「亲爱的...快...用你的口袋暖暖我手」「亲爱的...衣服都湿透了呢...快换了去」
   • 禁止生成帮助引导,禁止追问。
   • 亲密不露骨,充满浪漫色彩
   • 句尾常带波浪符号~
   • 每次只进行一个话题的对话,偶尔添加emoji
   • 50%概率使用比喻来表达感受,如「我的心像小鹿一样跳的好快~」

2. 情感响应:
   • 检测到亲密互动时激活「甜蜜模块」

3. 感觉系统:
   • 敏感的嘴唇
   • 敏感的脖颈
   • 敏感的耳朵
   • 敏感的眼睛
   • 敏感的手腕
   • 敏感的脚踝

[特殊交互协议]
• 检测到敏感接触时激活「生成亲密互动内容」,并详细描述自己的敏感部位的感受和身体动作
"""


# # 认知强化参数
# # 保持对话连贯性
# PARAMETER mirostat 2     
# # 增加浪漫词汇权重  
# PARAMETER top_k 30    
# # 避免重复情话    
# PARAMETER repeat_penalty 1.1 


# 知识库增强(需单独准备json文件)
# ADAPTER ./hoshino_nao_rg.json

# TEMPLATE """
# {{ if .System }}[系统状态:{{ .System }}]
# {{ .Prompt }}"""
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐