35-dify案例分享-手把手教你打造 Markdown 转 Word 自定义智能体

1.前言

​ 很多小伙伴之前和我提过想实现dify聊天历史记录一键保存文档word等文档。我们知道目前很多大语言模型是天然支持markdown文档的。也就是聊天对话的内容是可以让打语言模型输出markdown语法格式的文件内容的。那么我们在聊天对话中让他调用生成word一个插件是不是就能够实现word保存功能呢?

​ OK 我们基于整个思路在dify市场上找到了一款markdown转word插件,接下来我们用他们来实现这个功能。

2.markdown转word插件

dify 在1.0+的版本增强了插件市场功能,有更多丰富的插件来实现功能的扩展。我们在marketplace 搜到 doc

image-20250325160119954

点击这个插件就可以完成插件的安装了。

image-20250325160228706

插件安装

我创建一个AI 智能体

image-20250325160332580

image-20250325160430503

​ 按照上面1、2、3步骤完成智能体的创建。

​ 我们在左下角工具添加-doc插件

image-20250325160546265

image-20250325160643103

模型这里我们选择火山引擎的deekseek-v3模型,这里要注意不是所有的模型都支持function call,需要模型具有function call的功能,而且最好选择大一点尺寸模型,太小模型不聪明调动 AI Agent是出问题。

插件使用

我在聊天对话窗口中输入如下内容:

请帮我写一个儿童故事绘本关于白雪公主和七个小矮人的故事,内容markdownn格式显示,最后调用doc markdownn转word工具生成word

image-20250325161011166

智能体会更加我们要求生成markdownn格式的内容,并调用智能体工具doc 生成word文档

image-20250325161129798

不错,已经按照我要求生成word文档了,我们点击文档下载。

image-20250325161219654

报错了, 这里不知道哪里出了问题。文档是生成了,但是就是不能提供下载。

我们在容器挂载文件中找一下是否生成文档了。

在文件目录

E:\tmp\dify-1.1.2\docker\volumes\app\storage\tools\2c121f2b-08dd-463a-bfc1-1216481c7311

目录下找到刚才生成好的文档

image-20250325161412488

我们打开这个文档,看一下内容是否是刚才生成的内容。

image-20250325161446347

OK 也是没有问题的。不过文档下载不了。不知道哪个地方有问题。感觉这样能看不能用啊。

接下来我不死心,不行我增加用代码实现一个这样的插件功能呢?好吧带着这个想法我们就开始开干了。

3.自己开发doc插件

我们通过上面插件了解,这里我们可以分2步走。第一步我们先使用工作流制作一个带有markdown转word的工作流。第二步在使用ai agent配置这个自定义发布的工作流。

markdown转word的工作流制作

我们点击创建应用,这里我们选择workflow

image-20250325162058938

按照上面1、2、3、4步骤完成工作流创建。

这个工作流我们有3个部分组成,开始节点、http请求、结束

image-20250325162214651

开始

开始节点比较简单就是使用markdwon文档内容的,我们这里使用段落作为文本输入

image-20250325162356590

HTTP 请求

这个地方我们需要调用一个后端服务来处理markdown转word代码。我先看一下http请求设置

请求方式post 地址 http://172.35.5.63:8089/office/word/convert 这个是我们服务端接口地址(这里是我本机电脑地址)

body部分就是开始节点传入的llm_str内容(可以理解就是markdown格式内容)

image-20250325163125547

服务端代码实现

md_to_docx_server.py

from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import FileResponse
from spire.doc import Document, FileFormat
import os
import time
import logging
from pydantic import BaseModel

app = FastAPI(title="Markdown to Word Converter")

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class MarkdownContent(BaseModel):
    content: str

# 获取当前程序运行目录并创建必要的目录
current_dir = os.path.dirname(os.path.abspath(__file__))
temp_dir = os.path.join(current_dir, 'temp')
output_dir = os.path.join(current_dir, 'output')
os.makedirs(temp_dir, exist_ok=True)
os.makedirs(output_dir, exist_ok=True)

