亮网络解锁器,解锁网络数据的无限可能 了解详情
写点什么

手把手教你在 JavaScript 中使用 LangChain,解锁 AI 应用能力

作者 | Matt Nikonorov

  • 2023-11-29
    北京
  • 本文字数:9102 字

    阅读完需:约 30 分钟

手把手教你在JavaScript中使用LangChain,解锁AI应用能力

JS 版的 LangChain,是一个功能丰富的 JavaScript 框架。不管你是开发者还是研究人员都可以利用该框架通过创建语言分析模型和 Agents 来开展各项实验。该框架还提供了十分丰富的功能设置,基于这些功能设置,NLP 爱好者可以通过构建自定义模型来提高文本数据的处理效率。与此同时,作为一个 JS 框架,开发人员可以轻松的将他们的 AI 应用集成到自己的 Web 应用中。


环境准备


安装下面的步骤,我们创建一个新目录并且安装 LangChain 的 npm 包:


1.执行如下命令,安装 LangChain 的 npm 包


npm install -S langchain
复制代码


2.在目录下面创建一个以.mjs 为后缀的文件(例如:test1.mjs)


Agents(智体)


在 LangChain 中,一个 Agent 代表的是一个具备理解和生成文本能力的实例。通过给这些 Agent 设置特定行为和数据源,就可以训练他们执行各种与语言相关的任务,从而使他们具备为更多的应用提供服务的能力。


创建 LangChain 的 Agent


利用 LangChain 框架创建的 Agent 在数据获取和响应优化上都支持“工具”的配置。请看下面的示例代码。该例中,Agent 体使用 Serp API(一个网络搜索 API)在互联网上搜索与输入内容相关的信息,然后根据搜索得到的内容完成响应数据的生成,与此同时,它还使用 llm-math 工具来执行诸如 转换单位、百分比对比等 数学运算任务。


// langchain 智能体引入import { initializeAgentExecutorWithOptions } from "langchain/agents";// 引入语言模型:OpenAiimport { ChatOpenAI } from "langchain/chat_models/openai";// 引入网络搜索工具import { SerpAPI } from "langchain/tools";// 引入计算函数 工具import { Calculator } from "langchain/tools/calculator";// OpenAI 的 API 访问的密钥process.env["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"// SerpAPI 访问密钥process.env["SERPAPI_API_KEY"] = "YOUR_SERPAPI_KEY"// 创建工具链const tools = [new Calculator(), new SerpAPI()];// 模型配置,这里用的是 OpenAI gpt-3.5-turboconst model = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0 });// 智能体初始化const executor = await initializeAgentExecutorWithOptions(tools, model, {  agentType: "openai-functions",  verbose: false,});// 执行,这里给出的问题是:"通过搜索互联网,找出自 2010 年以来 Boldy James 发行了多少张专辑,以及 Nas 自 2010 年以来发行了多少张专辑?找出谁发行了更多的专辑,并显示百分比的差异。"const result = await executor.run("By searching the Internet, find how many albums has Boldy James dropped since 2010 and how many albums has Nas dropped since 2010? Find who dropped more albums and show the difference in percent.");console.log(result);
复制代码


上述代码,在模型创建之后,通过 initializeAgentExecutorWithOptions 函数将模型和工具(SerpAPI 和 Calculator)进行合并,生成了一个 executor(执行者)。在输入端,我们要求 LLM(大语言模型) 通过搜索 Internet(使用 SerpAPI),找出自 2010 年以来,Nas 和 Boldy James 这两位艺术家中谁发行了更多专辑,并技术差值百分比(使用计算器)。


在该例子中,我通过明确地告诉 LLM“通过搜索互联网…”,以使它通过互联网获取最新数据,而不使用 OpenAI 的的默认数据(该数据截止 2021 年),从而得出正确答案。


译者注:OpenAI 于 2023 年 11 月 2 日发布会上,表示其模型数据已经更新到了 2023 年 4 月。


下面是上面代码的输出:


> node test1.mjs从 2010 年至今,Boldy James 发了 4 张专辑,Nas 发了 17 张因此,Nas 比 Boldy James 发行的专辑要多,两者发行专辑的差值是 13我们将使用如下公式:(差值 / 总值)*100,来计算差值百分比在这里,差值是 13,总值是 17因此差值百分比是:(13/17)*100 = 76.47%所以,从 2010 年至今,Nas 发布的专辑比 Boldy James 多了 76。47%
复制代码


