基于LLM的自行车道CAD

news2024/12/23 16:21:39

LLM(大型语言模型)是强大的工具。对于许多人来说,用语言表达愿望通常比浏览复杂的 GUI 更简单。

1、系统简介和环境搭建

 urb-x.ch,这是一家专门从事自行车道建设的公司。轨道采用模块化构建块进行独特设计,可以通过多种方式进行组合。当拼凑在一起时,整个轨道网络形成了这些构建块的树形结构。

在某些方面,这个任务可以看作是一个视频游戏沙盒。可以将其视为在《过山车大亨》或《赛道狂热》中建造轨道。然而,虽然这些游戏提供了直观的设计体验,但它们无法提供土木工程项目所需的精度水平。另一方面,传统的 CAD 程序不允许大规模使用这样的模块化系统。

建立了一个无/低代码系统,让你可以轻松地创建车道,该系统构建在 Rhino 和 Grasshopper 的基础上。收获是什么?你必须投入一些时间来熟悉可用的组件。

与大多数视频游戏一样,与系统的交互可以被视为数据库系统中的事务。为此,设计了一个简单的 json/ pydantic 模式来存储轨道的配置。现在更新变成了简单的配置更新。我们将此配置称为“TrackConfig”。

{
  "version": "0.0.2",
  "library_dir": [
    "/Users/lucas/projects/gh/"
  ],
  "origin": {
    "position": [
      0.0,
      0.0,
      0.0
    ],
    "rotation": [
      0.0,
      0.0,
      0.0
    ]
  },
  "global_upgrades": {
    "PV": true,
    "HEATING": true,
    "FE3": {
      "LR": false
    }
  },
  "instance": {
    "id": "Oliver",
    "part_name": "XC50-4L",
    "children": {
      "-1": {
        "id": "Liam",
        "part_name": "XC50-4R",
        "children": {
          "-1": {
            "id": "Oliver",
            "part_name": "XC50-4R",
            "children": {
              "-1": {
                "id": "Ethan",
                "part_name": "XC50-4R",
                "children": {}
              }
            }
          }
        }
      }
    }
  },
  "configs": {},
  "selected": "Oliver"
}

作为一个项目,现在使用新的 OpenAI 函数来解析模型输出/实际上限制模型输出以匹配预期格式。

最初,目标是直接生成新的 TrackConfig。这种方法效果很好,但有一个显着的缺点:延迟非常大。不过,这还不错:大约 15 秒,这在大多数情况下仍然比使用 GUI 更快。总而言之,发现这对于迭代过程来说是不可接受的,并且希望加快速度。使用 W&B Prompts 记录所有内容,显示延迟和许多其他指标。它们工作得非常好,特别是在深入研究模型结果时!

为了应对延迟挑战,策略是减少模型所需的输出。这种方法的结果是集成了简单的更新功能。

from typing import Any, Optional, Union


from PythonModules.schema import TrackConfig, Part, PartNames


from pydantic import BaseModel, Field


class UpdatePart(BaseModel):
    """Updating or creating a part with the given id and part_name"""


    reasoning: str = Field(..., description="Answer all reasoning questions")
    id: str = Field(..., description="The unique id of a part. This is a unique random english first name.")
    part_name: PartNames = Field(..., description="The name of the part e.g. 'XS12'")
    parent: str = Field("", description="The id of the parent part or '' if the part is the root part. Usually This is the current selected part.")
    index: int = Field(-1, description="Where to insert the new part. -1 means append.")


    def __call__(self, track_config: Optional[TrackConfig] = None):
        return #code ommited




class UpdateSelection(BaseModel):
    """Select the part with the given id"""


    reasoning: str = Field(..., description="Which id's parts could be selected? Why does each part make sense or not?")
    id: str = Field(..., description="The unique id of a part. This is a unique random english first name.")


    def __call__(self, track_config: Optional[TrackConfig] = None):
        print(f"UpdateSelection(reasoning={self.reasoning}, id={id})")
        return #code ommited


# Other possible updates

虽然LLM很强大,但它们有一个一致的缺点:零样本预测可能不可靠。带有推理的输出要可靠得多。不幸的是,目前还没有任何 LangChain 链能够提供推理与 OpenAI 函数调用的组合。

公认的黑客解决方案是在函数调用中强制使用“推理”字段。前面讨论的 pydantic 模式说明了一个典型的例子。

这种策略虽然非常规,但已被证明是无价的,并且可能成为类似应用程序的关键要点。