@app.post("/office/word/convert")
async def convert_md_to_docx(request: Request):
    logger.info('Received request for /convert')
    content = await request.body()
    if not content:
        logger.error('No content part in the request')
        return JSONResponse(content={"error": "No content part"}, status_code=400)

    content = content.decode('utf-8')
    if content == '':
        logger.error('No content provided')
        return JSONResponse(content={"error": "No content provided"}, status_code=400)
    
    # 从请求的内容中读取
    mdfile_name = str(int(time.time())) + ".md"
    md_file_path = os.path.join(temp_dir, mdfile_name)
    with open(md_file_path, 'w', encoding='utf-8') as f:
        f.write(content)

    # 创建文档实例
    doc = Document()

    # 从上传的文件加载Markdown内容
    doc.LoadFromFile(md_file_path, FileFormat.Markdown)
    
    # 将Markdown文件转换为Word文档并保存
    file_name = str(int(time.time())) + ".docx"
    output_path = os.path.join(output_dir, file_name)
    doc.SaveToFile(output_path, FileFormat.Docx)

    # 释放资源
    doc.Dispose()
    
    # 清理临时文件
    if os.path.exists(md_file_path):
        os.remove(md_file_path)

    # 返回文件的下载链接
    base_url = str(request.base_url)
    download_url = base_url + 'office/word/download/' + os.path.basename(output_path)
    print(download_url)
    return {"download_url": download_url}

@app.get("/office/word/download/{filename}")
async def download_file(filename: str):
    file_path = os.path.join(output_dir, filename)
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="File not found")
    return FileResponse(file_path, filename=filename)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8089)

结束

这个地方也比较简单就是http请求body输出的部分

image-20250325163326743

写好这个接口后我们可以先用客户端测试代码或者postman验证测试一下.(客户端测试代码我们会上传github 文章末尾可以获取地址)

服务端启动后,我们使用postman调用 能够返回url

image-20250325163634070

并且这个URL 可以打开连接地址下载,说明我们服务端接口代码是可以对外提供服务的。

当然在服务端代码downloads文件夹也能找到生成的docx文件。这里我们就不做详细展开。

image-20250325163805696

markdown转word的工作流发布

上述测试完成OK 了,我们可以把这个工作流发布成工具。

image-20250325163949393

发布完成后我们在工具-工作流就能找到这个自定义的工作流

image-20250325164112177

以上我们就完成了工作流发布成工具的操作了。

4.markdown转word自定义智能体

自定义智能体制作

回到工作流工作台我们创建一下ai 智能体,这个步骤和前面的创建一个AI 智能体一样

image-20250325164403833

我们在编排里面填写系统提示词

## 角色
你是一个文档专家,专门帮助用户编写和生成各类Word格式的文档。
## 任务
1.你根据用户的要求尽可能的编写文档,最后输出以Markdown作为最终内容的输出。
2.调用 Word_Http_Post 工具,将最终输出的Markdown内容传入到 llm_r 参数。
3.最后直接向用户输出你从 Word_Http_Post 工具获取到的下载链接。
## 技能
生成word文档并获取下载链接工具:Word_Http_Post。

上面就是利用提示词告诉AI 需要调用我们自定义的这个工具相关要求。

在工具一栏我们添加我们刚才的自定义的工作流

image-20250325164555394

image-20250325164700937

接下来和前面一样我们选择一个带有function call 火山引擎的deekseek-v3模型。

image-20250325164807407

智能体测试及验证

我们输入一下提示词。

请帮我写一个儿童故事绘本小马过河的故事,内容markdown格式显示,最后调用文生Word_Http_Post工具生成word

image-20250325165109375

image-20250325171726792

​ 我们点击这个链接下载

image-20250325172058734

image-20250325172316883

打开后确实生成的我们要的“小马过河的故事” word.

以上我们就完成了自定义AI agent使用markdown生成word的智能体了。

项目体验地址http://dify.duckcloud.fun/chat/G1ZnSzixkmwP1c0B

image-20250325221934288

5.感谢

非常感谢jenal 提供的关于markdown转word代码和工作流,基于以上内容我才有思路写这个工作流的文章。

相关资料和文档可以看我开源的项目 https://github.com/wwwzhouhui/dify-for-dsl

6.总结