模型(Models)


LangChain 中支持三种类型的模型使用方式:


  1. LLM(大语言模型)

  2. Chat Model(对话模型)

  3. Embeddings(Embeddings 技术是一种将高纬数据转为低维数据的技术)


下面通过示例,我们一起来了解这三种模型的使用。


语言模型


LangChain 为 JavaScript 提供了使用语言模型能力,通过该能力 JS 可以根据文本输出生成文本输出。它不像聊天模型那么复杂,最适合处理简单的输入 - 输出的语言任务。下面是一个基于 OpenAI 模型的代码示例:


import { OpenAI } from "langchain/llms/openai";const llm = new OpenAI({  openAIApiKey: "你自己的 OpenAI 的密钥",  model: "gpt-3.5-turbo",  temperature: 0});const res = await llm.call("List all red berries");console.log(res);
复制代码


如你所见,该例是要求 OpenAI 的 gpt-3.5-turbo 模型罗列所有的红色浆果。其中,我将 temperature 设为 0,其目的是为了确保 LLM 输出结果的准确性。下面是输出的结果:


1. Strawberries2. Cranberries3. Raspberries4. Redcurrants5. Red Gooseberries6. Red Elderberries7. Red Huckleberries8. Red Mulberries
复制代码


对话模型


如果你需要更复杂的答案和对话,则需要使用对话模型。对话模型在技术上与语言模型有何不同?好吧,用 LangChain 官方文档 的话来说:


对话模型是语言模型的一个变体。虽然对话模型在底层使用的依然是大语言模型,但是他们在接口上略有不同。对话模型没有使用“文本输入、文本输出”格式的 API,而是使用了一个基于“聊天消息”来实现输入输出的接口。


下面是一个简单的 JavaScript 对话模型脚本(该示例相当无用但很有趣)。


import { ChatOpenAI } from "langchain/chat_models/openai";import { PromptTemplate } from "langchain/prompts";// 创建对话,配置密钥、模型版本、和 temperatureconst chat = new ChatOpenAI({  openAIApiKey: "YOUR_OPENAI_KEY",  model: "gpt-3.5-turbo",  temperature: 0});// 通过提示词模版,创建提示词const prompt = PromptTemplate.fromTemplate(`你现在扮演一个诗人的角色,在回答时请保持语言的韵律: {question}`);const runnable = prompt.pipe(chat);// 对话执行const response = await runnable.invoke({ question: "Djokovic, Federer 和 Nadal,三人中谁是最好的网球运动员?" });console.log(response);
复制代码


如你所见,上面的代码首先发送了一条系统消息给对话机器人,告诉它,当前扮演的是一个诗人角色,且在回答的时候要始终使用押韵的方式。然后再向对话机器人发送一条用户消息,让它给出 Djokovic、Federer 和 Nadal 这三人中,谁是最好的网球运动员。如果你运行这个脚本,将会看到如下内容:


// AI 消息体AIMessage.content:'In the realm of tennis, they all shine bright,\n' +'Djokovic, Federer, and Nadal, a glorious sight.\n' +'Each with their unique style and skill,\n' +'Choosing the best is a difficult thrill.\n' +'\n' +'Djokovic, the Serb, a master of precision,\n' +'With agility and focus, he plays with decision.\n' +'His powerful strokes and relentless drive,\n' +"Make him a force that's hard to survive.\n" +'\n' +'Federer, the Swiss maestro, a true artist,\n' +'Graceful and elegant, his game is the smartest.\n' +'His smooth technique and magical touch,\n' +'Leave spectators in awe, oh so much.\n' +'\n' +'Nadal, the Spaniard, a warrior on clay,\n' +'His fierce determination keeps opponents at bay.\n' +'With his relentless power and never-ending fight,\n' +'He conquers the court, with all his might.\n' +'\n' +"So, who is better? It's a question of taste,\n" +"Each player's greatness cannot be erased.\n" +"In the end, it's the love for the game we share,\n" +'That makes them all champions, beyond compare.'
复制代码


译注:这是一首诗,实在翻译不来,就不翻译了哈。


Embeddings


Embeddings 支持将文本数据转换为向量数据,以便于和其他相关的内容进行关联。这可能听起来有点抽象,让我们直接来看一个例子:


