比Cursor更强的Augment是如何给大模型提供上下文的?

推荐一下Augment,是Cursor的竞品 里提到了Augment Code。之前看过几眼,主要印象是他们的上下文索引比较新奇,有没人能看出来是怎么做的?文档说他们有一套索引方式,很大的项目上传到他们的私有云索引后就能给LLM精准地提供上下文。但文档看起来不想介绍具体闭源的实现方式

最初试用Cursor的时候他们上下文是基于RAG的,不太了解现在还是不是。他们先把整个项目里的所有文件切割并索引进向量数据库。取决于用户问题,他们的向量模型会找出数据库里语义上相关度最高的代码片段,然后把这些片段作为上下文提供给LLM。这样造成了一些问题,比如向量模型有时候找出的代码片段相关度不够高,LLM并不知道整个项目是什么样的,代码片段也包含了很多无用信息。

Aider是通过treesitter parser解析所有文件并去除无用信息,比如只保留函数定义去除实现,然后生成repository map。用户问问题的时候可以 /add 需要修改的文件。repository map和用户自己添加的文件可以比较好地让LLM理解项目和需求。

Claude Code似乎是大力出奇迹,每次都是LLM知道目录结构,指出它想看哪个文件,然后客户端把文件发送过去,循环直到LLM觉得足够了可以开始写代码了。没有仔细研究过,不知道是不是这样。

效果上感觉Augment最好,就是想不明白他们怎么做的

60 Likes

楼主都试过呀 :+1:

5 Likes

思路和cursor是差不多的,就是先索引,在检索。

你觉得augment好用是因为它有一个规划的流程在里面,他会把这个规划放到自己的memory里面,形成一个当前任务和长期任务的一个记忆。

就目前看上去而言,对于它判断需要读取的文件,它就全文读取(至少能感知到相关的信息,500行左右)。
image

而cursor这个低能儿现在是完全没有规划,而且极度压缩上下文。

而且augment有个好处,你可以将其他项目添加为上下文。


也就是说,如果你做一个前后端分离的项目,你在开发前端的时候,可以直接把后端的项目作为上下文直接搞到当前augment的上下文里,这样你开发前端项目的时候,augment对你的后端是有感知的。这点体验应该会很不错。

aider的这种模式有个很致命的缺点,就是严重依赖命名,如果命名太垃圾或者太随意就会导致模型错意,而 切片 + 语义总结 + 向量化后的数据,进行语义化检索的时候往往能得到一个较为准确的区间(做语义化检索的话,会需要一个额外的步骤,那就是引导模型生成 相对应的搜索语句),然后将这些区间丢给模型(这里面就涉及到上下文的问题,看厂家愿不愿意给你多带点匹配区间外的临近上下文,因为这部分上下文其实大概率也是和匹配到的区间相关联的,更直接的,其实其关联的文件也是相关度较高的,直接喂进去也是没问题的),最后如果根据这些内容已经可以求解,那么可以直接触发类似edit的操作,如果还无法求解,那么就会二次触发搜索,或者根据第一次搜索的内容去完整的读取其对应的文件进行分析,如此往复进行求解。

70 Likes

感谢解答,说得很清楚

这么看来确实,augment的方式是这几个里体验最好的。打算换vscode深度用段时间,之前试的vim插件目前是个半成品,缺少不少功能

5 Likes

好文好文,感谢

1 Like

还没用过augment

1 Like

大概看了下,感觉他们这个agent还是传统的rag路子,和普通chat的逻辑应该也还是用Claude+tool, 核心的能力应该还是claude 太牛逼了。

他们的tool:

