Elasticsearch:使用 AI SDK 和 Elastic 構建 AI 代理

作者:來自 Elastic?Carly Richmond

你是否經常聽到 AI 代理(AI agents)這個詞,但不太確定它們是什么,或者如何在 TypeScript(或 JavaScript)中構建一個?跟我一起深入了解 AI 代理的概念、它們的可能應用場景,以及一個使用 AI SDK 和 Elasticsearch 構建的旅行規劃代理示例。

你是否經常聽到 AI 代理這個詞,但不太確定它們是什么,或者它們如何與 Elastic 關聯?在這里,我將深入探討 AI 代理,具體包括:

  • 什么是 AI 代理?

  • AI 代理可以解決哪些問題?

  • 一個基于 AI SDK、TypeScript 和 Elasticsearch 的旅行規劃代理示例,代碼可在 GitHub 上找到。

什么是 AI 代理?

AI 代理是一種能夠自主執行任務并代表人類采取行動的軟件,它利用人工智能實現這一目標。AI 代理通過結合一個或多個大語言模型(large language models - LLMs)與用戶定義的工具(或函數)來執行特定操作。例如,這些工具可以執行以下操作:

  • 從數據庫、傳感器、API 或 Elasticsearch 等搜索引擎提取信息。

  • 執行復雜計算,并讓 LLM 總結其結果。

  • 基于各種數據輸入快速做出關鍵決策。

  • 根據響應觸發必要的警報和反饋。

AI 代理可以做什么?

AI 代理可以根據其類型在多個領域中應用,可能的示例包括:

  • 基于效用的代理:評估行動并提供推薦以最大化收益,例如根據用戶的觀看歷史推薦電影和電視劇。

  • 基于模型的代理:根據傳感器輸入實時決策,例如自動駕駛汽車或智能吸塵器。

  • 學習型代理:結合數據和機器學習識別模式和異常,例如用于欺詐檢測。

  • 投資建議代理:根據用戶的風險偏好和現有投資組合提供投資建議,以最大化收益。如果能權衡準確性、聲譽風險和監管因素,這將加速決策過程。

  • 簡單聊天機器人:如當前的聊天機器人,可訪問用戶賬戶信息并用自然語言回答基本問題。

示例:旅行規劃助手

為了更好地理解 AI 代理的功能,以及如何使用熟悉的 Web 技術構建一個 AI 代理,我們來看一個使用 AI SDK、TypeScript 和 Elasticsearch 編寫的簡單旅行規劃助手示例。

架構

我們的示例由 5 個不同的元素組成:

  1. 一個名為 weatherTool 的工具,從 Weather API 獲取提問者指定位置的天氣數據。

  2. 一個名為 fcdoTool 的工具,從 GOV.UK content API 提供目的地的當前旅行狀態。

  3. flightTool 工具使用簡單查詢從 Elasticsearch 獲取航班信息。

  4. 以上所有信息都會傳遞給 LLM GPT-4 Turbo

模型選擇

在構建你的第一個 AI 代理時,確定使用哪個模型可能會很困難。資源如 Hugging Face Open LLM Leaderboard 是一個不錯的起點。此外,你還可以參考 Berkeley Function-Calling Leaderboard 來獲取工具使用的指導。

在我們的案例中,AI SDK 特別推薦使用具有強大工具調用能力的模型,例如 gpt-4gpt-4-turbo,這在其 Prompt Engineering 文檔中有詳細說明。如果選擇了錯誤的模型,可能會導致 LLM 無法按預期調用多個工具,甚至會出現兼容性錯誤,如下所示:

# Llama3 lack of tooling support (3.1 or higher)
llama3 does not support tools# Unsupported toolChoice option to configure tool usage
AI_UnsupportedFunctionalityError: 'Unsupported tool choice type: required' functionality not supported.

先決條件

要運行此示例,請確保按照倉庫 README 中的先決條件進行操作。

基礎聊天助手

你可以使用 AI SDK 創建的最簡單的 AI 代理將生成來自 LLM 的響應,而無需任何額外的上下文。AI SDK 支持許多 JavaScript 框架,具體可參考其文檔。然而,AI SDK UI 庫文檔列出了對 React、Svelte、Vue.js 和 SolidJS 的不同支持,許多教程針對 Next.js。因此,我們的示例使用 Next.js 編寫。

