ai-service.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import OpenAI from 'openai';
  2. import hljs from 'highlight.js';
  3. import 'highlight.js/styles/atom-one-dark.css'; // 导入一个暗色主题样式
  4. export const openai = new OpenAI(
  5. {
  6. // 若没有配置环境变量,请用百炼API Key将下行替换为:apiKey: "sk-xxx",
  7. apiKey: 'sk-e9855234f47346049809ce23ed3ebe3f',
  8. baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
  9. dangerouslyAllowBrowser: true,
  10. }
  11. )
  12. export async function getFileContent(data) {
  13. try {
  14. const res = await fetch('http://180.76.147.97:18899/upload_file', {
  15. method: 'post',
  16. body: data,
  17. }).then(res => res.json())
  18. return res
  19. } catch (error) {
  20. }
  21. }
  22. export async function getFormKey(data) {
  23. try {
  24. const res = await fetch('http://180.76.147.97:18899/uie', {
  25. method: 'post',
  26. body: JSON.stringify(data),
  27. }).then(res => res.json())
  28. return res
  29. } catch (error) {
  30. }
  31. }
  32. export async function hepl(data) {
  33. try {
  34. const res = await fetch(' http://180.76.147.97:18899/test', {
  35. method: 'post',
  36. body: JSON.stringify(data)
  37. }).then(res => res.json())
  38. return res
  39. } catch (error) {
  40. }
  41. }
  42. export async function sendMessage(message) {
  43. try {
  44. // 创建新的 AbortController
  45. const controller = new AbortController();
  46. const a = +new Date()
  47. const response = await openai.chat.completions.create({
  48. model: "qwen-plus", //模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
  49. messages: message,
  50. stream: true
  51. });
  52. return response;
  53. } catch (error) {
  54. console.error("API call failed:", error);
  55. return '[FILE]'
  56. } finally {
  57. }
  58. }
  59. function formatMessages(currentMessage, Summary, html) {
  60. const messages = [{
  61. role: "user",
  62. content: currentMessage,
  63. }]
  64. // const messages = this.context.filter(msg => msg.role === 'user').map((msg) => ({
  65. // role: msg.role,
  66. // content: msg.content,
  67. // }));
  68. // console.log(currentMessage, this.currentPageInfo, input);
  69. // // 如果存在页面信息,添加到当前消息的上下文
  70. // if (this.currentPageInfo && !input) {
  71. // currentMessage = `基于之前总结的页面内容(标题:${JSON.stringify(this.currentPageInfo)}),${currentMessage}`;
  72. // }
  73. // messages.push()
  74. if (Summary) return messages
  75. if (html) messages.unshift({
  76. role: "user",
  77. content: `页面主要内容${html}`,
  78. })
  79. return messages
  80. }
  81. export function getSummaryPrompt(pageInfo) {
  82. return `请帮我总结以下网页内容的要点:
  83. 页面标题:${pageInfo.title}
  84. 网站:${pageInfo.siteName}
  85. URL:${pageInfo.url}
  86. 主要内容:
  87. ${pageInfo.mainContent}
  88. 要求:
  89. 1. 用简洁清晰的语言提取3-5个核心要点
  90. 2. 保持客观中立的语气
  91. 3. 按重要性排序
  92. 4. 如果内容是新闻,需要包含时间、地点、人物等关键信息
  93. 5. 如果内容是教程,需要突出操作步骤和关键提示
  94. 6. 如果内容是产品介绍,需要包含主要特点和优势
  95. 7. 返回内容做好换行,以及展示样式
  96. 请以"以下是对该页面内容的总结:"开头,然后用要点的形式列出主要内容。`;
  97. }
  98. export function getFileSummaryPrompt(file,name) {
  99. return `请帮我总结以下文件内容的要点:
  100. 文件名称:${name}
  101. 主要内容:
  102. ${file}
  103. 要求:
  104. 1. 用简洁清晰的语言提取3-5个核心要点
  105. 2. 保持客观中立的语气
  106. 3. 按重要性排序
  107. 4. 返回内容做好换行,以及展示样式
  108. 请以"以下是对该文件内容的总结:"开头,然后用要点的形式列出主要内容。`;
  109. }
  110. export function formatMessage(text) {
  111. if (!text) return "";
  112. // 用于转义代码块中的 HTML 字符
  113. const escapeHtml = (str) => {
  114. return str
  115. .replace(/&/g, "&")
  116. .replace(/</g, "&lt;")
  117. .replace(/>/g, "&gt;")
  118. .replace(/"/g, "&quot;")
  119. .replace(/'/g, "&#039;");
  120. };
  121. // 处理代码高亮
  122. const highlightCode = (code, language) => {
  123. if (language && language.trim() !== '') {
  124. try {
  125. return hljs.highlight(code, { language: language.trim() }).value;
  126. } catch (e) {
  127. // 如果指定的语言不支持,回退到自动检测
  128. return hljs.highlightAuto(code).value;
  129. }
  130. }
  131. return hljs.highlightAuto(code).value;
  132. };
  133. return (
  134. text
  135. // 处理带有语言标识的代码块
  136. .replace(/```(\w+)?\n([\s\S]*?)```/g, (match, lang, code) => {
  137. const highlightedCode = highlightCode(code, lang || '');
  138. return `<pre style="background-color: #282c34; padding: 10px; border-radius: 5px; overflow-x: auto;"><code class="hljs ${lang || ''}">${highlightedCode}</code></pre>`;
  139. })
  140. // 处理不带语言标识的代码块
  141. .replace(/```([\s\S]*?)```/g, (match, code) => {
  142. const highlightedCode = highlightCode(code, '');
  143. return `<pre style="background-color: #282c34; padding: 10px; border-radius: 5px; overflow-x: auto;"><code class="hljs">${highlightedCode}</code></pre>`;
  144. })
  145. // 处理行内代码
  146. .replace(/`([^`]+)`/g, (match, code) => `<code style="background-color: #f0f0f0; padding: 2px 4px; border-radius: 3px;">${escapeHtml(code)}</code>`)
  147. // 处理标题 (h1 ~ h6)
  148. .replace(/^#{1,6}\s+(.+)$/gm, (match, content) => {
  149. const level = match.trim().split("#").length - 1;
  150. return `<h${level}>${content.trim()}</h${level}>`;
  151. })
  152. // 处理换行
  153. .replace(/\n/g, "<br>")
  154. // 处理连续空格
  155. .replace(/ {2,}/g, (match) => "&nbsp;".repeat(match.length))
  156. // 处理粗体
  157. .replace(/\*\*(.*?)\*\*/g, "<strong>$1</strong>")
  158. // 处理斜体
  159. .replace(/\*(.*?)\*/g, "<em>$1</em>")
  160. // 处理链接
  161. .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank">$1</a>')
  162. // 处理无序列表:先将每行列表项转换为 <li> 标签
  163. .replace(/^[*-]\s+(.+)$/gm, "<li>$1</li>")
  164. // 然后将连续的 <li> 包裹在 <ul> 中
  165. .replace(/(<li>.*<\/li>)/gs, "<ul>$1</ul>")
  166. // 处理有序列表:先将每行列表项转换为 <li> 标签
  167. .replace(/^\d+\.\s+(.+)$/gm, "<li>$1</li>")
  168. // 然后将连续的 <li> 包裹在 <ol> 中
  169. .replace(/(<li>.*<\/li>)/gs, "<ol>$1</ol>")
  170. // 处理分隔线
  171. .replace(/^---+$/gm, "<hr>")
  172. // 处理引用
  173. .replace(/^>\s+(.+)$/gm, "<blockquote>$1</blockquote>")
  174. );
  175. }
  176. export function buildExcelUnderstandingPrompt(data, fileName, pageInfo) {
  177. // if (!data || data.length < 2) {
  178. // return "这是一个空的Excel文件,请检查文件内容。";
  179. // }
  180. // const headers = data[0];
  181. // const rows = data.slice(1);
  182. // data[0].forEach((header, i) => {
  183. // if (!this.excelData[header]) this.excelData[header] = []
  184. // this.excelData[header].push(data[1][i])
  185. // })
  186. return `我将向你展示一个通过SheetJS库读取的Excel文件内容和一个form表单。请帮我理解这些数据:
  187. 文件名:${fileName}
  188. 列标题:${data.join(", ")}
  189. 表单内容:
  190. ${pageInfo}
  191. 要求:
  192. 1. 请根据表单中的表单项和列标题进行匹配,一定以表单为准!
  193. 2. 生成表单项与列标题对应的数组,并使用findBy告诉我通过表单项的什么字段信息匹配到的,使用findByValue告诉我匹配到的表单项字段值,使用excelColumn字段告诉我excel文件中列标题的值。
  194. 3. 根据label匹配,findBy是label,并通过findByValue给我label元素的值,根据id匹配,findBy是id,并通过findByValue给是id的值,
  195. 3. 并去除没有匹配到的表单项和excel文件中没有匹配到的列,
  196. 4. 通过type字段告诉我输入项的类型
  197. 5. 表单项有label,根据label匹配,没有label根据placeholder匹配,没有placeholder,根据id匹配,再根据其他内容匹配
  198. 6. 仅返回数组,不要返回任何其他内容。`
  199. }
  200. // 5. 如果表单项有label标签,同时返回label, 通过label字段告诉我label元素的文本
  201. export function buildObjPrompt(obj, pageInfo) {
  202. return `我将向你展示一个对象和一个form表单。请帮我理解这些数据:
  203. 对象:${JSON.stringify(obj)}
  204. 表单内容:
  205. ${pageInfo}
  206. 要求:
  207. 1. 请根据表单中的表单项和对象进行匹配,一定以表单为准,key同时在对象和表单中出现,才能返回!
  208. 2. 表单项有label,根据label匹配,没有label根据placeholder匹配,没有placeholder,根据id匹配,再根据其他内容匹配
  209. 3. 并根据实际可操作的表单项的所有信息与上传的对象的key进行匹配,生成表单项与key的数组,并使用findBy告诉我通过表单项的什么字段信息匹配到的,使用findByValue告诉我匹配到的表单项字段值,使用excelColumn字段告诉我对应的key值。在一个字段内返回
  210. 4. 并去除没有匹配到的表单项和对象中没有匹配到的key,
  211. 5. 通过type字段告诉我输入项的类型,如果对象中key对应的是日期,type统一返回date
  212. 6. 仅返回数组,不要返回任何其他内容。`
  213. }
  214. function escapeHtml(html) {
  215. const div = document.createElement("div");
  216. div.textContent = html;
  217. return div.innerHTML;
  218. }