今天,我主要带大家探索了如何实现 Dify 聊天历史记录一键保存为 Word 文档的功能。我们尝试使用 dify 市场上的 markdown 转 word 插件来完成这一任务。通过在 dify 中创建 AI 智能体,并添加相应插件,让智能体根据要求生成 markdown 格式内容并调用插件生成 Word 文档。然而,虽然文档成功生成,但在下载环节出现了问题,虽能在容器挂载文件中找到生成的文档,但无法直接下载使用。

后面我们自己开发 doc 插件。解决了上面下载的问题,本次文章我们也实现了AI agent和工作流整合的一个案例,帮助大家更好的学习dify工作流以及发布工作流功能。今天的分享就到这里。感兴趣的小伙伴可以参考文章内容,自己动手尝试实现 Dify 聊天记录保存为 Word 文档的功能。期待我们在下一篇文章中再见!

### 实现 Dify 长文本生成并导出为 Word 文件的操作方法 为了实现通过 Dify 进行长文本生成并将结果导出为 Word 文件,可以按照以下方式操作: #### 1. **配置 Dify 平台** 在 Dify 中创建一个 AI 智能体,并为其设置合适的 Prompt 和参数以便于生成所需的长文本内容。可以通过市场中的插件或者自定义脚本扩展其功能[^4]。 #### 2. **集成 Markdown Word 功能** 由于 Dify 支持市场上可用的插件,可以选择安装 `Markdown to Word` 类型的插件来处理生成的内容换工作。如果该插件未能满足需求,则可考虑外部 Python 工具辅助完成此过程[^1]。 #### 3. **利用 Python 处理文档生成** 当内部插件无法解决下载问题时,推荐使用 Python 的第三方库如 `python-docx` 来手动编写逻辑以生成目标格式文件。下面给出一段基于 python-docx 的代码示例用于演示如何将字符串形式的数据写入到一个新的 `.docx` 文件当中去[^2]: ```python from docx import Document def save_text_to_word(text_content, file_name="output"): """ 将给定的文字内容保存成指定名称的Word文档 参数: text_content (str): 待存储至Word内的纯文字串 file_name (str): 输出文件的基础名,默认值为 'output' 返回值: str: 成功路径或错误消息 """ try: document = Document() paragraphs = text_content.split("\n") # 对输入按换行符分割形成列表 for para in paragraphs: if not para.strip(): continue # 如果为空白则跳过当前循环迭代项 heading_level = None # 初始化变量表示未知级别的标题等级 first_char = para[:1] if first_char.isdigit(): level_index = int(first_char)-1 while True: next_two_chars = para[level_index+1 : level_index+3].strip() if next_two_chars.startswith('.'): break elif not next_two_chars or len(next_two_chars)<2 : raise ValueError(f"Invalid Heading Format at Line:{para}") else: level_index +=1 actual_heading_part=para[level_index+len(str(level_index))+1:].lstrip() document.add_heading(actual_heading_part,int(level_index)) else: document.add_paragraph(para) output_path=f"{file_name}.docx" document.save(output_path) return f"File saved successfully! Path={output_path}" except Exception as e: return f"Error occurred during saving process - {e}" # Example Usage sample_long_text="""1. Introduction This is an introduction paragraph. 2. Main Content Here we discuss the main points. """ result_message=save_text_to_word(sample_long_text,"example_document") print(result_message) ``` 上述函数接受两个参数:一个是待存的长文本字符串;另一个是希望得到的结果文件的名字前缀(默认名为 "output")。它会先依据换行符拆分原始数据流成为多个段落单元格,再逐一判断每部分是否适合作为主标题、子标题还是普通正文对待,最后将其逐条加入新建好的空白 DOCX 容器里头直至全部加载完毕为止。 #### 4. **上传与共享最终产物** 一旦完成了本地端上的所有编辑动作之后,就可以借助 FTP/SFTP 协议或者其他云盘服务手段分享出去供他人查阅啦! --- ### 注意事项 - 确保环境中已正确安装所需依赖包 (`pip install python-docx`)。 - 若涉及大量图片嵌套等情况需额外引入 Pillow 或其他图像处理类库支持[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值