import { OpenAIEmbeddings } from "langchain/embeddings/openai";
process.env["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
const embeddings = new OpenAIEmbeddings();
const res = await embeddings.embedQuery("谁是万维网之父?");console.log(res)
复制代码


这里是数据返回,是一大串的浮点数据:


[  0.02274114,  -0.012759142,   0.004794503,  -0.009431809,    0.01085313,  0.0019698727,  -0.013649924,   0.014933698, -0.0038185727,  -0.025400387,  0.010794181,   0.018680222,   0.020042595,   0.004303263,   0.019937797,  0.011226473,   0.009268062,   0.016125774,  0.0116391145, -0.0061765253,  -0.0073358514, 0.00021696436,   0.004896026,  0.0034026562,  -0.018365828,  ... 1501 more items]
复制代码


这就是 Embeddings 的形态。仅仅是为了六个单词,就用了那么多浮点数!利用 Embeddings 技术,可以将输入文本与潜在答案、相关文本、名称等进行关联。


下面让我们来看一个 Embeddings 模型的一个使用案例


在下面的脚本中,我们向模型提问:“世界上最重的动物是什么?”。然后我们借助 Embeddings 技术让模型能从我们提供的参考答案中找出最佳答案。


import { OpenAIEmbeddings } from "langchain/embeddings/openai";
process.env["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
const embeddings = new OpenAIEmbeddings();// 余弦相似度函数function cosinesim(A, B) { var dotproduct = 0; var mA = 0; var mB = 0;
for(var i = 0; i < A.length; i++) { dotproduct += A[i] * B[i]; mA += A[i] * A[i]; mB += B[i] * B[i]; }
mA = Math.sqrt(mA); mB = Math.sqrt(mB); var similarity = dotproduct / (mA * mB);
return similarity;}// 嵌入 1:蓝鲸是世界上最重的动物const res1 = await embeddings.embedQuery("The Blue Whale is the heaviest animal in the world");// 嵌入 2:乔治·奥威尔写了《一九八四》这本书const res2 = await embeddings.embedQuery("George Orwell wrote 1984");// 嵌入 3:随机内容const res3 = await embeddings.embedQuery("Random stuff");// 源内容数组const text_arr = ["The Blue Whale is the heaviest animal in the world", "George Orwell wrote 1984", "Random stuff"]// 利用 embeddings 转换之后的数据数组const res_arr = [res1, res2, res3]// 问题:世界上最重的动物是什么?const question = await embeddings.embedQuery("What is the heaviest animal?");// 相似度数组const sims = []for (var i=0;i<res_arr.length;i++){ // 这里利用 cosinesim 函数,计算问题和每个答案的相识度 sims.push(cosinesim(question, res_arr[i]))}// 给数组挂载求最大值的函数 (数组本身不具备, 通过原型赋予)Array.prototype.max = function() { return Math.max.apply(null, this);};// 输出相识度最大的 结果console.log(text_arr[sims.indexOf(sims.max())])
复制代码


在上面的代码中,先定义了一个计算相识度的函数:cosinesim(A, B),其次利用 embeddings 技术将每个答案转换为了向量数据,接着使用 cosinesim 函数计算出了每个答案和输入问题的相识度值,最高拿到相识度最高的答案,完成输出。下面是输出的结果:


The Blue Whale is the heaviest animal in the world// 蓝鲸是世界上最重的动物
复制代码


Chunks(数据块)


由于 LangChain 模型在生产响应的时候不支持大文本的输入。所以需要用到诸如文本分割等数据分块的技术将大文本数据分割成多个 Chunk。下面我向你演示 LangChain 中两种简单的文本数据分割方法,以实现大文本输入。


方法一、CharacterTextSplitter


为了避免分割之后,Chunk 中内容中断,可以使用换行符来进行文本拆分,该方法是在每次出现换行符时执行分割,可以通过 CharacterTextSplitter 来实现,示例代码如下:


import { Document } from "langchain/document";import { CharacterTextSplitter } from "langchain/text_splitter";// 创建一个分割器,使用换行符进行分割,每个区块的大小是 7,区块的重叠度是 3const splitter = new CharacterTextSplitter({  separator: "\n",  chunkSize: 7,  chunkOverlap: 3,});const output = await splitter.createDocuments([your_text]);
复制代码


这是拆分文本的一种有用的方法,同时,你可以使用任何字符作为 Chunk 的分隔符,而不仅仅是换行符(\n)


方法二、RecursiveCharacterTextSplitter


如果要严格按一定长度的字符拆分文本,可以使用 RecursiveCharacterTextSplitter 来实现,示例代码如下:


import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";const splitter = new RecursiveCharacterTextSplitter({  // chunk 的大小  chunkSize: 100,  // chunk 的重叠度  chunkOverlap: 15,});const output = await splitter.createDocuments([your_text]);
复制代码


在此示例中,会将文本按照每 100 个字符进行一次拆分,每个 Chunk 的重叠度为 15 个字符。


Chunk 的大小和重叠度


通过上面的示例,想必你已经迫不及待的想知道 Chunk 的大小和重叠度这两个参数确切的含义以及它们对性能的影响了吧。下面我简单从两方面解释下:


  • chunkSize 决定了每个 Chunk 中的字符数量。chunkSize 的值越大,那么 Chunk 中的字符数就越多,LangChain 处理该 Chunk 和产生对应输出所需的时间就越长,反之亦然。

  • chunkOverlap 是用于设置了每个 Chunk 之间共享上下文的大小。chunkOverlap 的值越高,Chunk 的冗余度就越高 ;chunkOverlap 的值越低,Chunk 之间共享的上下文就越少。通常将 chunkOverlap 设置在 Chunk 大小的 10% 到 20% 之间会比较理想,当然,真正理想 chunkOverlap 值还是要根据不同的文本类型和使用场景来确定。


Chains(模型链)


通过单个 LLM 的输入输出是无法完成一些更为复杂的任务,因此需要利用 Chains,通过将多个 LLM 的功能链接一起来完成。下面是一个很有意思的例子:


import { ChatPromptTemplate } from "langchain/prompts";import { LLMChain } from "langchain/chains";import { ChatOpenAI } from "langchain/chat_models/openai";
process.env["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"
// 这是一段知识库const wiki_text = `Alexander Stanislavovich 'Sasha' Bublik (Александр Станиславович Бублик; born 17 June 1997) is a Kazakhstani professional tennis player. He has been ranked as high as world No. 25 in singles by the Association of Tennis Professionals (ATP), which he achieved in July 2023, and is the current Kazakhstani No. 1 player...
Alexander Stanislavovich Bublik was born on 17 June 1997 in Gatchina, Russia and began playing tennis at the age of four. He was coached by his father, Stanislav. On the junior tour, Bublik reached a career-high ranking of No. 19 and won eleven titles (six singles and five doubles) on the International Tennis Federation (ITF) junior circuit.[4][5]...`const chat = new ChatOpenAI({ temperature: 0 });const chatPrompt = ChatPromptTemplate.fromMessages([ [ "system", "You are a helpful assistant that {action} the provided text", ], ["human", "{text}"],]);// 这里将 2 个模型进行了链接const chainB = new LLMChain({ prompt: chatPrompt, llm: chat,});
const resB = await chainB.call({ action: "lists all important numbers from", text: wiki_text,});console.log({ resB });
复制代码


在上面的代码中,我在提示词中设置了一个变量,同时通过将 LLM 的 temperature 设置为 0,以要求 LLM 给出一个基于事实的回答。该例中,我要求 LLM 基于给定的简短知识库,输出我最喜欢网球运动员的关键数据。以下是 LLM 给出的回答:


{  resB: {    text: 'Important numbers from the provided text:\n' +      '\n' +      "- Alexander Stanislavovich 'Sasha' Bublik's date of birth: 17 June 1997\n" +      "- Bublik's highest singles ranking: world No. 25\n" +      "- Bublik's highest doubles ranking: world No. 47\n" +      "- Bublik's career ATP Tour singles titles: 3\n" +      "- Bublik's career ATP Tour singles runner-up finishes: 6\n" +      "- Bublik's height: 1.96 m (6 ft 5 in)\n" +      "- Bublik's number of aces served in the 2021 ATP Tour season: unknown\n" +      "- Bublik's junior tour ranking: No. 19\n" +      "- Bublik's junior tour titles: 11 (6 singles and 5 doubles)\n" +      "- Bublik's previous citizenship: Russia\n" +      "- Bublik's current citizenship: Kazakhstan\n" +      "- Bublik's role in the Levitov Chess Wizards team: reserve member"  }}
复制代码


很酷,但这还没有真正展示 Chains 的全部能力。再看一个更实际的例子:


import { z } from "zod";import { zodToJsonSchema } from "zod-to-json-schema";import { ChatOpenAI } from "langchain/chat_models/openai";import {  ChatPromptTemplate,  SystemMessagePromptTemplate,  HumanMessagePromptTemplate,} from "langchain/prompts";import { JsonOutputFunctionsParser } from "langchain/output_parsers";process.env["OPENAI_API_KEY"] = "YOUR_OPENAI_KEY"const zodSchema = z.object({  albums: z    .array(      z.object({        name: z.string().describe("The name of the album"),        artist: z.string().describe("The artist(s) that made the album"),        length: z.number().describe("The length of the album in minutes"),        genre: z.string().optional().describe("The genre of the album"),      })    )    .describe("An array of music albums mentioned in the text"),});const prompt = new ChatPromptTemplate({  promptMessages: [    SystemMessagePromptTemplate.fromTemplate(      "List all music albums mentioned in the following text."    ),    HumanMessagePromptTemplate.fromTemplate("{inputText}"),  ],  inputVariables: ["inputText"],});const llm = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0 });const functionCallingModel = llm.bind({  functions: [    {      name: "output_formatter",      description: "Should always be used to properly format output",      parameters: zodToJsonSchema(zodSchema),    },  ],  function_call: { name: "output_formatter" },});const outputParser = new JsonOutputFunctionsParser();const chain = prompt.pipe(functionCallingModel).pipe(outputParser);const response = await chain.invoke({  inputText: "My favorite albums are: 2001, To Pimp a Butterfly and Led Zeppelin IV",});console.log(JSON.stringify(response, null, 2));
复制代码


此脚本通过读取输入的文本信息,识别所有提到的音乐专辑以及将每张专辑的名称、艺术家、长度和流派,最后将所有数据转换为 JSON 格式进行输出。以下是输入“我最喜欢的专辑是:2001 年、To Pimp a Butterfly 和 Led Zeppelin IV”的输出:


{  "albums": [    {      "name": "2001",      "artist": "Dr. Dre",      "length": 68,      "genre": "Hip Hop"    },    {      "name": "To Pimp a Butterfly",      "artist": "Kendrick Lamar",      "length": 79,      "genre": "Hip Hop"    },    {      "name": "Led Zeppelin IV",      "artist": "Led Zeppelin",      "length": 42,      "genre": "Rock"    }  ]}
复制代码


虽然这只是一个有趣的例子,但通过该技术可以将非结构化的文本数据转为结构化的数据,从而使用在其他应用系统中。


不止 OpenAI


尽管在演示 LangChain 不同功能的示例中,我一直都是使用 OpenAI 模型。但其实 LangChain 并不局限于 OpenAI 模型。你可以将 LangChain 与许多其他 LLM 和 AI 服务一起使用。在 LangChain 的官方文档中可以找到 LangChain 的 JS 版本所支持集成的完整 LLM 列表。


例如,你可以将 Cohere 与 LangChain 一起使用。再使用 npm install cohere-ai 安装 Cohere 之后,你就可以像下面示例代码一样,使用 LangChain 和 Cohere 编写一个简单的问答脚本:


import { Cohere } from "langchain/llms/cohere";const model = new Cohere({  maxTokens: 50,  apiKey: "YOUR_COHERE_KEY", // In Node.js defaults to process.env.COHERE_API_KEY});const res = await model.call(  "Come up with a name for a new Nas album" // 给 Nas 的新专辑起个名字);console.log({ res });
复制代码


输出的结果如下:


{  res: ' Here are a few possible names for a new Nas album:\n' +    '\n' +    "- King's Landing\n" +    "- God's Son: The Sequel\n" +    "- Street's Disciple\n" +    '- Izzy Free\n' +    '- Nas and the Illmatic Flow\n' +    '\n' +    'Do any'}
复制代码


总结


读完本篇文章,相信你已经对 JS 版的 LangChain 各方面能力都有所了解了。现在你可以通过 LangChain 用 JS 开发各种基于 AI 的应用和体验 LLM 了。当然,也请你必参考 LangChainJS 的官方文档,以了解更多有关特定功能的详细信息。


最后,预祝你在 JavaScript 中愉快的使用 LangChain 进行编码和体验!如果你喜欢这篇文章,你可能还想阅读如何在 Python 中使用 LangChain 这篇文章:


https://www.sitepoint.com/langchain-python-complete-guide/


原文链接:


https://www.sitepoint.com/langchain-javascript-complete-guide/


相关阅读:

LangChain 的问题所在

OpenAI 用 45 分钟重塑游戏规则!干掉 MJ、LangChain,创造“不会编程的应用开发者”新职业

LangChain:2023 年最潮大语言模型 Web 开发框架

理论 + 实践详解最热的 LLM 应用框架 LangChain

公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2023-11-29 13:584731

评论

发布
暂无评论
发现更多内容

一篇文章看懂 JavaScript 如何实现继承

树上有只程序猿

JavaScript proto

点对点传输技术可实现更大的文件传输

镭速

大文件传输 点对点传输

一文带你了解跨境数据传输和隐私

镭速

跨境数据传输

本文介绍如何使用 Three.js 库在边界框和球体之间实现冲突检测。假设在阅读本文之前,您已经先阅读了我们的 3D 碰撞检测介绍性文章,并了解了 Three.js 的基本知识。

3D建模设计

3D

什么是数字孪生?

3D建模设计

数字孪生

开源图形驱动在OpenHarmony上的使用和落地

OpenHarmony开发者

OpenHarmony

PoseiSwap 开启“Poseidon”池,治理体系或将全面开启

威廉META

Ascend C保姆级教程:我的第一份Ascend C代码

华为云开发者联盟

人工智能 华为云 昇腾 华为云开发者联盟 企业号 8 月 PK 榜

生成式AI:全球传媒软件市场的璀璨新星

百度开发者中心

人工智能 媒体 生成式AI 文心一言

7 个使用生成式 AI 构建的项目

3D建模设计

生成式AI

深入MaxCompute -第十一弹 -QUALIFY

阿里云大数据AI技术

大数据

Java单元测试及常用语句 | 京东物流技术团队

京东科技开发者

Mockito 测试 单元测试 企业号 8 月 PK 榜 Java单元测试

软件测试/测试开发丨Python 内置库 正则表达式

测试人

Python 正则表达式 程序员 软件测试 自动化测试

生成式人工智能能否使数字孪生在能源和公用事业行业成为现实?

3D建模设计

数字孪生 生成式AI

揭秘ChatGPT,如何打造自己的自定义指令 | 京东云技术团队

京东科技开发者

自定义指令 大语言模型 chatgpt app 企业号 8 月 PK 榜

软件测试 | 人工智能:优势与挑战

测吧(北京)科技有限公司

测试

浅析Java - SPI机制 | 京东云技术团队

京东科技开发者

Java 后端 spi 企业号 8 月 PK 榜

云密一体,京东云密码资源池实力守护安全防线

京东科技开发者

云原生 网络安全 密码安全 企业号 8 月 PK 榜

Xmind for Mac(思维导图软件) 23.08中文激活版

mac

XMind 思维导图软件 苹果mac Windows软件

生成式AI艺术创新

百度开发者中心

人工智能 生成式AI 文心一言

Comparing WiFi Performance: IPQ5018 vs IPQ4019/IPQ4029 SoMs

wallyslilly

IPQ4019 ipq4029 ipq5018

机场数据安全三步走战略|盾见

极盾科技

数据安全

KaiwuDB 助力能源企业实现 4 大价值提升

KaiwuDB

KaiwuDB 分布式储能

生成式AI:提高生产力,重塑未来行业

百度开发者中心

人工智能 ChatGPT 生成式AI 文心一言

快乐开源活动全面升级!提PR,赢PS5、Switch等缤纷好礼

飞桨PaddlePaddle

人工智能 百度飞桨

关于我为什么要用微前端这件事

这我可不懂

架构 前端开发 微前端

使用 THREE.js 进行边界体积碰撞检测

3D建模设计

three.js 碰撞检测

【稳定性】揭秘团队快速排查问题的三字经,你学会了吗? | 京东物流技术团队

京东科技开发者

团队 线上故障 故障排查 企业号 8 月 PK 榜

人工智能改善生活:不同受众的定制化应用

测吧(北京)科技有限公司

高效构建实时数仓:探秘NineData数据复制技术

NineData

数据库 大数据 实时数仓 数据复制 迁移指南

盘点那些国际知名黑客(上篇)

禅道项目管理

手把手教你在JavaScript中使用LangChain,解锁AI应用能力_生成式 AI_InfoQ精选文章