利用Anthropic的Claude 3.5 Sonnet生成报告:两种方法的比较
大家好!我是Raphael,巴西房地产公司Pilar的联合创始人兼CTO。Pilar为房地产经纪人和经纪公司提供软件和服务,采用低成功费模式。我们不收取高昂的前期费用,而是从每次成功的交易中收取少量佣金,使我们的成功直接与客户的成功挂钩。我们由20名技术人员组成的团队不断创新,最新产品是Pilar Homes,一个全新的房地产门户网站,旨在为购房者和房产经纪人提供最佳体验。
在这篇文章中,我将分享我们使用人工智能生成报告的经验,特别是Anthropic的Claude 3.5 Sonnet,并比较两种不同的方法。
我们处理任务的理念将在未来的文章中详细介绍(敬请关注!),但简而言之,这些任务最终以Jira工单的形式出现在“技术服务台”看板上。生成报告就是这样一项任务,大多数任务需要工程师花费大约30分钟来解决,复杂报告很少超过几个小时。但情况正在发生变化。我们最初只与一两个合作伙伴合作的精品品牌正在扩张,成为更大的经纪公司,我们也与业内老牌公司签订了更多合同。虽然增加工程师的工作时间可以解决日益增长的报告需求,但我看到了探索人工智能代理并在现实环境中学习架构模式的机会。
在我们的初始方法中,我们将工具暴露给Claude的3.5 Sonnet模型,使其能够执行数据库查询、将检索到的文档转换为CSV并将其结果写入.csv文件。
以下是我们的结构,很大程度上受到了上面博客文章的启发:
<code># 每个collection对象描述一个MongoDB集合及其字段 # 这有助于Claude理解我们的数据模式 COLLECTIONS = [ { 'name': 'companies', 'description': 'Companies are the real estate brokerages. If the user provides a code to filter the data, it will be a company code. The _id may be retrieved by querying the company with the given code. Company codes are not used to join data.', 'fields': { '_id': 'The ObjectId is the MongoDB id that uniquely identifies a company document. Its JSON representation is \"{"$oid": "the id"}\"', 'code': 'The company code is a short and human friendly string that uniquely identifies the company. Never use it for joining data.', 'name': 'A string representing the company name', } }, # 此处之后描述了更多集合,但思路相同... ] # 这是client.messages.create的“system”参数 ROLE_PROMPT = "You are an engineer responsible for generating reports in CSV based on a user's description of the report content" # 这是“user”消息 task_prompt = f"{report_description}.\nAvailable collections: {COLLECTIONS}\nCompany codes: {company_codes}\n.Always demand a company code from the user to filter the data -- the user may use the terms imobiliária, marca, brand or company to reference a company. If the user wants a field that does not exist in a collection, don't add it to the report and don't ask the user for the field." </code>
report_description只是一个通过argparse读取的命令行参数,company_codes是从数据库中检索到的,并将其暴露给模型,以便它知道哪些公司存在以及用户输入中什么是公司代码。示例:(MO - Mosaic Homes,NV - Nova Real Estate,等等)。
模型可用的工具包括:find和docs2csv。
<code>def find(collection: str, query: str, fields: list[str]) -> Cursor: """Find documents in a collection filtering by "query" and retrieving fields via projection""" return db.get_collection(collection).find(query, projection={field: 1 for field in fields}) def docs2csv(documents: list[dict]) -> list[str]: """ Convert a dictionary to a CSV string. """ print(f"Converting {len(documents)} documents to CSV") with open('report.csv', mode='w', encoding='utf-8') as file: writer = csv.DictWriter(file, fieldnames=documents[0].keys()) writer.writeheader() writer.writerows(documents) return "report.csv"</code>
Claude能够调用find函数对我们的数据库执行结构良好的查询和投影,并使用docs2csv工具生成小型CSV报告(少于500行)。但是,较大的报告会触发max_tokens错误。
在分析了我们的令牌使用模式后,我们意识到大部分令牌消耗都来自通过模型处理单个记录。这促使我们探索另一种方法:让Claude生成处理代码,而不是直接处理数据。
虽然解决max_tokens限制在技术上并不困难,但它需要我们重新思考解决问题的方法。
解决方案?让Claude生成将在我们的CPU上运行的Python代码,而不是通过AI处理每个文档。
我必须修改角色和任务提示并删除工具。
以下是报告生成代码的要点。
生成报告的命令是:
<code># 每个collection对象描述一个MongoDB集合及其字段 # 这有助于Claude理解我们的数据模式 COLLECTIONS = [ { 'name': 'companies', 'description': 'Companies are the real estate brokerages. If the user provides a code to filter the data, it will be a company code. The _id may be retrieved by querying the company with the given code. Company codes are not used to join data.', 'fields': { '_id': 'The ObjectId is the MongoDB id that uniquely identifies a company document. Its JSON representation is \"{"$oid": "the id"}\"', 'code': 'The company code is a short and human friendly string that uniquely identifies the company. Never use it for joining data.', 'name': 'A string representing the company name', } }, # 此处之后描述了更多集合,但思路相同... ] # 这是client.messages.create的“system”参数 ROLE_PROMPT = "You are an engineer responsible for generating reports in CSV based on a user's description of the report content" # 这是“user”消息 task_prompt = f"{report_description}.\nAvailable collections: {COLLECTIONS}\nCompany codes: {company_codes}\n.Always demand a company code from the user to filter the data -- the user may use the terms imobiliária, marca, brand or company to reference a company. If the user wants a field that does not exist in a collection, don't add it to the report and don't ask the user for the field." </code>
Claude生成的Python内容(运行良好):
<code>def find(collection: str, query: str, fields: list[str]) -> Cursor: """Find documents in a collection filtering by "query" and retrieving fields via projection""" return db.get_collection(collection).find(query, projection={field: 1 for field in fields}) def docs2csv(documents: list[dict]) -> list[str]: """ Convert a dictionary to a CSV string. """ print(f"Converting {len(documents)} documents to CSV") with open('report.csv', mode='w', encoding='utf-8') as file: writer = csv.DictWriter(file, fieldnames=documents[0].keys()) writer.writeheader() writer.writerows(documents) return "report.csv"</code>
我们与Claude 3.5 Sonnet的历程表明,人工智能可以显着提高运营效率,但成功的关键在于选择正确的架构。代码生成方法被证明比直接的AI处理更强大,同时保持了自动化的优势。
除了正确构建报告外,代码生成方法还允许工程师审查AI的工作,这是一件非常好的事情。
为了完全自动化流程,消除人工参与并处理更大数量的报告,跨多个代理实例分配工作——每个实例处理更少的令牌——将是该系统的自然演变。对于此类分布式AI系统中的架构挑战,我强烈推荐Phil Calçado关于构建AI产品的最新文章。
此实现的主要经验教训:
以上是使用 Anthropic 的 Claude Sonnet 生成报告的详细内容。更多信息请关注PHP中文网其他相关文章!