任何 AI SDK 聊天機器人的基本結構使用 useChat 鉤子來處理來自后端路由的請求,默認情況下是 /api/chat/

page.tsx 文件包含了我們在 Chat 組件中的客戶端實現,包括由 useChat hook 暴露的提交、加載和錯誤處理功能。加載和錯誤處理功能是可選的,但建議提供請求狀態的指示。與簡單的 REST 調用相比,代理可能需要相當長的時間來響應,因此在此過程中保持用戶更新狀態非常重要,避免用戶快速連續點擊和重復調用。

由于該組件涉及客戶端交互,我使用了 use client 指令,以確保該組件被視為客戶端包的一部分:

'use client';import { useChat } from '@ai-sdk/react';
import Spinner from './components/spinner';export default function Chat() {/* useChat hook helps us handle the input, resulting messages, and also handle the loading and error states for a better user experience */const { messages, input, handleInputChange, handleSubmit, isLoading, stop, error, reload } = useChat();return (<div className="chat__form"><div className="chat__messages">{/* Display all user messages and assistant responses */messages.map(m => (<div key={m.id} className="message"><div>{ /* Messages with the role of *assistant* denote responses from the LLM*/ }<div className="role">{m.role === "assistant" ? "Sorley" : "Me"}</div>{ /* User or LLM generated content */}<div className="itinerary__div" dangerouslySetInnerHTML={{ __html: markdownConverter.makeHtml(m.content) }}></div></div></div>))}</div>{/* Spinner shows when awaiting a response */isLoading && (<div className="spinner__container"><Spinner /><button id="stop__button" type="button" onClick={() => stop()}>Stop</button></div>)}{/* Show error message and return button when something goes wrong */error && (<><div className="error__container">Unable to generate a plan. Please try again later!</div><button id="retry__button" type="button" onClick={() => reload()}>Retry</button></>)}{ /* Form using default input and submission handler form the useChat hook */ }<form onSubmit={handleSubmit}><inputclassName="search-box__input"value={input}placeholder="Where would you like to go?"onChange={handleInputChange}disabled={error != null}/></form></div>);
}

Chat 組件將通過鉤子暴露的 input 屬性保持用戶輸入,并在提交時將響應發送到相應的路由。我使用了默認的 handleSubmit 方法,它將調用 /ai/chat/ 的 POST 路由。

該路由的處理程序位于 /ai/chat/route.ts 中,通過 OpenAI?provider 程序初始化與 gpt-4-turbo LLM 的連接:

import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
import { NextResponse } from 'next/server';// Allow streaming responses up to 30 seconds to address typically longer responses from LLMs
export const maxDuration = 30;// Post request handler
export async function POST(req: Request) {const { messages } = await req.json();try {// Generate response from the LLM using the provided model, system prompt and messagesconst result = streamText({model: openai('gpt-4-turbo'),system: 'You are a helpful assistant that returns travel itineraries',messages});// Return data stream to allow the useChat hook to handle the results as they are streamed through for a better user experiencereturn result.toDataStreamResponse();} catch(e) {console.error(e);return new NextResponse("Unable to generate a plan. Please try again later!");}
}

請注意,上述實現將默認從環境變量 OPENAI_API_KEY 中提取 API 密鑰。如果需要自定義 OpenAI 提供程序的配置,可以使用 createOpenAI 方法來覆蓋提供程序的設置。

通過以上路由,結合 Showdown 幫助將 GPT 的 Markdown 輸出格式化為 HTML,再加上一些 CSS 魔法(在 globals.css 文件中),我們最終得到了一個簡單的響應式 UI,可以根據用戶的提示生成行程:

基本的 LLM 行程視頻

添加工具

向 AI 代理添加工具基本上就是創建 LLM 可以使用的自定義功能,以增強其生成的響應。在此階段,我將添加 3 個新的工具,LLM 可以選擇在生成行程時使用,如下圖所示:

天氣工具

雖然生成的行程是一個很好的開始,但我們可能希望添加 LLM 沒有經過訓練的額外信息,比如天氣。這促使我們編寫第一個工具,它不僅可以作為 LLM 的輸入,還能提供額外的數據,幫助我們調整 UI。

創建的天氣工具,完整代碼如下,接受一個參數 location,LLM 將從用戶輸入中提取該位置。schema 屬性使用 TypeScript 的 schema 驗證庫 Zod 來驗證傳入的參數類型,確保傳遞的是正確的參數類型。description 屬性允許你定義工具的功能,幫助 LLM 決定是否調用該工具。

import { tool as createTool } from 'ai';
import { z } from 'zod';import { WeatherResponse } from '../model/weather.model';export const weatherTool = createTool({description: 'Display the weather for a holiday location',parameters: z.object({location: z.string().describe('The location to get the weather for')}),execute: async function ({ location }) {// While a historical forecast may be better, this example gets the next 3 daysconst url = `https://api.weatherapi.com/v1/forecast.json?q=${location}&days=3&key=${process.env.WEATHER_API_KEY}`;try {const response = await fetch(url);const weather : WeatherResponse = await response.json();return { location: location, condition: weather.current.condition.text, condition_image: weather.current.condition.icon,temperature: Math.round(weather.current.temp_c),feels_like_temperature: Math.round(weather.current.feelslike_c),humidity: weather.current.humidity};} catch(e) {console.error(e);return { message: 'Unable to obtain weather information', location: location};}}
});

你可能已經猜到,execute 屬性是我們定義異步函數并實現工具邏輯的地方。具體來說,發送到天氣 API 的位置會傳遞給我們的工具函數。然后,響應會被轉換為一個單一的 JSON 對象,可以顯示在 UI 上,并且也用于生成行程。

鑒于我們目前只運行一個工具,因此不需要考慮順序或并行流程。簡單來說,就是在原始 api/chat 路由中處理 LLM 輸出的 streamText 方法中添加 tools 屬性:

import { weatherTool } from '@/app/ai/weather.tool';// Other imports omittedexport const tools = {displayWeather: weatherTool,
};// Post request handler
export async function POST(req: Request) {const { messages } = await req.json();// Generate response from the LLM using the provided model, system prompt and messages (try catch block omitted)const result = streamText({model: openai('gpt-4-turbo'),system: 'You are a helpful assistant that returns travel itineraries based on the specified location.',messages,maxSteps: 2,tools});// Return data stream to allow the useChat hook to handle the results as they are streamed through for a better user experiencereturn result.toDataStreamResponse();
}

工具輸出與消息一起提供,這使我們能夠為用戶提供更完整的體驗。每條消息包含一個 parts 屬性,其中包含 type 和 state 屬性。當這些屬性的值分別為 tool-invocation 和 result 時,我們可以從 toolInvocation 屬性中提取返回的結果,并按需要顯示它們。

更改后的 page.tsx 源代碼將顯示天氣摘要以及生成的行程:

'use client';import { useChat } from '@ai-sdk/react';
import Image from 'next/image';import { Weather } from './components/weather';import pending from '../../public/multi-cloud.svg';export default function Chat() {/* useChat hook helps us handle the input, resulting messages, and also handle the loading and error states for a better user experience */const { messages, input, handleInputChange, handleSubmit, isLoading, stop, error, reload } = useChat();return (<div className="chat__form"><div className="chat__messages">{/* Display all user messages and assistant responses */messages.map(m => (<div key={m.id} className="message"><div>{ /* Messages with the role of *assistant* denote responses from the LLM */}<div className="role">{m.role === "assistant" ? "Sorley" : "Me"}</div>{ /* Tool handling */}<div className="tools__summary">{m.parts.map(part => {if (part.type === 'tool-invocation') {const { toolName, toolCallId, state } = part.toolInvocation;if (state === 'result') {{ /* Show weather results */}if (toolName === 'displayWeather') {const { result } = part.toolInvocation;return (<div key={toolCallId}><Weather {...result} /></div>);}} else {return (<div key={toolCallId}>{toolName === 'displayWeather' ? (<div className="weather__tool"><Image src={pending} width={80} height={80} alt="Placeholder Weather"/><p className="loading__weather__message">Loading weather...</p></div>) : null}</div>);}}})}</div>{ /* User or LLM generated content */}<div className="itinerary__div" dangerouslySetInnerHTML={{ __html: markdownConverter.makeHtml(m.content) }}></div></div></div>))}</div>{ /* Spinner and loading handling omitted */ }{ /* Form using default input and submission handler form the useChat hook */}<form onSubmit={handleSubmit}><inputclassName="search-box__input"value={input}placeholder="Where would you like to go?"onChange={handleInputChange}disabled={error != null}/></form></div>);
}

上述代碼將向用戶提供以下輸出:

FCO 工具

AI 代理的強大之處在于 LLM 可以選擇觸發多個工具來獲取相關信息,以生成響應。假設我們想要查看目標國家的旅行指南。下面的代碼展示了如何創建一個新的工具 fcdoGuidance,它可以觸發一個對 GOV.UK Content API 的 API 調用:

import { tool as createTool } from 'ai';
import { z } from 'zod';import { FCDOResponse } from '../model/fco.model';export const fcdoTool = createTool({description: 'Display the FCDO guidance for a destination',parameters: z.object({country: z.string().describe('The country of the location to get the guidance for')}),execute: async function ({ country }) {const url = `https://www.gov.uk/api/content/foreign-travel-advice/${country.toLowerCase()}`;try {const response = await fetch(url, { headers: { 'Content-Type': 'application/json' } });const fcoResponse: FCDOResponse = await response.json();const alertStatus: string = fcoResponse.details.alert_status.length == 0 ? 'Unknown' : fcoResponse.details.alert_status[0].replaceAll('_', ' ');return { status: alertStatus, url: fcoResponse.details?.document?.url};} catch(e) {console.error(e);return { message: 'Unable to obtain FCDO information', location: location};}}
});

你會注意到,格式與之前討論的天氣工具非常相似。事實上,要將該工具包含到 LLM 輸出中,只需將其添加到 tools 屬性,并修改 /api/chat 路由中的提示即可:

// Imports omittedexport const tools = {fcdoGuidance: fcdoTool,displayWeather: weatherTool,
};// Post request handler
export async function POST(req: Request) {const { messages } = await req.json();// Generate response from the LLM using the provided model, system prompt and messages (try/ catch block omitted)const result = streamText({model: openai('gpt-4-turbo'),system:"You are a helpful assistant that returns travel itineraries based on a location" + "Use the current weather from the displayWeather tool to adjust the itinerary and give packing suggestions." +"If the FCDO tool warns against travel DO NOT generate an itinerary.",messages,maxSteps: 2,tools});// Return data stream to allow the useChat hook to handle the results as they are streamed through for a better user experiencereturn result.toDataStreamResponse();
}