tool 定义
"tool_definitions": [
    {
      "name": "save-file",
      "description": "Save a new file. Use this tool to write new files with the attached content. It CANNOT modify existing files. Do NOT use this tool to edit an existing file by overwriting it entirely. Use the str-replace-editor tool to edit existing files instead.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"file_path\":{\"type\":\"string\",\"description\":\"The path of the file to save.\"},\"file_content\":{\"type\":\"string\",\"description\":\"The content of the file.\"},\"add_last_line_newline\":{\"type\":\"boolean\",\"description\":\"Whether to add a newline at the end of the file (default: true).\"}},\"required\":[\"file_path\",\"file_content\"]}",
      "tool_safety": 1
    },
    {
      "name": "remember",
      "description": "Call this tool when user asks you:\n- to remember something\n- to create memory/memories\n\nUse this tool only with information that can be useful in the long-term.\nDo not use this tool for temporary information.\n",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"memory\":{\"type\":\"string\",\"description\":\"The concise (1 sentence) memory to remember.\"}},\"required\":[\"memory\"]}",
      "tool_safety": 1
    },
    {
      "name": "open-browser",
      "description": "Open a URL in the default browser.\n\n1. The tool takes in a URL and opens it in the default browser.\n2. The tool does not return any content. It is intended for the user to visually inspect and interact with the page. You will not have access to it.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"url\":{\"type\":\"string\",\"description\":\"The URL to open in the browser.\"}},\"required\":[\"url\"]}",
      "tool_safety": 1
    },
    {
      "name": "launch-process",
      "description": "Launch a new process with a shell command. A process can be waiting (`wait=true`) or non-waiting (`wait=false`, which is default).\n\nIf `wait=true`, launches the process in an interactive terminal, and waits for the process to complete up to\n`wait_seconds` seconds (default: 60). If the process ends\nduring this period, the tool call returns. If the timeout expires, the process will continue running in the\nbackground but the tool call will return. You can then interact with the process using the other process tools.\n\nNote: Only one waiting process can be running at a time. If you try to launch a process with `wait=true`\nwhile another is running, the tool will return an error.\n\nIf `wait=false`, launches a background process in a separate terminal. This returns immediately, while the\nprocess keeps running in the background.\n\nNotes:\n- Use `wait=true` processes when the command is expected to be short, or when you can't\nproceed with your task until the process is complete. Use `wait=false` for processes that are\nexpected to run in the background, such as starting a server you'll need to interact with, or a\nlong-running process that does not need to complete before proceeding with the task.\n- If this tool returns while the process is still running, you can continue to interact with the process\nusing the other available tools. You can wait for the process, read from it, write to it, kill it, etc.\n- You can use this tool to interact with the user's local version control system. Do not use the\nretrieval tool for that purpose.\n- If there is a more specific tool available that can perform the function, use that tool instead of\nthis one.\n\nThe OS is darwin. The shell is 'bash'.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"command\":{\"type\":\"string\",\"description\":\"The shell command to execute.\"},\"wait\":{\"type\":\"boolean\",\"description\":\"Optional: whether to wait for the command to complete (default false).\"},\"wait_seconds\":{\"type\":\"number\",\"description\":\"Optional: number of seconds to wait for the command to complete (default is 60). Only relevant when wait=true.\"},\"cwd\":{\"type\":\"string\",\"description\":\"Working directory for the command. If not supplied, uses the current working directory.\"}},\"required\":[\"command\"]}",
      "tool_safety": 2
    },
    {
      "name": "kill-process",
      "description": "Kill a process by its terminal ID.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"terminal_id\":{\"type\":\"integer\",\"description\":\"Terminal ID to kill.\"}},\"required\":[\"terminal_id\"]}",
      "tool_safety": 1
    },
    {
      "name": "read-process",
      "description": "Read output from a terminal.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"terminal_id\":{\"type\":\"integer\",\"description\":\"Terminal ID to read from.\"}},\"required\":[\"terminal_id\"]}",
      "tool_safety": 1
    },
    {
      "name": "write-process",
      "description": "Write input to a terminal.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"terminal_id\":{\"type\":\"integer\",\"description\":\"Terminal ID to write to.\"},\"input_text\":{\"type\":\"string\",\"description\":\"Text to write to the process's stdin.\"}},\"required\":[\"terminal_id\",\"input_text\"]}",
      "tool_safety": 1
    },
    {
      "name": "list-processes",
      "description": "List all known terminals and their states.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
      "tool_safety": 1
    },
    {
      "name": "wait-process",
      "description": "Wait for a process to complete or timeout.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"process_id\":{\"type\":\"integer\",\"description\":\"Process ID to wait for.\"},\"wait\":{\"type\":\"number\",\"description\":\"Number of seconds to wait for the process to complete.\"}},\"required\":[\"process_id\",\"wait\"]}",
      "tool_safety": 1
    },
    {
      "name": "web-search",
      "description": "Search the web for information. Returns results in markdown format.\nEach result includes the URL, title, and a snippet from the page if available.\n\nThis tool uses Google's Custom Search API to find relevant web pages.",
      "input_schema_json": "{\"description\": \"Input schema for the web search tool.\", \"properties\": {\"query\": {\"description\": \"The search query to send.\", \"title\": \"Query\", \"type\": \"string\"}, \"num_results\": {\"default\": 5, \"description\": \"Number of results to return\", \"maximum\": 10, \"minimum\": 1, \"title\": \"Num Results\", \"type\": \"integer\"}}, \"required\": [\"query\"], \"title\": \"WebSearchInput\", \"type\": \"object\"}"
    },
    {
      "name": "web-fetch",
      "description": "Fetches data from a webpage and converts it into Markdown.\n\n1. The tool takes in a URL and returns the content of the page in Markdown format;\n2. If the return is not valid Markdown, it means the tool cannot successfully parse this page.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"url\":{\"type\":\"string\",\"description\":\"The URL to fetch.\"}},\"required\":[\"url\"]}",
      "tool_safety": 0
    },
    {
      "name": "codebase-retrieval",
      "description": "This tool is Augment's context engine, the world's best codebase context engine. It:\n1. Takes in a natural language description of the code you are looking for;\n2. Uses a proprietary retrieval/embedding model suite that produces the highest-quality recall of relevant code snippets from across the codebase;\n3. Maintains a real-time index of the codebase, so the results are always up-to-date and reflects the current state of the codebase;\n4. Can retrieve across different programming languages;\n5. Only reflects the current state of the codebase on the disk, and has no information on version control or code history.",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"information_request\":{\"type\":\"string\",\"description\":\"A description of the information you need.\"}},\"required\":[\"information_request\"]}",
      "tool_safety": 1
    },
    {
      "name": "str-replace-editor",
      "description": "Custom editing tool for viewing, creating and editing files\n* `path` is a file path relative to the workspace root\n* command `view` displays the result of applying `cat -n`.\n* If a `command` generates a long output, it will be truncated and marked with `<response clipped>`\n* `insert` and `str_replace` commands output a snippet of the edited section for each entry. This snippet reflects the final state of the file after all edits and IDE auto-formatting have been applied.\n\n\nNotes for using the `str_replace` command:\n* Use the `str_replace_entries` parameter with an array of objects\n* Each object should have `old_str`, `new_str`, `old_str_start_line_number` and `old_str_end_line_number` properties\n* The `old_str_start_line_number` and `old_str_end_line_number` parameters are 1-based line numbers\n* Both `old_str_start_line_number` and `old_str_end_line_number` are INCLUSIVE\n* The `old_str` parameter should match EXACTLY one or more consecutive lines from the original file. Be mindful of whitespace!\n* Empty `old_str` is allowed only when the file is empty or contains only whitespaces\n* It is important to specify `old_str_start_line_number` and `old_str_end_line_number` to disambiguate between multiple occurrences of `old_str` in the file\n* Make sure that `old_str_start_line_number` and `old_str_end_line_number` do not overlap with other entries in `str_replace_entries`\n* The `new_str` parameter should contain the edited lines that should replace the `old_str`. Can be an empty string to delete content\n\nNotes for using the `insert` command:\n* Use the `insert_line_entries` parameter with an array of objects\n* Each object should have `insert_line` and `new_str` properties\n* The `insert_line` parameter specifies the line number after which to insert the new string\n* The `insert_line` parameter is 1-based line number\n* To insert at the very beginning of the file, use `insert_line: 0`\n\nNotes for using the `view` command:\n* Strongly prefer to use larger ranges of at least 1000 lines when scanning through files. One call with large range is much more efficient than many calls with small ranges\n* Prefer to use grep instead of view when looking for a specific symbol in the file\n\nIMPORTANT:\n* This is the only tool you should use for editing files.\n* If it fails try your best to fix inputs and retry.\n* DO NOT fall back to removing the whole file and recreating it from scratch.\n* DO NOT use sed or any other command line tools for editing files.\n* Try to fit as many edits in one tool call as possible\n* Use view command to read the file before editing it.\n",
      "input_schema_json": "{\"type\":\"object\",\"properties\":{\"command\":{\"type\":\"string\",\"enum\":[\"view\",\"str_replace\",\"insert\"],\"description\":\"The commands to run. Allowed options are: 'view', 'str_replace', 'insert'.\"},\"path\":{\"description\":\"Full path to file relative to the workspace root, e.g. 'services/api_proxy/file.py' or 'services/api_proxy'.\",\"type\":\"string\"},\"view_range\":{\"description\":\"Optional parameter of `view` command when `path` points to a file. If none is given, the full file is shown. If provided, the file will be shown in the indicated line number range, e.g. [11, 12] will show lines 11 and 12. Indexing at 1 to start. Setting `[start_line, -1]` shows all lines from `start_line` to the end of the file.\",\"type\":\"array\",\"items\":{\"type\":\"integer\"}},\"insert_line_entries\":{\"description\":\"Required parameter of `insert` command. A list of entries to insert. Each entry is a dictionary with keys `insert_line` and `new_str`.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"insert_line\":{\"description\":\"The line number after which to insert the new string. This line number is relative to the state of the file before any insertions in the current tool call have been applied.\",\"type\":\"integer\"},\"new_str\":{\"description\":\"The string to insert. Can be an empty string.\",\"type\":\"string\"}},\"required\":[\"insert_line\",\"new_str\"]}},\"str_replace_entries\":{\"description\":\"Required parameter of `str_replace` command. A list of entries to replace. Each entry is a dictionary with keys `old_str`, `old_str_start_line_number`, `old_str_end_line_number` and `new_str`. `old_str` from different entries should not overlap.\",\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"old_str\":{\"description\":\"The string in `path` to replace.\",\"type\":\"string\"},\"old_str_start_line_number\":{\"description\":\"The line number of the first line of `old_str` in the file. This is used to disambiguate between multiple occurrences of `old_str` in the file.\",\"type\":\"integer\"},\"old_str_end_line_number\":{\"description\":\"The line number of the last line of `old_str` in the file. This is used to disambiguate between multiple occurrences of `old_str` in the file.\",\"type\":\"integer\"},\"new_str\":{\"description\":\"The string to replace `old_str` with. Can be an empty string to delete content.\",\"type\":\"string\"}},\"required\":[\"old_str\",\"new_str\",\"old_str_start_line_number\",\"old_str_end_line_number\"]}}},\"required\":[\"command\",\"path\"]}",
      "tool_safety": 1
    }
  ]

