当前位置: 首页 > news >正文

从零开始的Agent学习(二)-增加文档输出功能

背景

        继上次完成一个简单的聊天机器人之后,小H就在想该如何增加功能或者是环节,看到平常常用的cursor和kiro,能够修改代码的功能真的好厉害吧,不过一时间应该还没法完成这么高难度的东西,但是修改代码本质来看就是编辑文件嘛,所以打算试着从将LLM返回的结果输出到一个文件中来下手。

整体架构

        增加一个Doc类,用来完成工具类的具体实现;

        给出方法函数,利用Langchain工具包装

        修改提示词,提示大模型可以进行调用改工具

        同时对上次的项目结构进行修正,将工具类放到同一个地方去。

project
├── tools         # 工具类
│   ├── __init__.py     # 模块初始化
│   ├── document_exporter.py        # 文档输出工具类
│   └── MessageManager.py # 上下文整理类
├── .venv   # 虚拟环境
└── langgraph_chat.py      # 主要运行类

DocumentExporter

依赖

import os
import re
from datetime import datetime
from typing import Optional, Dict, Any
from langchain.tools import Tool

初始化

        对于工具类,我们希望他初始化的时候只要设定自己的输出路径就可以了,然后后面我们用函数再增加传入的内容。

def __init__(self, output_dir: str = "exports"):self.output_dir = output_dirself._ensure_output_dir()  # 确保目录存在
def _ensure_output_dir(self):"""确保输出目录存在"""if not os.path.exists(self.output_dir):os.makedirs(self.output_dir)

MD内容搭建

        这里提供了一份MD输出的格式输出,实际上只要稍微改动一些根据其他文件的输出方式就可以输出成其他文件,只依赖文件路径输入其实不会有影响的,只要修改本次内容中对应的文件名修饰的部分就可以了。