一旦將顯示工具輸出的組件添加到頁面,對于不建議旅行的國家,輸出應該如下所示:

支持工具調用的LLM可以選擇是否調用工具,除非它認為有必要。使用gpt-4-turbo時,我們的兩個工具會并行調用。然而,之前嘗試使用llama3.1時,取決于輸入,只有一個模型會被調用。

航班信息工具

RAG(Retrieval Augmented Generation - 檢索增強生成)指的是一種軟件架構,其中從搜索引擎或數據庫中提取的文檔作為上下文傳遞給 LLM,以基于提供的文檔集來生成回應。這種架構允許 LLM 根據它之前沒有訓練過的數據生成更準確的回應。雖然 Agentic RAG 通過定義的工具或結合向量或混合搜索處理文檔,但也可以像我們這里所做的那樣,利用 RAG 作為與傳統詞匯搜索的復雜流程的一部分。

為了將航班信息與其他工具一起傳遞給LLM,最后一個工具 flightTool 通過 Elasticsearch JavaScript 客戶端,從 Elasticsearch 中拉取出發和到達航班的航班信息,使用提供的出發地和目的地:

import { tool as createTool } from 'ai';
import { z } from 'zod';import { Client } from '@elastic/elasticsearch';
import { SearchResponseBody } from '@elastic/elasticsearch/lib/api/types';import { Flight } from '../model/flight.model';const index: string = "upcoming-flight-data";
const client: Client = new Client({node: process.env.ELASTIC_ENDPOINT,auth: {apiKey: process.env.ELASTIC_API_KEY || "",},
});function extractFlights(response: SearchResponseBody<Flight>): (Flight | undefined)[] {return response.hits.hits.map(hit => { return hit._source})
}export const flightTool = createTool({description:"Get flight information for a given destination from Elasticsearch, both outbound and return journeys",parameters: z.object({destination: z.string().describe("The destination we are flying to"),origin: z.string().describe("The origin we are flying from (defaults to London if not specified)"),}),execute: async function ({ destination, origin }) {try {const responses = await client.msearch({searches: [{ index: index },{query: {bool: {must: [{match: {origin: origin,},},{match: {destination: destination,},},],},},},// Return leg{ index: index },{query: {bool: {must: [{match: {origin: destination,},},{match: {destination: origin,},},],},},},],});if (responses.responses.length < 2) {throw new Error("Unable to obtain flight data");}return {outbound: extractFlights(responses.responses[0] as SearchResponseBody<Flight>),inbound: extractFlights(responses.responses[1] as SearchResponseBody<Flight>)};} catch (e) {console.error(e);return {message: "Unable to obtain flight information",location: location,};}},
});

這個示例使用了 Multi search API 來分別拉取出發和到達航班的信息,然后通過?extractFlights?工具方法提取文檔。

為了使用工具的輸出,我們需要再次修改我們的提示和工具集合,更新?/ai/chat/route.ts?文件:

// Imports omitted// Allow streaming responses up to 30 seconds to address typically longer responses from LLMs
export const maxDuration = 30;export const tools = {getFlights: flightTool,displayWeather: weatherTool,fcdoGuidance: fcdoTool
};// Post request handler
export async function POST(req: Request) {const { messages } = await req.json();// Generate response from the LLM using the provided model, system prompt and messages (try/ catch block omitted)const result = streamText({model: openai('gpt-4-turbo'),system:"You are a helpful assistant that returns travel itineraries based on location, the FCDO guidance from the specified tool, and the weather captured from the displayWeather tool." + "Use the flight information from tool getFlights only to recommend possible flights in the itinerary." + "Return an itinerary of sites to see and things to do based on the weather." + "If the FCDO tool warns against travel DO NOT generate an itinerary.",messages,maxSteps: 2,tools});// Return data stream to allow the useChat hook to handle the results as they are streamed through for a better user experiencereturn result.toDataStreamResponse();
}

通過最終的提示,所有 3 個工具將被調用,以生成包含航班選項的行程:

總結

如果你之前對 AI 代理還不完全了解,現在你應該清楚了!我們通過使用 AI SDK、Typescript 和 Elasticsearch 的簡單旅行規劃示例來進行了解。我們可以擴展我們的規劃器,添加其他數據源,允許用戶預訂旅行以及旅游,甚至根據位置生成圖像橫幅(目前 AI SDK 中對此的支持仍處于實驗階段)。

如果你還沒有深入了解代碼,可以在這里查看!

資源

  1. AI SDK 核心文檔
  2. AI SDK 核心 > 工具調用
  3. Elasticsearch JavaScript 客戶端
  4. 旅行規劃 AI 代理 | GitHub

想要獲得 Elastic 認證嗎?查看下次 Elasticsearch 工程師培訓的時間!

Elasticsearch 擁有眾多新功能,可以幫助你為你的使用案例構建最佳搜索解決方案。深入了解我們的示例筆記本,了解更多內容,開始免費云試用,或在本地機器上嘗試 Elastic。

原文:Building AI Agents with AI SDK and Elastic - Elasticsearch Labs

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/73647.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/73647.shtml
英文地址,請注明出處:http://en.pswp.cn/web/73647.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

5G智慧工廠專網部署:IPLOOK助力制造業數字化轉型

5G專網 隨著工業4.0時代的到來&#xff0c;制造業對高效、低延遲和智能化網絡的需求日益增長。5G專網憑借其高速率、低時延和大連接特性&#xff0c;成為智慧工廠數字化轉型的重要支撐。IPLOOK作為全球領先的移動核心網解決方案提供商&#xff0c;基于自身強大的5G核心網產品和…

第六屆 藍橋杯 嵌入式 省賽

參考 第六屆藍橋杯嵌入式省賽程序設計題解析&#xff08;基于HAL庫&#xff09;_藍橋杯嵌入式第六屆真題-CSDN博客 一、分析功能 RTC 定時 1&#xff09;時間初始化 2&#xff09;定時上報電壓時間 ADC測量 采集電位器的輸出電壓信號。 串行功能 1&#xff09;傳送要設置…

第十二篇《火攻篇》:一把火背后的戰爭哲學與生存智慧

《孫子兵法》作為人類歷史上最早的軍事戰略經典&#xff0c;其思想穿透了2500年的時空&#xff0c;至今仍在政治、商業乃至個人決策領域閃耀光芒。第十二篇《火攻篇》看似聚焦于具體的戰術手段&#xff0c;實則蘊含了深刻的戰爭倫理與生存哲學。本文解讀這一篇章如何用一把火點…

word光標一直閃的解決辦法

在選項里&#xff0c;打開首選項&#xff0c;&#xff08;如果打不開&#xff0c;可以新建一個word也許就可以&#xff0c;實在不行只能靠眼疾手快&#xff0c;趁他還沒閃趕緊點&#xff09; 選COM加載項&#xff0c;在里面取消勾選MicrosoftOfficePLUS

修改菜品-01.需求分析與設計

一.需求分析與設計 修改時要首先回顯 設計時我們要設計哪些接口&#xff1f; 根據id查詢菜品接口設計&#xff1a; 我們要根據id進行查詢&#xff0c;因此在這里面id被作為路徑參數。使用注解PathVariable。在查詢菜品時&#xff0c;要將對應的口味也查出來&#xff0c;因此還…

Oracle到達夢數據庫遷移:技術要點與實踐分享

一、達夢數據庫簡介 達夢數據庫(DM,Dameng Database)是國內自主研發的具有自主知識產權的大型通用數據庫管理系統,具備以下顯著特點: 1.高性能:高效的存儲與計算分離架構:達夢數據庫采用先進的存儲與計算分離架構,能夠根據業務需求靈活分配存儲和計算資源,大大提高了…

Vue動態綁定:文本框、單選按鈕、下拉列表、多選按鈕

Vue 指令系列文章: 《Vue插值:雙大括號標簽、v-text、v-html、v-bind 指令》 《Vue指令:v-cloak、v-once、v-pre 指令》 《Vue條件判斷:v-if、v-else、v-else-if、v-show 指令》 《Vue循環遍歷:v-for 指令》 《Vue事件處理:v-on 指令》 《Vue表單元素綁定:v-model 指令》…

動態IP與靜態IP該如何選?

一、當IP地址成為"網絡身份" 2023年亞馬遜封號潮中&#xff0c;某杭州賣家因登錄IP頻繁切換&#xff08;早8點在紐約&#xff0c;午間瞬移到東京&#xff09;&#xff0c;觸發平臺風控導致賬號凍結。這類"時空錯亂癥"揭示了跨境電商的生存法則&#xff1a…

【機器學習】——機器學習基礎概念

摘要 本文主要介紹了機器學習的基礎概念和典型過程。一個完整的機器學習過程包括數據收集、數據預處理、數據集劃分、選擇模型、訓練模型、模型評估、模型優化和模型部署等關鍵步驟。在數據收集階段&#xff0c;要獲取足夠且高質量的數據&#xff1b;數據預處理包括數據清理、…

麒麟信安全國產化智算一體機與海光C86芯片+ 海光DCU卡完成兼容性適配!

近日&#xff0c;麒麟信安全國產化智算一體機與國產海光C86芯片、海光DCU卡完成兼容性適配&#xff01; 在數字化轉型的浪潮中&#xff0c;智能辦公已成為企業提升效率、降低成本的重要手段&#xff0c;如何快速、高效地部署智能辦公解決方案&#xff0c;成為許多企業面臨的挑…

Axure設計之中繼器表格——拖動列調整位置教程(中繼器)

一、原理介紹 實現表格列的拖動排序&#xff0c;主要依賴Axure的動態面板和中繼器兩大核心功能&#xff1a; 動態面板交互控制 將表格的列標題封裝在動態面板中&#xff0c;通過拖拽事件&#xff08;開始、移動、結束&#xff09;捕捉用戶操作 在拖拽過程中實時計算鼠標位置&…

Vue2項目打包后,某些圖片被轉換為base64導致無法顯示

提示&#xff1a;以下是本篇文章正文內容&#xff0c;下面案例可供參考 Vue2項目打包后&#xff0c;某些圖片被轉換為base64導致無法顯示 1.為什么有些圖片會被轉成base64&#xff0c;而其他的卻正常輸出到dist/img目錄下&#xff1f; 因為Vue CLI默認可能會對小于某個閾值的…

node-red dashboard

安裝&#xff1a; npm install node-red-dashboard 訪問&#xff1a; http://127.0.0.1:1880/ui 1. 創建一個新的 Dashboard 頁面: 在 Node-RED 編輯器中&#xff0c;拖動一個 ui_dashboard 節點到工作區&#xff0c;并將其連接到你的數據流。 2. 配置 Dashboard 節點: 雙擊…

《深入探究:數字類型轉換為指定格式字符串的奧秘》

在計算機編程的世界里&#xff0c;數據就如同流淌在系統脈絡中的血液&#xff0c;而數據類型則是決定其形態與行為的關鍵基因。將數字類型轉換為字符串類型并指定格式&#xff0c;這一看似基礎的操作&#xff0c;實則蘊含著豐富的技術內涵與應用價值&#xff0c;廣泛滲透于數據…

人體細粒度分割sapiens 實戰筆記

目錄 sapiens 分割示例: 分割config文件: 依賴項: mmcv安裝 測試 cnn和ops一起測試: 報錯: 保存圖片代碼: 人體box裁剪擴大,不裁剪擴大效果很差 sapiens https://github.com/facebookresearch/sapiens 分割示例: https://github.com/facebookresearch/sapie…

【cocos creator 3.x】3Dui創建,模型遮擋ui效果

官方文檔&#xff1a;https://docs.cocos.com/creator/3.8/manual/zh/ui-system/components/editor/ui-model.html 1、3Dui創建 創建label&#xff0c;默認會添加canvas根節點和2dCamera 將Camera刪除&#xff0c;canvas上組建去除cc.Canvas&#xff0c;cc.widget&#xff0…

從零開始跑通3DGS教程:介紹

寫在前面 本文內容 本文所屬《從零開始跑通3DGS教程》系列文章&#xff0c;將實現從原始圖像(有序、無序)數據開始&#xff0c;經過處理(視頻抽幀成有序)&#xff0c;SFM&#xff0c;3DGS訓練、編輯、渲染等步驟&#xff0c;完整地呈現從原始圖像到新視角合成的全部流程&#x…

車架號查詢車牌號接口如何用Java對接

一、什么是車架號查詢車牌號接口&#xff1f; 車架號查詢車牌號接口&#xff0c;即傳入車架號&#xff0c;返回車牌號、車型編碼、初次登記日期信息。車架號又稱車輛VIN碼&#xff0c;車輛識別碼。 二、如何用Java對接該接口&#xff1f; 下面我們以阿里云接口為例&#xff0…

SvelteKit 最新中文文檔教程(12)—— 高級路由

前言 Svelte&#xff0c;一個語法簡潔、入門容易&#xff0c;面向未來的前端框架。 從 Svelte 誕生之初&#xff0c;就備受開發者的喜愛&#xff0c;根據統計&#xff0c;從 2019 年到 2024 年&#xff0c;連續 6 年一直是開發者最感興趣的前端框架 No.1&#xff1a; Svelte …

Ubuntu系統保姆級Paperless-ngx部署指南:零基礎實現文檔云端化管理

文章目錄 前言1.關于Paperless-ngx2.Docker部署3.簡單使用paperless4.安裝cpolar內網穿透5. 配置公網地址6. 配置固定公網地址總結 前言 在當今快節奏的辦公環境中&#xff0c;文檔管理成為了一個不可忽視的問題。想象一下這樣的場景&#xff1a;你需要一份重要的合同&#xf…