此外他们的博客上提到了两个比较有意思的点

1 他们的embedding模型是专门针对大代码库设计的,

其实我们从他们的context engine也能看出来,应该还像是embedding rag的路子,不知道他们这里对模型有哪些优化

2 自动选择模型
可以明目张胆降智了

9 Likes

embedding 有推荐吗 开源几个感觉都不太行

1 Like

那个规划就是 deep research 的形式,其实并没用什么用。而且这个跟模型记忆没有任何关系。

1 Like

你多轮对话试试你就知道了,对比下cursor 和 augment吧

1 Like

你用过 cursor composer ?一样支持。而且 cursor 也可以添加外部上下文,叫做文档 Docs。

2 Likes

1 Like

两个玩意天差地别大哥,你实际用看看再说吧

3 Likes

始终感觉embedding效果是有上限的。。。

目前使用下来,augment的agent模式还是比较强的,不知道后面会不会走cursor的老路。

embedding 搜索知识库 效果一直达不到预期的精度 卡主了

:tieba_025: :tieba_025: :tieba_025:

昨天使用了了一下它的agent模式,感觉挺不错的,需求给它,一个命令它可以帮你做任务,一直把这个做完为止

感觉使用repomix 然后用gemini2.0 flash来进行上下文检索是不是不错hh

1 Like

这个是在哪里呀,第一次用没找到设置