现在,讨论延迟。如果没有推理组件,延迟会徘徊在 1.5 秒左右,这个值低得惊人。添加推理后,延迟会根据所采用的推理的深度和数量而变化。本质上,增加的运行时间与推理标记的数量成线性比例。那里相当简单。大多数情况下,延迟时间都小于 4 秒,尽管优化仍在进行中并且希望能将其降低。

借助 W&B Prompts,可以制作提示并观察其他用户如何与工具交互。这种洞察力能够分析两种提示的功效,从而进行改进,例如改进系统提示以增强预测。

让我们深入探讨提示业务。由于 GPT-3 Turbo 的上下文大小相当大,而预测令牌数量相当少,有一些空间可以使用,所以可以在提示上挥霍。

把所有认为重要的东西都扔掉了,保持干净整洁。查看下面进行的设置:

system_template = """
You are a world class assistant, helping an engineer to build an amazing street network from prefefined parts. The whole system is modular. 
You are responsible for deciding on which updates to do to the underlying configuration. The engineer will then update the configuration based on your input. 
You get access to a pointer named 'selected'. This id shows you relative to what you probably should append things to.
The whole track configuration is stored in a json file. In the instance key a tree of parts exists. The decendant of a child is the "children" field. The main child has key "-1".
The whole track consisting of a tree should make it easier to describe on where to append things.


The configuration is based on the following pydantic schema:


class PartNames(str, Enum):
    Straigt30mElement = "XS12"
    CurveRight50mRadius10mLenthgElement = "XC50-4L"
    CurveLeft50mRadius10mLenthgElement = "XC50-4R"
    DeletedElement = "Deleted"


class Origin(BaseModel):
    position: List[float] = Field(..., description="The origin position coordinates (x,y,z))")
    rotation: List[float] = Field(..., description="The origin rotation angles in degrees (x,y,z)")
    
class Part(BaseModel):
    id: str = Field(..., description="The unique id of a part. This is a unique random english first name.")
    part_name: PartNames = Field(..., description="The name of the part")
    children: Optional[Dict[str, 'Part']] = Field({}, description="Dictionary of child parts. Key=='next' is the default next part")


Part.update_forward_refs()  # This updates Element to include the recursive reference to itself


class TrackConfig(BaseModel):
    version: str = Field(..., description="The version of the track configuration")
    library_dir: List[str] = Field(..., description="List of paths to the libraries")
    origin: Origin = Field(..., description="The origin position and rotation of the track")
    global_upgrades: Dict[str, Any] = Field(..., description="Global upgrades for every element")
    instance: Part = Field(..., description="Part instances of the track")
    configs: Dict[str, Dict[str, Any]] = Field(..., description="Configuration dictionary for the track configuration")
    selected: str = Field(..., description="The id of the selected Element")


For new elements think of a new english first name as id! Think of a random name.
If not specified otherwise append or add new parts to the selected part. Never add new parts to a parent as a different child then -1, unless specified otherwise!
If a parent has other children it usually is asumed that the child with key -1 is the main child and that you should append to that one or one of its children.


Altough also visible in the schema, the following part_name's are available:
Straigt 30m Element: "XS12"
Curve Right!! 50m Radius 10m outer Length Element: "XC50-4L"
Curve Left!!  50m Radius 10m outer Length Element: "XC50-4R"


Reasons for the update fields should answer the following questions! You have to answer all of them:
- Which id do you want to update or is it a new id?
- What part_name do you want to use?
- Why this part_name?
- What parents could you use?
- If the parent already has children, why do you want to replace main child?


"""


prompt_template = """
The current configuration is as follows:
--------------------
{track_config}
--------------------
Use the given format to pick update steps from the following input:
--------------------
{input}
--------------------
Tips: Answer all questions.
Tips: Make sure to answer in the correct format!!!
"""

现在让我们看看模型调用:

class Track:
    def __init__(self, llm, system_template, prompt_template):
        self.path = "track.json"
        self.new_config = None
        prompt_msgs = [
            SystemMessage(content= system_template),
            HumanMessagePromptTemplate.from_template(prompt_template)
        ]
        prompt = ChatPromptTemplate(messages=prompt_msgs)


        self.chain = create_openai_fn_chain([UpdatePart,UpdateSelection], llm, prompt, verbose=False)


    @property
    def track_config(self):
        if not self.new_config:
            data_dict = json.load(open(self.path, "r"))
            track_config = TrackConfig(**data_dict)
            self.new_config = track_config


        return self.new_config
    
    @track_config.setter
    def track_config(self, track_config: TrackConfig):
        self.new_config = track_config
        
    def store(self):
        json.dump(self.track_config.dict(), open(self.path, "w"), indent=2)
    
    def agent(self):
        # interactively update the track_config
        # asks for user input and calls the callback function


        while prompt:=input("How should the track be updated? to quit press enter without input."):
            self(prompt)
    
    # Possibly wrap the call in retries if the to predict format is very difficult
    # @retry(wait=wait_random_exponential(min=1, max=60), stop=stop_after_attempt(6))
    def __call__(self, input) -> Any:
        json_str = json.dumps(self.track_config.dict(), indent=2)
        function:Union[UpdatePart,UpdateSelection] = self.chain.run(input = input, track_config=json_str)
        
        # call function with the track_config
        res = function(self.track_config)


        # store the new track_config
        self.store()
        
        return res


model = "gpt-3.5-turbo"
llm = ChatOpenAI(model=model,temperature=0.9)
track = Track(llm, system_template, prompt_template)

现在我们要么使用 track.agent() 方法来连续更新配置。或者使用单个命令:

track("append a new right element to the track")
track("Add a straight part to the last added track")
...

2、如何使用 W&B 提示

此处使用 W&B Prompts 主要是为了记录并查看其他人如何使用我的工具。这是一次了解人们在建造轨道时所做出的不同假设的旅程,并了解模型提出的古怪假设。您可以在函数调用的“原因”字段中发现这些模型假设。

只需设置一个环境变量,然后就可以开始了。

# we need a single line of code to start tracing LangChain with W&B
os.environ["LANGCHAIN_WANDB_TRACING"] = "true"

现在,锁链只是一场单步舞。如果能把它分成几个阶段,特别是分离出推理,那就很巧妙了。但是,这是一项正在进行的工作。

以下是 CAD 中车道的形状:

注意:我们只是在这里展示车道。为了清晰起见,所有额外的东西,如房屋、街道和桥梁,都没有显示在图中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1666042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI工具的热门与卓越:揭示AI技术的实际应用和影响

文章目录 每日一句正能量前言常用AI工具创新AI应用个人体验分享后记 每日一句正能量 我们在我们的劳动过程中学习思考,劳动的结果,我们认识了世界的奥妙,于是我们就真正来改变生活了。 前言 随着人工智能(AI)技术的快…

prometheus、mysqld_exporter、node_export、Grafana安装配置

工具简介 Prometheus(普罗米修斯):是一个开源的服务监控系统和时间序列数据库 mysqld_exporter: 用于监控 mysql 服务器的开源工具,它是由 Prometheus 社区维护的一个官方 Exporter。该工具通过连接到mysql 服务器并执…

每日一题9:Pandas-填充缺失值

一、每日一题 DataFrame products --------------------- | Column Name | Type | --------------------- | name | object | | quantity | int | | price | int | ---------------------编写一个解决方案,在 quantity 列中将缺失的值 编…

flutter开发实战-人脸识别相机使用

flutter开发实战-人脸识别相机使用 当需要拍摄的时候,需要检测到人脸再进行后续的操作,这里使用的是face_camera 一、引入face_camera 在工程的pubspec.yaml中引入插件 # 检测人脸face_camera: ^0.0.8iOS端需要设置相关权限 在info.plist文件中&…

编程代码的舞者--Python循环语句

循环语句是编程中不可或缺的要素之一,它们能够让程序反复执行特定的任务,提高代码的重复利用性和效率。在本篇博客中,我们将深入探讨Python中常用的循环语句,包括for循环和while循环,以及控制循环流程的关键字break和c…

【Win10设备管理器中无端口选项】

计算机疑难杂症分享002 Win10设备管理器中无端口选项1、问题现象2、问题原因3、问题解决3.1、驱动精灵(亲测的此方法)3.2、添加过时硬件3.3、官方的方法 Win10设备管理器中无端口选项 1、问题现象 当我调试串口通信时,发现打开设备管理器没有端口,打开…

系统需求开发和管理指南(软件标准文件Word)

1.需求获取的方式 2.需求分析的准则 3.需求分析的方法 4.需求开发考虑的方面 5.需求确认的方法 6.需求优先级的设定 7.需求文档编制规范要求 软件全文档获取方式一:本文末个人名片直接获取。 软件全文档获取二:软件项目开发全套文档下载_软件项目文档-C…

