导读
本文将带大家一步一步的在腾讯云HAI平台上部署deepseek,然后使用对外API+python+django+vue+elementUI做一个漂亮的法律咨询(律师)辅助平台工具。
包含部署过程、功能设计、开发平台过程、接口调通过程、实际测试等步骤。能为读者提供一个全面详细的新手指南,减少面对法律纠纷时候的分析成本。尤其是律师朋友们可以通过这个平台大大提高工作效率,减少脑细胞消耗!
先看看最终效果:(文末有可复制源码)
正文开始 !
纯新手向,白话流,没有过编程经验的小伙伴正好借此学习如何打造一个简单的web平台。
一、先在腾讯云HAI上部署deepseek
1.注册并登录腾讯云
首先先进入腾讯云官网并点击右上角进行注册:cloud.tencent.com/
注册后直接登录即可。
2.进入腾讯云HAI后台
网址如下:console.cloud.tencent.com/hai/instanc...
或在腾讯云顶部搜索:HAI ,结果第一条点击立即使用。
首次进入会提示需要授权,点击"同意授权"
3.新建应用
点击"新建",开始创造一个新应用吧!
在新建页面中,依次按照如图选择:
1. 选择应用 (肯定选deepseek-r1啊)
2.计费模式 (用完就关,要用再开)
3.地域 (选个离你最近的,网速快)
4.算力方案(我选的3.6块钱的,足够用了,擅长推理)
5.实例名称
6.云硬盘(默认200GB,足够用了,不能调更低了)
7.网络 (每台500GB,10兆宽带,足够用了)
8.协议(勾选上)
当一切配置完成后,点击右下角立即购买即可。
等待创建完成(需要几分钟),就可以在【算力管理】页面中看到这个实例【法律咨询(小律师)辅助平台】了。
友情提示(这个实例可以开机关机,在"更多"里操作即可。)
此刻让其保持开机状态:也就是运行中,即可开始后续步骤。
4. 配置和启动应用
点击算力链接,在弹出的选项中选择 JupyterLab,这样可以打开控制后台的页面。
(记下自己的 公网IP ,这个后面是有用的)
在打开的页面中,点击Terminal:(就会进入命令行的终端界面了)
接下来,我们将通过ollama工具来启动这个deepseek服务,命令如下(14b是我觉得还是可以用,有钱的上更大的)
ollama run deepseek-r1:14b
还记得之前的这个实例外面显示的公网IP么?
此刻这个公网IP + 端口6399 ,就是这个deepseek的远程网址了。在你自己的电脑浏览器可以直接输入以下网址测试了:
(注意:这个公网IP每次关机开机后可能都会变化,当然一旦服务平台启动了,也就不该轻易关机了)
如上图,看到这个显示:Ollama is running 就代表服务启动成功了。
之后我们在开发本地的网站平台的时候,就可以通过这个域名的接口来远程调用这个deepseek-r1的问答等功能了。
相当于我们最终要实现的web平台:法律咨询(小律师)辅助平台 的AI引擎已经弄好了,接下来就搞定平台的外壳即可。
二、本地开发一个web平台
1. 环境准备
我本地的环境版本为以下这些,各位其实可以用其他版本来开发,大版本号一样那代码和操作也基本差不多。
编程IDE:pycharm 专业版
Python : 3.7.6 然后以该版本的python的pip工具直接下载其他库即可自动安装适合的版本。
Django : 3.2.13
2. 创建django项目
-
自己本地电脑终端或cmd窗口输入命令:django-admin startproject FLZX
-
进入创建好的FLZX项目根目录:cd FLZX
-
创建具体app应用:django-admin startapp Myapp
创建好后,在pycharm中打开该项目,如图所示:
3.给django项目初始化
settings.py文件的修改如下
添加自己创建的Myapp,注释掉csrf中间件
设置语言和时区
设置可支持他人访问
在Myapp目录下手动创建static和templates俩个文件夹,用来存放网页模版和静态资源
在django项目根目录(Terminal面板)中执行一句同步sql的命令:python3 manage.py migrate
可以再执行一句创建超管的命令,然后按照提示输入邮箱、密码等即可:python3 manage.py createsuperuser
3. 开发法律咨询(小律师)辅助平台
html页面开发:
首先在templates文件夹内创建一个HTML文件。
取名为:Home.html (如下图,自动填充好了一些基本元素)
为了能访问这个html页面,我们需要先构建url 和 对应的def函数,并把他们三个给串联起来:
url就写在urls.py中:
views.py中写def:
接下来,就是开发这个Home.html了。
关于这个页面的设计,我的预想是有个一大大的输入框,用来填充遇到的案子描述。
然后有下方有单选框组,就是用来选定各个功能的。(包括:案子成功率,案子可参考的法律条目,起诉书或其他什么文件生成,还有可以想到的打赢官司的各种办法,还有可以参考的案例等)然后单选框组右侧有个输入框,用来输入一些具体的文案。
然后在单选框组下方还有个按钮,用来启动执行。点击执行按钮后,发送请求给后台
最后下面有个大大的deepseek回答展示区。
源码如下:(可复制)
python
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>DeepSeek法律智能助手专业版</title> <style> /* 添加以下样式 */ .loading { padding: 1.5rem; text-align: center; color: #2c5f9d; } .loader { display: inline-block; width: 20px; height: 20px; border: 3px solid #f3f3f3; border-radius: 50%; border-top: 3px solid #2c5f9d; animation: spin 1s linear infinite; margin-left: 10px; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .result-card { background: #f8fbfe; padding: 1.5rem; border-radius: 8px; border-left: 4px solid #2c5f9d; } .result-card h3 { color: #2c5f9d; margin-bottom: 1rem; } .result-card .content { line-height: 1.8; color: #444; } .result-card ul { padding-left: 2rem; margin: 1rem 0; } .result-card li { margin: 0.5rem 0; } .error { color: #dc3545; padding: 1rem; background: #ffeef0; border-radius: 6px; } :root { --primary-color: #2c5f9d; --accent-color: #3a7ab9; --text-dark: #1e3b50; } * { margin: 0; padding: 0; box-sizing: border-box; font-family: '微软雅黑', 'Segoe UI', sans-serif; } body { background: #f8fbfe; padding: 2rem; max-width: 1200px; margin: 0 auto; min-height: 100vh; } h2 { color: var(--text-dark); text-align: center; margin: 0 0 2rem; font-size: 2.2rem; letter-spacing: 1px; } /* 案件输入区 */ .case-input { width: 100%; height: 150px; padding: 1.2rem; border: 2px solid var(--primary-color); border-radius: 8px; margin-bottom: 1.5rem; resize: vertical; font-size: 1rem; line-height: 1.6; box-shadow: 0 2px 4px rgba(44, 62, 80, 0.1); } /* 控制面板 */ .control-panel { display: flex; gap: 1.5rem; margin-bottom: 1.5rem; } /* 横向单选框组 */ .radio-grid { flex: 1; background: white; padding: 1.5rem; border-radius: 10px; box-shadow: 0 3px 6px rgba(0,0,0,0.08); min-height: 180px; display: flex; flex-direction: column; } .radio-group { display: flex; flex-wrap: wrap; gap: 0.8rem; margin-top: 0.5rem; } .radio-item { flex: 1 1 calc(33.33% - 0.8rem); min-width: 200px; padding: 0.8rem; background: #f8fafd; border-radius: 6px; transition: all 0.2s; } .radio-item:hover { background: #f2f6fc; transform: translateY(-1px); } .radio-item input[type="radio"] { width: 16px; height: 16px; margin-right: 0.6rem; accent-color: var(--primary-color); } /* 参数输入区 */ .params-box { flex: 1; background: white; border-radius: 10px; padding: 1.5rem; box-shadow: 0 3px 6px rgba(0,0,0,0.08); min-height: 180px; display: flex; flex-direction: column; } .params-input { flex: 1; margin-top: 0.5rem; } .params-input textarea { width: 100%; height: 100%; padding: 1rem; border: 1px solid #dde3e9; border-radius: 6px; resize: none; font-size: 0.95rem; } /* 执行按钮 */ .execute-btn { align-self: flex-end; padding: 0.8rem 2rem; background: linear-gradient(135deg, var(--primary-color), var(--accent-color)); color: white; border: none; border-radius: 25px; font-size: 1rem; cursor: pointer; transition: all 0.3s; margin-top: 1rem; box-shadow: 0 3px 6px rgba(44, 95, 157, 0.2); } .execute-btn:hover { opacity: 0.9; transform: translateY(-1px); } /* 响应区 */ .response-area { background: white; border-radius: 10px; padding: 2rem; box-shadow: 0 4px 12px rgba(0,0,0,0.1); min-height: 300px; } .response-area h2 { color: var(--text-dark); margin-bottom: 1.5rem; font-size: 1.3rem; border-left: 4px solid var(--primary-color); padding-left: 1rem; } @media (max-width: 768px) { .control-panel { flex-direction: column; } .radio-item { flex: 1 1 100%; } } </style> </head> <body> <h2>DeepSeek法律智能助手</h2> <textarea class="case-input" placeholder="请详细描述法律案件(包含时间、地点、涉案人员、争议焦点等关键信息)..."></textarea> <div class="control-panel"> <!-- 功能选择区 --> <div class="radio-grid"> <h3>智能法律工具</h3> <div class="radio-group"> <label class="radio-item"> <input type="radio" name="function" checked> 胜率预测 </label> <label class="radio-item"> <input type="radio" name="function"> 法律条文 </label> <label class="radio-item"> <input type="radio" name="function"> 文书生成 </label> <label class="radio-item"> <input type="radio" name="function"> 诉讼策略 </label> <label class="radio-item"> <input type="radio" name="function"> 类案检索 </label> <label class="radio-item"> <input type="radio" name="function"> 时效计算 </label> <label class="radio-item"> <input type="radio" name="function"> 管辖分析 </label> <label class="radio-item"> <input type="radio" name="function"> 费用估算 </label> <label class="radio-item"> <input type="radio" name="function"> 证据评估 </label> </div> </div> <!-- 参数设置区 --> <div class="params-box"> <h3>参数配置</h3> <div class="params-input"> <textarea placeholder="请输入具体要求(例如:文书类型/法律领域/金额区间等)..."></textarea> </div> <button class="execute-btn">立即分析</button> </div> </div> <!-- 响应展示区 --> <div class="response-area"> <h2>专业分析结果</h2> <div id="deepseek-response"> <!-- 分析结果将通过JavaScript动态加载 --> </div> </div> </body> <script> // DOM元素获取 const executeBtn = document.querySelector('.execute-btn'); const caseInput = document.querySelector('.case-input'); const paramsInput = document.querySelector('.params-input textarea'); const responseArea = document.getElementById('deepseek-response'); // 事件监听 executeBtn.addEventListener('click', async () => { try { // 收集表单数据 const formData = { caseDescription: caseInput.value, selectedFunction: document.querySelector('input[name="function"]:checked').parentElement.textContent.trim(), params: paramsInput.value }; // 显示加载状态 responseArea.innerHTML = '<div class="loading">分析中...<div class="loader"></div></div>'; // 发送请求 const response = await fetch('/get_answer/', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(formData) }); if (!response.ok) throw new Error(`请求失败: ${response.status}`); // 解析结果 const result = await response.json(); // 渲染结果 responseArea.innerHTML = ` <div class="result-card"> <h3>${result.title || '分析结果'}</h3> <div class="content">${formatResult(result.content)}</div> ${result.reference ? `<div class="reference">依据:${result.reference}</div>` : ''} </div> `; } catch (error) { console.error('请求失败:', error); responseArea.innerHTML = `<div class="error">错误: ${error.message}</div>`; } }); // 结果格式化函数 function formatResult(content) { // 如果是数组格式自动转换为列表 if (Array.isArray(content)) { return `<ul>${content.map(item => `<li>${item}</li>`).join('')}</ul>`; } return content.replace(/\n/g, '<br>'); } </script> </html>
python
from django.shortcuts import render from django.http import HttpResponse,JsonResponse from Myapp.models import * from django.views.decorators.http import require_http_methods import json,os,requests # Create your views here. def home(request): return render(request,'Home.html') @require_http_methods(["POST"]) def get_answer(request): '''组成提问,传递给下游函数,得到结果后返回给前端''' data = json.loads(request.body) print(data) question = '你现在是一个精通法律的律师,以下是我最近头疼的一个案子的描述:%s\n 我需要你帮我做一个:%s\n 这是我的一些补充:%s'%(data['caseDescription'],data['selectedFunction'],data['params']) result = { "title": data['selectedFunction'], "content": search_laws(question), "reference": "法律法规数据库" } return JsonResponse(result, safe=False) def search_laws(question): """发送给腾讯云HAI的deepseek""" url = "http://你的公网IP:6399/api/generate" payload = { "model": "deepseek-r1:14b", # Ollama服务中注册的模型名称 "prompt": question, "stream": False, # 设置为False获取完整响应 "options": { "temperature": 0.7, # 控制生成随机性(0-1) "max_tokens": 512 # 最大输出长度 } } try: response = requests.post( url, json=payload, timeout=30 # 设置超时时间为30秒 ) if response.status_code == 200: result = response.json() return result["response"] else: return f"请求失败,状态码:{response.status_code},响应:{response.text}" except Exception as e: return f"请求异常:{str(e)}"