def _build_markdown_content(self, content: str, title: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> str:"""构建 Markdown 内容"""lines = []# 标题if title:lines.append(f"# {title}")lines.append("")# 元数据if metadata:lines.append("## 文档信息")lines.append("")for key, value in metadata.items():lines.append(f"- **{key}**: {value}")lines.append("")# 生成信息lines.append("## 生成信息")lines.append("")lines.append(f"- **生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")lines.append(f"- **生成工具**: LangGraph 聊天机器人")lines.append("")# 主要内容lines.append("## 内容")lines.append("")lines.append(content)return "\n".join(lines)

        主要就是依据固定格式进行添加内容,配合下面的导出方法,如果有没看到的辅助方法,文章结尾全部代码里面可以找到的。

   def export_to_markdown(self, content: str, title: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> str:"""导出内容到 Markdown 文件Args:content: 要导出的内容title: 文档标题(可选)metadata: 元数据信息(可选)Returns:str: 生成的文件路径"""filename = self._generate_filename(title)filepath = os.path.join(self.output_dir, filename)# 构建 Markdown 内容md_content = self._build_markdown_content(content, title, metadata)# 写入文件try:with open(filepath, 'w', encoding='utf-8') as f:f.write(md_content)return f"✅ 文档已成功导出到: {filepath}"except Exception as e:return f"❌ 文档导出失败: {str(e)}"

        为了能够让LLM使用,我们需要提供一个函数接口,这里使用的是LangChain的Tool来做工具集成,Tool是LangChain框架提供的一个类,用于封装可执行的工具函数。那么里面应该包括一个实例化的对象,同时还要有对应的方法去调用我们刚才说到的导出文档的方法。

        Tool中含有三个核心参数,name代表的是工具的唯一标识符、AI 在决定使用哪个工具时会看到这个名称;description就是描述这个工具的作用、输入输出等内容,更有利于大模型判断是否使用;func参数,就是实际调用的参数。

def create_document_export_tool() -> Tool:"""创建文档导出工具"""exporter = DocumentExporter()def export_document(input_str: str) -> str:"""导出文档工具函数输入格式: "标题|内容" 或者直接是内容"""try:# 解析输入if "|" in input_str:parts = input_str.split("|", 1)title = parts[0].strip()content = parts[1].strip()else:title = Nonecontent = input_str.strip()# 添加一些元数据metadata = {"内容长度": f"{len(content)} 字符","内容类型": "AI 生成内容"}return exporter.export_to_markdown(content, title, metadata)except Exception as e:return f"❌ 文档导出工具执行失败: {str(e)}"return Tool(name="export_document",description="""将内容导出为 Markdown 文档。使用场景:当用户要求将信息保存到文档、整理到文件、导出报告等时使用。输入格式:1. 只有内容:"这是要导出的内容"2. 标题和内容:"文档标题|这是要导出的内容"示例:- "明天天气预报|明天北京天气晴朗,温度15-25度"- "市场调研报告|根据搜索结果,当前市场趋势..."""",func=export_document)

        实际使用的话,我们只要在这里的tools加上这个create···tool返回的结果, 然后在一开始的提示词中添加对应的工具内容,后面就可以交给大模型自主判断了。

结果

代码

"""
文档导出工具
用于将对话内容和搜索结果导出为 Markdown 格式文档
"""import os
import re
from datetime import datetime
from typing import Optional, Dict, Any
from langchain.tools import Toolclass DocumentExporter:"""文档导出器类"""def __init__(self, output_dir: str = "exports"):"""初始化文档导出器Args:output_dir: 输出目录,默认为 'exports'"""self.output_dir = output_dirself._ensure_output_dir()def _ensure_output_dir(self):"""确保输出目录存在"""if not os.path.exists(self.output_dir):os.makedirs(self.output_dir)def _sanitize_filename(self, filename: str) -> str:"""清理文件名,移除不合法字符"""# 移除或替换不合法字符filename = re.sub(r'[<>:"/\\|?*]', '_', filename)# 限制长度if len(filename) > 100:filename = filename[:100]return filenamedef _generate_filename(self, title: Optional[str] = None) -> str:"""生成文件名"""timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")if title:clean_title = self._sanitize_filename(title)return f"{timestamp}_{clean_title}.md"else:return f"document_{timestamp}.md"def export_to_markdown(self, content: str, title: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> str:"""导出内容到 Markdown 文件Args:content: 要导出的内容title: 文档标题(可选)metadata: 元数据信息(可选)Returns:str: 生成的文件路径"""filename = self._generate_filename(title)filepath = os.path.join(self.output_dir, filename)# 构建 Markdown 内容md_content = self._build_markdown_content(content, title, metadata)# 写入文件try:with open(filepath, 'w', encoding='utf-8') as f:f.write(md_content)return f"✅ 文档已成功导出到: {filepath}"except Exception as e:return f"❌ 文档导出失败: {str(e)}"def _build_markdown_content(self, content: str, title: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> str:"""构建 Markdown 内容"""lines = []# 添加标题if title:lines.append(f"# {title}")lines.append("")# 添加元数据if metadata:lines.append("## 文档信息")lines.append("")for key, value in metadata.items():lines.append(f"- **{key}**: {value}")lines.append("")# 添加生成时间lines.append("## 生成信息")lines.append("")lines.append(f"- **生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")lines.append(f"- **生成工具**: LangGraph 聊天机器人")lines.append("")# 添加主要内容lines.append("## 内容")lines.append("")lines.append(content)return "\n".join(lines)def create_document_export_tool() -> Tool:"""创建文档导出工具"""exporter = DocumentExporter()def export_document(input_str: str) -> str:"""导出文档工具函数输入格式: "标题|内容" 或者直接是内容"""try:# 解析输入if "|" in input_str:parts = input_str.split("|", 1)title = parts[0].strip()content = parts[1].strip()else:title = Nonecontent = input_str.strip()# 添加一些元数据metadata = {"内容长度": f"{len(content)} 字符","内容类型": "AI 生成内容"}return exporter.export_to_markdown(content, title, metadata)except Exception as e:return f"❌ 文档导出工具执行失败: {str(e)}"return Tool(name="export_document",description="""将内容导出为 Markdown 文档。使用场景:当用户要求将信息保存到文档、整理到文件、导出报告等时使用。输入格式:1. 只有内容:"这是要导出的内容"2. 标题和内容:"文档标题|这是要导出的内容"示例:- "明天天气预报|明天北京天气晴朗,温度15-25度"- "市场调研报告|根据搜索结果,当前市场趋势..."""",func=export_document)# 为了方便直接使用
def export_to_markdown(content: str, title: Optional[str] = None) -> str:"""便捷函数:直接导出内容到 Markdown"""exporter = DocumentExporter()return exporter.export_to_markdown(content, title)if __name__ == "__main__":# 测试代码print("测试文档导出工具...")# 创建工具tool = create_document_export_tool()# 测试1: 只有内容result1 = tool.func("这是一个测试文档的内容,包含了一些重要信息。")print(f"测试1结果: {result1}")# 测试2: 标题和内容result2 = tool.func("天气预报|明天北京天气晴朗,气温15-25摄氏度,适合外出活动。")print(f"测试2结果: {result2}")print("测试完成!")

结语

        小H的agent已经可以输出文件了,那么查看文件等功能也应该跟上了,或者还有什么东西可以加上呢?

http://www.xdnf.cn/news/1340119.html

相关文章:

  • 36、供应链计划与执行优化 (军方后勤) - /供应链管理组件/military-logistics-scm
  • 34、扩展仓储管理系统 (跨境汽车零部件模拟) - /物流与仓储组件/extended-warehouse-management
  • 3D 环形旋转图片轮播(纯html,css,js)
  • 力扣hot100:无重复字符的最长子串,找到字符串中所有字母异位词(滑动窗口算法讲解)(3,438)
  • 从零开始理解 K 均值聚类:原理、实现与应用
  • 自学嵌入式第二十四天:数据结构(4)-栈
  • linux-ubuntu里docker的容器portainer容器建立后如何打开?
  • WSL的Ubuntu如何改名字
  • Ubuntu网络图标消失/以太网卡显示“未托管“
  • java项目:如何优化JVM参数?
  • nginx-自制证书实现
  • 读《精益数据分析》:精益画布——创业与产品创新的高效工具
  • 【工具】前端JS/VUE修改图片分辨率
  • 使用Docker部署Coze Studio开源版
  • Advanced Math Math Analysis |02 Limits
  • Oracle CLOB类型转换
  • k8s下的网络通信与认证
  • 【C++】模板(进阶)
  • 从YOLOv5到RKNN:零冲突转换YOLOv5模型至RK3588 NPU全指南
  • 在线课程|基于SprinBoot+vue的在线课程管理系统(源码+数据库+文档)
  • openEuler系统中如何将docker安装在指定目录
  • ES_文档
  • 【数据结构】树与二叉树:结构、性质与存储
  • 牛客:链表的回文结构详解
  • 牛客:链表分割算法详解
  • LeetCode100 -- Day3
  • C++---滑动窗口平滑数据
  • 深度学习之NLP基础
  • KB5063878补丁故障解决方案:从蓝屏幕到系统修复的全面指南
  • 短波红外科研相机:开启科研新视野的利器​