Unity开发中导弹路径散射的原理与实现

Unity开发中导弹路径散射的原理与实现 前言逻辑原理代码实现导弹自身脚本外部控制脚本 应用效果结语 前言 前面我们学习了导弹的追踪的效果,但是在动画或游戏中,我们经常可以看到导弹发射后的弹道是不规则的,扭扭曲曲的飞行,然后击…

Leetcode39.组合总和

文章目录 题目描述解题思路重复子集剪枝 代码 题目 参考题解 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返…

Python | Leetcode Python题解之第78题子集

题目: 题解: class Solution:def subsets(self, nums: List[int]) -> List[List[int]]:self.res []self.backtrack([], 0, nums)return self.resdef backtrack(self, sol, index, nums):self.res.append(sol)for i in range(index, len(nums)):self…

leetcode-矩阵最长递增路径-102

题目要求 思路 1.通过双循环去把每一个结点作为起始点进行统计,将返回的路径长度存放在res中,取最大的res的长度。 2.递归中需要的几个值,x和y当前结点的坐标,pre用于存储上一个结点的元素值,因为要求是路径上的元素是…

Redis简单使用

认识Redis redis:字典型数据库,存储的是键值对,是NoSql数据库 关系型数据库和NoSql之间的区别: 结构化:NoSql非结构化数据库,松散结构(键值对key-value(可以任意类型)&…

科技查新中化工领域查新点如何确立与提炼?案例讲解!

我国化工科技查新工作始于1985年,至今经历了30多年的发展。化工类课题包含化工、炼油、 冶金、能源、轻工、石化、环境、医药、环保和军工等, 具有物质种类繁多、制备工艺复杂等特点。因此,本文结合化工查新项目实例,总结提高化工…

scrapy的入门

今天我们先学习一下scrapy的入门,Scrapy是一个快速的高层次的网页爬取和网页抓取框架,用于爬取网站并从页面中提取结构化的数据。 1. scrapy的概念和流程 1.1 scrapy的概念 我们先来了解一下scrapy的概念,什么是scrapy: Scrapy是一个Python编写的开源网络爬虫框架…

【userfaultfd+条件竞争劫持modprobe_path】TSGCTF 2021 -- lkgit

前言 入门题,单纯就是完成每日一道 kernel pwn 的 kpi 😀 题目分析 内核版本:v5.10.25,可以使用 userfaultfd,不存在 cg 隔离开启了 smap/smep/kaslr/kpti 保护开启了 SLAB_HADNERN/RANDOM 保护 题目给了源码&…

HarmonyOS NEXT星河版之模拟图片选择器(下)---使用Swiper实现图片滑动预览

文章目录 一、目标二、开撸2.1 改造图片预览Dialog2.2 改造主页面2.3 主页面完整代码 三、小结 一、目标 在前面的介绍中,查看选中的图片都是单张预览,接下来要改造成多张可滑动预览,如下: 二、开撸 2.1 改造图片预览Dialog …

【c++】set、map用法详解

set、map用法详解 1. 关联式容器2. 键值对2.1 :pair2.2:make_pair 3. 树形结构的关联式容器3.1:set构造函数find()erase()insert()count()lower_bound()upper_bound() 3.2:multiset3.3:map构造函数insert()operator[] …

如何在bud里弄3d模型?---模大狮模型网

随着数字化设计的不断发展,越来越多的设计软件提供了对3D模型的支持,为设计师们带来了更广阔的创作空间。Bud作为一款功能强大的设计工具,也提供了添加和编辑3D模型的功能,让用户能够更加灵活地进行设计创作。本文将为您详细介绍如…

最新网页版USB转串口芯片CH340中文规格书手册(20240511)

前言 南京沁恒的产品已经很成熟了,完全可替代国外USB转串口产品,不必迷信FT232,CP2102之类了。 另外,急着买芯片,直接跑过去的,看过几次妹子了:) CH340手册,基于网页3.3版本,规格书…

ARM单片机实现流水灯(GD32)

根据上图可知使用的引脚分别是PA8,PE6,PF6流水灯功能的实现要分别初始化这几个引脚 流水灯实现 编写流水灯代码 LED.C #include "gd32f30x.h" // Device header #include "Delay.h" // 初始化LED灯 void LED_Init(void){// 使能RCU时钟…