打造本地化模型工作流-AI助手全面升级

Dify的介绍与安装

  • Dify是什么?

用他们自己的官网(https://dify.ai/)介绍来说他们是:The Innovation Engine for GenAl Applications——它是生成式AI应用的创新引擎

Dify是GitHub的开源的项目(https://github.com/langgenius/dify)

  • Dify的特性

对比我们之前用到的MaxKB来说,Dify无疑是一个全面加强的生成式AI的创建引擎

他的能力不仅包含MaxKB的RAG引擎。也同时可以本地化部署,更可以建立业务场景更为复杂的Agent以及Workflow。当然这也只是Dify的主要特性。

随着我们进行安装部署后,在我们的一步步探索中,将逐步发现Dify的强大能力。

  • Dify的安装与部署

    我们来到Dify的github主页并且clone代码到本地

  • https://github.com/langgenius/dify
    

    然后在代码的根目录执行

  • cd docker``cp .env.example .env``docker compose up -d
    

没错,这又是一个基于docker的项目,等待拉取对应组件并且安装后。Dify就算安装成功了

我们可以看到安装并且运行中的Dify包含nginx,redis,poestgresql等等多个部分。相比MaxKB的结构来说就已经复杂了好多。

这里我们可以看到,其中nginx组件把容器中的80端口映射到本机的80端口了。

没错,我们想体验本地化部署的Dify,访问http://localhost/apps这个地址就好了。

首次登录会进行进入初始化页面,会要求提供一个你的邮箱作为管理员账户。设置好后,就可以进入Dify的主页了

  • 模型配置

首先我们聚焦到右上角的设置区

在这里我们又看到了熟悉的配置模型的内容,以及我们的老朋友Ollama。当然几乎所有知名的AI提供商,都可以配置在Dify中。这里我们配置了本地的Ollama以及智谱-AI。

Ollama的配置主要是localhost:11434的端口配置,其他AI提供商的则是需要在对应网站获取API-EKY并且配置到Dify中。

  • 第一个AI应用

我们再回到Dify主页,先可以简单设置一个聊天工具。

在创建完成后我们在这个应用的配置页面,发现了一些熟悉的东西,M阿西KB创建应用时候出现过的提示词、本地知识库Dify是全面支持的。另外右上角,我们可以随时随意的切换这个应用所使用的模型。同时也可以在这里进行简单的测试,没有问题后就可以把这个应用发布了

发布完成后,会在Dify的主页看到这个应用。

  • 打造期待的工作流

    在Dify中我们可以设置三类应用,分别是聊天助手、Agent、工作流。

    回顾一下上一次我们设想的客服助手需要实现的功能。

那么这个流程现在是可以通过Dify的工作流实现的了。

根据Dify的工作流的组件

工作流是由我们自行定义和组合的节点组成的顺序执行的流程

结合我们的业务流程图。发现所有我们所需的节点都有解决方案。

在业务流程中,问题分类,对应Dify的问题分类器节点。而 function call部分则对应着HTTP请求。

为了验证我们的流程,我们建立一个电商助手的工作流:

它能支持三类问题:1.优惠券问题 2.订单问题 3.其他问题

一、如果提问内容与优惠券问题相关联,则会1.调用优惠券信息接口 2.调用优惠券知识库 3.把以上内容作为上下文传入优惠券推理模型,由模型结合问题给出答案

二、如果提问内容与订单问题相关联,则会1.调用订单信息接口 2.将订单信息接口上下文传入优惠券推理模型,由模型结合问题给出答案

三、其他类的问题,则直接把用户问题接入通用处理大模型

根据以上基本应用需求。我们规划的工作流如下

为此我们也建立了两个模拟接口分别是优惠券信息与订单信息

这里仅以优惠券信息为例

    `@RequestMapping("/coupon")`    `public String coupon(){`        `Map<String ,String> coupon = new HashMap<>();`        `coupon.put("valid_start_time","2018-06-18 10:53:22");`        `coupon.put("valid_end_time","2025-10-20 10:53:25");`        `coupon.put("name","新人礼包券");`        `coupon.put("id","4dbaee58d68ef8ea");`        `coupon.put("current_time", DateUtil.now());`        `Map<String ,String> coupon2 = new HashMap<>();`        `coupon2.put("valid_start_time","2018-06-18 10:53:22");`        `coupon2.put("valid_end_time","2023-10-20 10:53:25");`        `coupon2.put("name","回归礼包券");`        `coupon2.put("id","51dee58d68ef8ea");`        `coupon.put("current_time", DateUtil.now());`        `List<Map<String,String>> couponList = new ArrayList<>();`        `couponList.add(coupon);`        `couponList.add(coupon2);`        `return JSONUtil.toJsonStr(couponList);`    `}`

这里包括valid_end_time优惠券过期时间,以及当前时间current_time

同时我们也在Dify中设置了优惠券规则的知识库,规定了优惠券过期的判断依据

所有组件都准备完毕后,剩下的工作流配置就没有障碍了。

下面我们逐一介绍Dify流程中我们用到的几个节点以及配置内容

开始节点

开始节点是流程的开始,这里可以自定义整个工作流的入参,这里我们配置了两个参数chat,以及userid。chat是用户提出的问题,userid则是记录用户的id。在后续的场景中,可能会产生依据userid进行查询某个API的可能性。

问题分类器

本质上还是一个语言模型,他会根据前置节点的输入信息进行合理的推断,从而进行流程的路由分发工作

这里的分类尽量要贴合前置节点(本例中的开始节点中的chat内容)

HTTP请求

这里的配置与一般的http请求配置方式是一致的。这里不再赘述,这里特别提一点,参数值params里是可以指定之前节点中的各种参数值的,这里我加了一个参数userid,其值来源就是在开始节点中的入参userid。

知识检索

这里的配置特别提示的就是查询变量,这里也是需要指定一个查询变量的。依据这个变量进行RAG检索以及召回动作。

LLM模型

这个就是一个标准的语言模型的节点了。我们可以配置具体的模型,相关的提示词,另外这里特别强调一下,本地化的模型特别的“不听话”,所以提示词的建立还是需要一些技巧,慢慢引导模型懂你的意思的。这个过程可以单独建立一个语言模型应用不断尝试。最终打磨出适合的提示词。

结束

这里是工作流的重点,需要配置的内容是返回值。在这个例子中我们返回的是前一步优惠券推理模型的输出结果。以文字形式输出。

再补全其他两个分支的工作流,这时我们再完整的看下这个工作流

然后可以点运行并且在输入参数后进行流程测试

  • 运行过程中,我们可以看到运行的流程节点间的线段会变成蓝色

  • 运行完毕后,也看到了最终输出的结果

  • 发布、调试、集成到其他系统

    在线测试满意之后,我们就可以把这个应用发布出来了。应

  • 发布完成后,我们点击这个访问API

这里提供了通过API访问这个工作流应用的说明文档。

   curl -X POST 'http://localhost/v1/workflows/run' \``--header 'Authorization: Bearer app-v46HdwGDpo2kUUcBbmSHobwD' \``--header 'Content-Type: application/json' \``--data-raw '{`    `"inputs": {  "chat":"哪张优惠券可用?","userId": "123"},`    `"response_mode": "streaming",`    `"user": "abc-123"``}'``   
    data: {"event": "workflow_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "workflow_id": "df3ab5a5-e15e-4c10-aa34-f4730dc85853", "sequence_number": 14, "inputs": {"chat": "\u4f18\u60e0\u5238", "sys.files": [], "sys.user_id": "abc-123"}, "created_at": 1720061525}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "59f4329b-9879-4a66-b428-9e90cc939139", "node_id": "1720001015245", "node_type": "start", "title": "\u5f00\u59cb", "index": 1, "predecessor_node_id": null, "inputs": null, "created_at": 1720061525, "extras": {}}}``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "59f4329b-9879-4a66-b428-9e90cc939139", "node_id": "1720001015245", "node_type": "start", "title": "\u5f00\u59cb", "index": 1, "predecessor_node_id": null, "inputs": {"chat": "\u4f18\u60e0\u5238", "sys.files": [], "sys.user_id": "abc-123"}, "process_data": null, "outputs": {"chat": "\u4f18\u60e0\u5238", "sys.files": [], "sys.user_id": "abc-123"}, "status": "succeeded", "error": null, "elapsed_time": 0.0009632089931983501, "execution_metadata": null, "created_at": 1720061525, "finished_at": 1720061524, "files": []}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "45588b3f-7011-400e-ac88-2d22b8d12d76", "node_id": "1720058356548", "node_type": "question-classifier", "title": "\u95ee\u9898\u5206\u7c7b\u5668", "index": 2, "predecessor_node_id": "1720001015245", "inputs": null, "created_at": 1720061525, "extras": {}}}``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "45588b3f-7011-400e-ac88-2d22b8d12d76", "node_id": "1720058356548", "node_type": "question-classifier", "title": "\u95ee\u9898\u5206\u7c7b\u5668", "index": 2, "predecessor_node_id": "1720001015245", "inputs": {"query": "\u4f18\u60e0\u5238"}, "process_data": {"model_mode": "chat", "prompts": [{"role": "system", "text": "\n    ### Job Description',\n    You are a text classification engine that analyzes text data and assigns categories based on user input or automatically determined categories.\n    ### Task\n    Your task is to assign one categories ONLY to the input text and only one category may be assigned returned in the output.Additionally, you need to extract the key words from the text that are related to the classification.\n    ### Format\n    The input text is in the variable text_field.Categories are specified as a category list with two filed category_id and category_name in the variable categories .Classification instructions may be included to improve the classification accuracy.\n    ### Constraint\n    DO NOT include anything other than the JSON array in your response.\n    ### Memory\n    Here is the chat histories between human and assistant, inside <histories></histories> XML tags.\n    <histories>\n    \n    </histories>\n", "files": []}, {"role": "user", "text": "\n    { \"input_text\": [\"I recently had a great experience with your company. The service was prompt and the staff was very friendly.\"],\n    \"categories\": [{\"category_id\":\"f5660049-284f-41a7-b301-fd24176a711c\",\"category_name\":\"Customer Service\"},{\"category_id\":\"8d007d06-f2c9-4be5-8ff6-cd4381c13c60\",\"category_name\":\"Satisfaction\"},{\"category_id\":\"5fbbbb18-9843-466d-9b8e-b9bfbb9482c8\",\"category_name\":\"Sales\"},{\"category_id\":\"23623c75-7184-4a2e-8226-466c2e4631e4\",\"category_name\":\"Product\"}],\n    \"classification_instructions\": [\"classify the text based on the feedback provided by customer\"]}\n", "files": []}, {"role": "assistant", "text": "\n```json\n    {\"keywords\": [\"recently\", \"great experience\", \"company\", \"service\", \"prompt\", \"staff\", \"friendly\"],\n    \"category_id\": \"f5660049-284f-41a7-b301-fd24176a711c\",\n    \"category_name\": \"Customer Service\"}\n```\n", "files": []}, {"role": "user", "text": "\n    {\"input_text\": [\"bad service, slow to bring the food\"],\n    \"categories\": [{\"category_id\":\"80fb86a0-4454-4bf5-924c-f253fdd83c02\",\"category_name\":\"Food Quality\"},{\"category_id\":\"f6ff5bc3-aca0-4e4a-8627-e760d0aca78f\",\"category_name\":\"Experience\"},{\"category_id\":\"cc771f63-74e7-4c61-882e-3eda9d8ba5d7\",\"category_name\":\"Price\"}],\n    \"classification_instructions\": []}\n", "files": []}, {"role": "assistant", "text": "\n```json\n    {\"keywords\": [\"bad service\", \"slow\", \"food\", \"tip\", \"terrible\", \"waitresses\"],\n    \"category_id\": \"f6ff5bc3-aca0-4e4a-8627-e760d0aca78f\",\n    \"category_name\": \"Experience\"}\n```\n", "files": []}, {"role": "user", "text": "\n    '{\"input_text\": [\"\u4f18\u60e0\u5238\"],',\n    '\"categories\": [{\"category_id\": \"1\", \"category_name\": \"\u4f18\u60e0\u5238\u95ee\u7b54\"}, {\"category_id\": \"2\", \"category_name\": \"\u666e\u901a\u95ee\u7b54\"}], ',\n    '\"classification_instructions\": [\"\"]}'\n", "files": []}], "usage": {"prompt_tokens": 887, "prompt_unit_price": "0", "prompt_price_unit": "0", "prompt_price": "0.0000000", "completion_tokens": 138, "completion_unit_price": "0", "completion_price_unit": "0", "completion_price": "0.0000000", "total_tokens": 1025, "total_price": "0.0000000", "currency": "USD", "latency": 7.283583379001357}}, "outputs": {"class_name": "\u4f18\u60e0\u5238\u95ee\u7b54"}, "status": "succeeded", "error": null, "elapsed_time": 7.29491296201013, "execution_metadata": {"total_tokens": 1025, "total_price": "0.0000000", "currency": "USD"}, "created_at": 1720061525, "finished_at": 1720061531, "files": []}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "2e05dc89-a9e5-4461-a226-80368e1ba1b3", "node_id": "1720058784300", "node_type": "http-request", "title": "HTTP \u8bf7\u6c42 2", "index": 3, "predecessor_node_id": "1720058356548", "inputs": null, "created_at": 1720061532, "extras": {}}}``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "2e05dc89-a9e5-4461-a226-80368e1ba1b3", "node_id": "1720058784300", "node_type": "http-request", "title": "HTTP \u8bf7\u6c42 2", "index": 3, "predecessor_node_id": "1720058356548", "inputs": null, "process_data": {"request": "GET http://host.docker.internal:8080/coupon HTTP/1.1\n\n"}, "outputs": {"status_code": 200, "body": "[{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u65b0\u4eba\u793c\u5305\u5238\",\"valid_end_time\":\"2025-10-20 10:53:25\",\"id\":\"4dbaee58d68ef8ea\",\"current_time\":\"2024-07-04 10:52:11\"},{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u56de\u5f52\u793c\u5305\u5238\",\"valid_end_time\":\"2023-10-20 10:53:25\",\"id\":\"51dee58d68ef8ea\"}]", "headers": {"content-type": "text/plain;charset=UTF-8", "content-length": "299", "date": "Thu, 04 Jul 2024 02:52:11 GMT", "cache-status": "47ea977ee374;fwd=stale;detail=match", "via": "1.1 47ea977ee374 (squid/6.1)", "connection": "keep-alive"}, "files": []}, "status": "succeeded", "error": null, "elapsed_time": 0.06886870801099576, "execution_metadata": null, "created_at": 1720061532, "finished_at": 1720061531, "files": []}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "7b3e53a1-69e8-4be1-b159-62a311a7c29d", "node_id": "1720001028973", "node_type": "knowledge-retrieval", "title": "\u77e5\u8bc6\u68c0\u7d22", "index": 4, "predecessor_node_id": "1720058784300", "inputs": null, "created_at": 1720061532, "extras": {}}}``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "7b3e53a1-69e8-4be1-b159-62a311a7c29d", "node_id": "1720001028973", "node_type": "knowledge-retrieval", "title": "\u77e5\u8bc6\u68c0\u7d22", "index": 4, "predecessor_node_id": "1720058784300", "inputs": {"query": "\u4f18\u60e0\u5238"}, "process_data": null, "outputs": {"result": [{"metadata": {"_source": "knowledge", "position": 1, "dataset_id": "9521cccb-313a-42a0-8a2f-ecc040970964", "dataset_name": "\u4f18\u60e0\u5238\u89c4\u5219", "document_id": "6790853d-cd4a-4dfa-8062-ddd1c15aa594", "document_name": "\u4f18\u60e0\u5238\u89c4\u5219.docx", "document_data_source_type": "upload_file", "segment_id": "a36d593d-c3c4-44cb-8ea0-758560fa72fe", "retriever_from": "workflow", "score": 0.54185438, "segment_hit_count": 10, "segment_word_count": 50, "segment_position": 1, "segment_index_node_hash": "1350de447714b3750a132bef35b6e4b16c5c89360c5ca9683ecaa50a31a81e29"}, "title": "\u4f18\u60e0\u5238\u89c4\u5219.docx", "content": "\u5f53\u4f18\u60e0\u5238\u7684valid_end_time\u5c5e\u6027\u5c0f\u4e8ecurrent_time\u5f53\u524d\u65f6\u95f4\u65f6\uff0c\u4f18\u60e0\u5238\u5224\u5b9a\u4e3a\u8fc7\u671f\u3002"}]}, "status": "succeeded", "error": null, "elapsed_time": 0.021647582994773984, "execution_metadata": null, "created_at": 1720061532, "finished_at": 1720061531, "files": []}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "861b49f6-530c-4fb2-92f1-3d690a1e27f0", "node_id": "1720058769328", "node_type": "llm", "title": "LLM 2", "index": 5, "predecessor_node_id": "1720001028973", "inputs": null, "created_at": 1720061532, "extras": {}}}``   ``event: ping``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "861b49f6-530c-4fb2-92f1-3d690a1e27f0", "node_id": "1720058769328", "node_type": "llm", "title": "LLM 2", "index": 5, "predecessor_node_id": "1720001028973", "inputs": {"#context#": "\u5f53\u4f18\u60e0\u5238\u7684valid_end_time\u5c5e\u6027\u5c0f\u4e8ecurrent_time\u5f53\u524d\u65f6\u95f4\u65f6\uff0c\u4f18\u60e0\u5238\u5224\u5b9a\u4e3a\u8fc7\u671f\u3002"}, "process_data": {"model_mode": "chat", "prompts": [{"role": "system", "text": "\u6839\u636e[{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u65b0\u4eba\u793c\u5305\u5238\",\"valid_end_time\":\"2025-10-20 10:53:25\",\"id\":\"4dbaee58d68ef8ea\",\"current_time\":\"2024-07-04 10:52:11\"},{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u56de\u5f52\u793c\u5305\u5238\",\"valid_end_time\":\"2023-10-20 10:53:25\",\"id\":\"51dee58d68ef8ea\"}]\u662f\u4f18\u60e0\u5238\u7684\u5217\u8868\uff0c\u5305\u542b\u5230\u671f\u65f6\u95f4\u548c\u5f53\u524d\u65f6\u95f4\uff0c\u4f60\u4ec5\u9700\u8981\u6839\u636e\u8fd9\u4e24\u4e2a\u65f6\u95f4\u8fdb\u884c\u5224\u65ad\u3002\u4ee5\u3010\u53ef\u7528\u7684\u4f18\u60e0\u5238\u540d\u79f0\uff1axxx\uff0c\u5230\u671f\u65f6\u95f4\u4e3ayyy \u3011\u8fd9\u79cd\u683c\u5f0f\u8f93\u51fa\u3002\u4e0d\u9700\u8981\u8f93\u51fa\u63a8\u7406\u8fc7\u7a0b\uff0c\u4ec5\u6309\u89c4\u5b9a\u683c\u5f0f\u8f93\u51fa", "files": []}, {"role": "user", "text": "\u6839\u636e[{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u65b0\u4eba\u793c\u5305\u5238\",\"valid_end_time\":\"2025-10-20 10:53:25\",\"id\":\"4dbaee58d68ef8ea\",\"current_time\":\"2024-07-04 10:52:11\"},{\"valid_start_time\":\"2018-06-18 10:53:22\",\"name\":\"\u56de\u5f52\u793c\u5305\u5238\",\"valid_end_time\":\"2023-10-20 10:53:25\",\"id\":\"51dee58d68ef8ea\"}]\u662f\u4f18\u60e0\u5238\u7684\u5217\u8868\uff0c\u5305\u542b\u5230\u671f\u65f6\u95f4\u548c\u5f53\u524d\u65f6\u95f4\uff0c\u4f60\u4ec5\u9700\u8981\u5f53\u4f18\u60e0\u5238\u7684valid_end_time\u5c5e\u6027\u5c0f\u4e8ecurrent_time\u5f53\u524d\u65f6\u95f4\u65f6\uff0c\u4f18\u60e0\u5238\u5224\u5b9a\u4e3a\u8fc7\u671f\u3002\u4ece\u77e5\u8bc6\u68c0\u7d22\u5185\u5bb9\u4e2d\uff0c\u6839\u636e\u8fd9\u4e24\u4e2a\u65f6\u95f4\u8fdb\u884c\u5224\u65ad\u3002\u4ee5\u3010\u53ef\u7528\u7684\u4f18\u60e0\u5238\u540d\u79f0\uff1axxx\uff0c\u5230\u671f\u65f6\u95f4\u4e3ayyy \u3011\u8fd9\u79cd\u683c\u5f0f\u8f93\u51fa\u3002\u4e0d\u9700\u8981\u8f93\u51fa\u63a8\u7406\u8fc7\u7a0b\uff0c\u4ec5\u6309\u89c4\u5b9a\u683c\u5f0f\u8f93\u51fa", "files": []}]}, "outputs": {"text": "\u6839\u636e\u63d0\u4f9b\u7684\u4f18\u60e0\u5238\u5217\u8868\uff1a\n\n1. \u65b0\u4eba\u793c\u5305\u5238\uff08id: 4dbaee58d68ef8ea\uff09\uff0cvalid_end_time: 2025-10-20 10:53:25\uff0ccurrent_\u65f6\u95f4: 2024-07-04 10:52:11\u3002\u8be5\u5238\u5c1a\u672a\u8fc7\u671f\u3002\n\n2. \u56de\u5f52\u793c\u5305\u5238\uff08id: 51dee58d68ef8ea\uff09\uff0cvalid_end_time: 2023-10-20 10:53:25\uff0ccurrent_\u65f6\u95f4: 2024-07-04 10:52:11\u3002\u8be5\u5238\u5df2\u8fc7\u671f\u3002\n\n\u8f93\u51fa\u683c\u5f0f\u5982\u4e0b\uff1a\n\n\u3010\u53ef\u7528\u7684\u4f18\u60e0\u5238\u540d\u79f0\uff1a\u65b0\u4eba\u793c\u5305\u5238\uff0c\u5230\u671f\u65f6\u95f4\u4e3a2025-10-20 10:53:25\u3011\n\u3010\u5df2\u8fc7\u671f\u7684\u4f18\u60e0\u5238\u540d\u79f0\uff1a\u56de\u5f52\u793c\u5305\u5238\uff0c\u5230\u671f\u65f6\u95f4\u4e3a2023-10-20 10:53:25\u3011", "usage": {"prompt_tokens": 483, "prompt_unit_price": "0", "prompt_price_unit": "0", "prompt_price": "0.0000000", "completion_tokens": 239, "completion_unit_price": "0", "completion_price_unit": "0", "completion_price": "0.0000000", "total_tokens": 722, "total_price": "0.0000000", "currency": "USD", "latency": 8.947470255021472}}, "status": "succeeded", "error": null, "elapsed_time": 8.956229670991888, "execution_metadata": {"total_tokens": 722, "total_price": "0.0000000", "currency": "USD"}, "created_at": 1720061532, "finished_at": 1720061540, "files": []}}``   ``data: {"event": "node_started", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "98189293-b1c5-4a91-8b81-13b318eef349", "node_id": "1720061330502", "node_type": "end", "title": "\u7ed3\u675f", "index": 6, "predecessor_node_id": "1720058769328", "inputs": null, "created_at": 1720061541, "extras": {}}}``   ``data: {"event": "node_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "98189293-b1c5-4a91-8b81-13b318eef349", "node_id": "1720061330502", "node_type": "end", "title": "\u7ed3\u675f", "index": 6, "predecessor_node_id": "1720058769328", "inputs": null, "process_data": null, "outputs": null, "status": "succeeded", "error": null, "elapsed_time": 0.0010395830031484365, "execution_metadata": null, "created_at": 1720061541, "finished_at": 1720061540, "files": []}}``   ``data: {"event": "workflow_finished", "workflow_run_id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "task_id": "6dc14f97-cc31-404f-911b-42d4967c8e23", "data": {"id": "fdb58da5-87d5-4a65-8c82-214539f573a2", "workflow_id": "df3ab5a5-e15e-4c10-aa34-f4730dc85853", "sequence_number": 14, "status": "succeeded", "outputs": null, "error": null, "elapsed_time": 16.399369008024223, "total_tokens": 1747, "total_steps": 6, "created_by": {"id": "6caaa9b1-0abd-4de7-b780-ddc5ff5f3c2a", "user": "abc-123"}, "created_at": 1720061525, "finished_at": 1720061540, "files": []}}
  • 这里有一些小困难,就是返回的是流式信息

    为此,我们特别设计了一个处理流式返回值的方法如下

    import cn.hutool.http.HttpResponse;``import cn.hutool.http.HttpUtil;``import cn.hutool.json.JSONObject;``import cn.hutool.json.JSONUtil;``   ``public class WorkFlowApi {`    `private static final String URL = "http://localhost/v1/workflows/run";`    `private static final String AUTH_TOKEN = "app-v46HdwGDpo2kUUcBbmSHobwD";``   `    `public void runWorkflow(String chat, String userId) {`        `JSONObject json = new JSONObject();`        `json.putOpt("inputs", new JSONObject().putOpt("chat", chat).putOpt("user", userId));`        `json.putOpt("response_mode", "streaming");`        `json.putOpt("user", userId);``   `        `HttpResponse response = HttpUtil.createPost(URL)`                `.header("Authorization", "Bearer " + AUTH_TOKEN)`                `.header("Content-Type", "application/json")`                `.body(json.toString())`                `.execute();``   `        `if (response.isOk()) {`            `String responseBody = response.body();`            `// 解析响应数据`            `String[] lines = responseBody.split("\n");`            `for (String line : lines) {`                `if (line.startsWith("data:")) {`                    `String data = line.substring("data:".length());`                    `JSONObject dataJson = JSONUtil.parseObj(data);`                    `if (dataJson.containsKey("event") && dataJson.getStr("event").equals("node_finished")) {`                        `JSONObject outputs = dataJson.getJSONObject("data").getJSONObject("outputs");`                        `if (outputs != null && outputs.containsKey("text")) {`                            `System.out.println(outputs.getStr("text"));`                        `}`                    `}`                `}`            `}``   `        `} else {`            `System.out.println("Failed to execute workflow: " + response.getStatus());`        `}`    `}``   `    `public static void main(String[] args) {`        `WorkFlowApi runner = new WorkFlowApi();`        `runner.runWorkflow("优惠券", "abc-123");`    `}``}``   

点击main方法进行调试,发现结果可以顺利的解析出来了。

这样,我们就已经把一个完整的商城助手应用建立起来,并且把它发布出来并且可以结合到任何其他系统中,为相关的系统进行“AI赋能”了。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

Spring Boot是一个流行的Java框架,用于快速构建和部署企业级应用程序,尤其是微服务架构。将Spring Boot与AI模型集成,通常是为了简化人工智能应用的开发流程,让开发者能够更轻松地处理数据预处理、模型调用、结果解析等工作。 具体步骤和可能的做法包括: 1. **模型API调用**:利用Spring Boot的RestTemplate或Feign等组件,编写RESTful接口来调用外部的AI模型API(如Hugging Face的Hub或阿里云的模型服务)。 ```java @RestController public class AIDataController { @Autowired private AIService aiService; @PostMapping("/predict") public PredictResponse predict(@RequestBody RequestData requestData) { return aiService.predict(requestData); } } ``` 2. **模型本地化**:如果AI模型较小并且允许,可以将其嵌入到Spring Boot应用中作为jar包或模型文件,使用如TensorFlow Serving这样的库来加载和运行本地模型。 3. **集成机器学习库**:例如使用Spring-ML或Weka等库,这些提供了方便的工具集来整合机器学习算法,简化训练和预测过程。 4. **模型解释和可视化**:为了更好地理解和调试模型行为,可以结合开源的模型解释工具,如LIME或SHAP,以便于用户理解模型决策背后的逻辑。 5. **持续集成/持续部署(CI/CD)**:确保AI模型和应用一起进行自动化测试和部署,Spring Boot提供了强大的工具支持。 相关问题: 1. Spring Boot如何优化AI模型的请求响应速度? 2. 如何在Spring Boot中安全地管理AI模型的访问权限? 3. 使用Spring Boot做AI项目时,如何保证模型更新不影响现有的服务稳定性?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值