打算在这篇文章分享我平时开发AI应用的经验,会持续更新。头条的规则是不允许已发布的文件有大幅修改,所以后面的更新会发表成新的文章,在评论里面放链接。
20250417:
今天注册了一个域名myaiweb.cn。 阿里云有活动,两年39块钱,送dns解析。 本来以为实名审核要很麻烦,但没想到填了点个人信息,很快申请下来了。 欢迎大家使用我的大五人格性格分析工具
https://www.myaiweb.cn/five.html
boss直聘会员才送一次大五人格性格测试,而我这个是免费的。测试完后还可以让ai针对你性格进一步分析,给出更有针对性的建议。
同时也申请了一个免费的测试证书,部署到了nginx。有效期3个月,等到期了再考虑买个付费的证书。
考虑到后面还要再搭个rag,可能还要再买一台机部署postgres,2核4g内存,一年700来块钱。不过暂时不着急
今天调试网页中,无意发现百度在首页的控制台里面,输出了百度校园招聘的广告,挺有技术情节的。 百度2025校园招聘简历投递:
https://talent.baidu.com/jobs/list 以后也许可以多翻一下网页源代码,也许有意外收获。
分享我最近写的,将ai返回的markdown格式内容转换成html格式输出的代码 (后面我考虑做成一个独立的网页),代码有些乱,因为主体是AI写的,我负责调试修改bug。
function processAIResponse(data) {
// 增强的 markdown 解析逻辑
let formattedResult = data.result
// 先处理分隔线
.replace(/^[-]{3,}/gm, '<hr>');
console.log('----- 分隔符处理后 -----', formattedResult);
//处理表格(调整后的正则表达式)
formattedResult = formattedResult
.replace(/(\|[^\n]+\|[\s]*[\r\n]+)(\|[\s\-|:]+\|[\s]*[\r\n]+)((\|[^\n]+\|[\s]*[\r\n]*)+)/gm,
(match, header, divider, rows) => {
// match: 完整匹配的表格字符串(从 | 表头 | 到 | 最后一行 | 的全部内容)
// header: 第一个捕获组 ([^\|]+?) - 表头行的内容(包含首尾的 |)
// divider: 第二个捕获组 ([\s\-:|]+) - 分隔线行的内容(包含首尾的 |)
// rows: 第三个捕获组 ((?:\|.*\|[\r\n]*)+) - 所有数据行的合并字符串
// 示例表格结构:
// | Header1 | Header2 | <- 这是header
// |---------|---------| <- 这是divider
// | Row1Col1| Row1Col2| <- 从这是rows
// | Row2Col1| Row2Col2|
console.log('----- 发现表格内容 -----');
console.log('发现表格结构 原始内容:', match.substring(0, 50));
const processCell = (cell) => {
// 保留换行符并移除首尾空格
return cell.trim().replace(/\n/g, '<br>');
};
// 处理表头
const headerRow = header.split('\n')[0]; // 取第一行作为表头
const headerCells = headerRow.split('|')
.slice(1, -1)
.map(cell => `<th>${processCell(cell)}</th>`)
.join('');
// 处理数据行
const bodyRows = rows.split('\n')
.filter(line => line.trim().startsWith('|'))
.map(row => {
return `<tr>${
row.split('|')
.slice(1, -1)
.map(cell => `<td>${processCell(cell)}</td>`)
.join('')
}</tr>`;
})
.join('');
const finalTable = `<table class="analysis-table">
<thead><tr>${headerCells}</tr></thead>
<tbody>${bodyRows}</tbody>
</table>\n`;
return finalTable;
});
// console.log('----- 表格处理后 -----', formattedResult);
// 2. 处理标题(增加严格边界匹配)
formattedResult = formattedResult.replace(/^#{1,6}\s+([^\n]+)/gm, (match, p1) => {
console.log('处理标题:', match.trim());
const level = match.match(/^#+/)[0].length;
return `<h${level}>${p1.trim()}</h${level}>`;
});
console.log('----- 标题处理后 -----', formattedResult);
formattedResult = formattedResult
// 修改列表项匹配正则表达式,支持中文格式
.replace(/^([-*+]|\s+[-*+]|\u2022|\u25E6|\u25AA)\s(.+)$/gm, (match, bullet, content) => {
console.log('发现列表项:', match);
return `<li>${content}</li>`;
})
// 加粗和斜体
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.+?)\*/g, '<em>$1</em>')
// 代码块
.replace(/```([\s\S]*?)```/g, '<pre><code>$1</code></pre>')
// 行内代码
.replace(/`(.+?)`/g, '<code>$1</code>')
// 链接和图片
.replace(/!\[(.*?)\]\((.*?)\)/g, '<img alt="$1" src="$2">')
.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2">$1</a>')
// 引用
.replace(/^\>\s(.+?)$/gm, '<blockquote>$1</blockquote>')
// 4. 包裹无序列表(增加边界检测)
.replace(/(<li>[\s\S]*?<\/li>)+/g, match => {
return /<\/?h\d>/.test(match) ? match : `<ul>${match}</ul>`;
})
// 5. 最后处理换行(排除表格和列表中的换行)
.replace(/(?<!<\/td>|[>-])\n/g, '<br>');
formattedResult += "<br>";
console.log("formattedResult = ", formattedResult);
//document.getElementById('ai-result').innerHTML = formattedResult;
}
20250416:
今天把前几天用ai写的网页工具部署到web端,发现一个问题。之前我在开发环境用的是npm run dev启动服务的,在浏览器访问时可以正常访问。
但是上传到linux环境时,因为加了个前缀(我上面部署了几个不同工具,通过nginx分发),访问时就会出现问题了,在操作网页过程中,浏览器地址栏会变化,导致前缀丢失。
今天查了一下,说要把一个函数换了就行
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL), // 修改这一行 从createWebHistory改成createWebHashHistory就能自适应所有目录
routes
});
不过这样网址会有#结果,例如:
http://www.myaiweb.cn/prod_frontend/index.html#/
难怪上家公司我们前端同事开发的web页面网址也是有#,之前没问过他原因,还以为是故意的
昨天安装openai新版本失败,今天查了一下,说可能是python版本太低。所以我从网上下载了一个3.12版本的代码包,按ai提示安装了依赖,居然一次编译过了。之后尝试更新openai版本,果然顺利升级成功。
20250415:
今天买了一个阿里云服务器,打算在上面跑一个python脚本,转发前端调用deepseek的请求(前端直接发起请求会因为跨域问题失败)。程序在我windows机器上跑起来还是比较顺利的,但在服务器运行就报错,提示找不到OpenAI
查了一下,是因为openai包的版本太低了。但不知道为什么,无论我怎么升级,它都只能升级到0.8版本,而根据ai回答,OpenAI最低要1.0。
后来只能放弃用openai包,自己写http请求代替,,贴个代码,跟大家分享一下,说不定哪天有人需要
def send_messages(messages):
headers = {
"Authorization": "Bearer sk-", # 这里是要填从deepseek那里创建的密钥
"Content-Type": "application/json"
}
data = {
"model": "deepseek-chat",
"messages": messages
}
response = requests.post(
"https://api.deepseek.com/v1/chat/completions",
headers=headers,
json=data
)
response.raise_for_status()
# 打印响应状态和结果
print(f"API响应状态码: {response.status_code}")
print(f"API响应内容: {response.text}")
result = response.json()
print(f"解析后的JSON结果: {json.dumps(result, indent=2, ensure_ascii=False)}")
# 返回给前端自行解析
return response.text
#return result['choices'][0]['message']
阿里云服务器默认是没放开80端口的,先要在机器上把80端口添加到防火墙白名单,然后在阿里云控制台也配置放开80端口。(443端口也一样)。我因为之前踩过这个坑,这次把防火墙放开后端口还是不能访问,立即就想到要到控制台修改路由规则。相信应该建站的新人会踩我这个坑,记录一下。
20250414:
今天尝试写一个网页工具,调用deepseek的api,发现一些问题。
1 直接在网页上调用deepseek的api请求会报错
five.html:1 Access to fetch at 'https://api.deepseek.com/' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No '
Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.了解此错误
five.html:773
POST https://api.deepseek.com/ net::ERR_FAILED
估计是官方服务器没配置支持跨域查询,需要自己搞一台服务器转发才行
2 deepseek r1官方api,返回的回答结果在content,思考过程在reasoning_content,而有一些本地部署的模型却是把思考过程放在<think></think>中
3 腾讯的r1模型费用特别高,一年要10万3千元(不限量),所以我没用,直接到官网充了10块钱,生成了一个测试的api-key。
不过目前有个问题,官网没有账户管理概念,所有api-key共用一个金额,暂时不知道怎么处理。按我想法最好是不同的api-key可以有不同的余额。
20250114:
做rag需要到向量数据库查询知识时,需要注意先将问题改写后,再到数据库查,否则查询结果会很不精确。
例如用户对话是这样的:
user: 你们公司有什么特色技术吗
system: 我们公司在能源管理和安防上有优势
user:还有没?<-- 这里如果不改写,直接到向量数据库查询,会找不到数据。需要先使用大模型结合上下文 将这个问题改写成:你们公司除了能源管理和安防外,还有哪些特色技术