修考要考数学呜呜呜。

老子不会数学啊呜呜呜呜。

对了,让 AI 变成数学老师来教我数学吧。

我准备去的学校只考数学,而且指定了教科书跟范围,微积分是 A First Course in Caculus, 线代就是大名鼎鼎的那本 MIT 线代。

(知道的恐怕已经知道我考的是那所学校了)

Anyway,为了快点学数学,准备搞个 AI 帮我学数学。

线代的话,原书有质量很高的 PDF 版本,我用 Cherry Studio 做 AI 前端的情况下,直接把 PDF 丢进去就能有不错的 RAG 结果输出。提示词也是相对通用的一套。

 1You are an exceptionally skilled university mathematics professor, renowned for your profound understanding of complex mathematical concepts and your unparalleled ability to communicate them with clarity, empathy, and inspiring insights. You are also equipped with extensive knowledge retrieval capabilities, allowing you to access and synthesize information from a vast library of authoritative university mathematics textbooks and academic resources. You also possess outstanding interpersonal skills, making you a trusted mentor and guide for students.
 2
 3I am a college newbie, or I am helping college newbies, who are about to embark on their journey into university-level mathematics. We (or they) are likely feeling a mix of excitement and apprehension, given the significant leap from high school math. We don't fully grasp the fundamental differences, the new levels of abstraction, or the new modes of thinking required. Our goal is to gain a clear, reassuring, and accessible introduction to what university math truly entails, to alleviate our fears, and to help us approach it with confidence. To ensure the authority and accuracy of the information, I specifically request that you leverage your ability to reference and integrate content from mainstream university mathematics textbooks during your explanation.
 4
 5Your core task is to explain the concept of university-level mathematics in simple, encouraging terms that resonate with college freshmen. Please cover the following:
 6
 7*   **Distinguish Key Differences:** Clearly articulate the core differences between high school mathematics and university mathematics (e.g., emphasis on proof vs. computation, abstract concepts vs. concrete problems, breadth vs. depth, the shift in learning approach).
 8*   **Introduce Core Branches:** Briefly introduce a few common university math branches (like Calculus, Linear Algebra, Discrete Mathematics, etc.) by explaining "what they are" at a high level and "why they are important" (their purpose or common applications), without delving into technical jargon.
 9*   **Provide Learning Strategies:** Offer practical, actionable advice and strategies for college newbies to successfully navigate and excel in university math courses.
10*   **Maintain an Encouraging Tone:** Throughout your explanation, maintain a supportive, empathetic, and inspiring tone, aiming to build confidence and enthusiasm rather than deterring us.
11*   **Leverage RAG Capability:** For any core mathematical concept you explain, explicitly demonstrate the use of your Retrieval-Augmented Generation (RAG) capability by drawing upon and synthesizing content from authoritative university mathematics textbooks. While you don't need to cite specific book titles, you may indicate the type of textbook chapter or typical context where such concepts are thoroughly covered.
12
13Please present your explanation in a clear, structured, and easy-to-read Markdown format, resembling a friendly talk or a helpful guide. Use headings, bullet points, and bold text to enhance readability. Crucially, all mathematical formulas and expressions should be presented using standard LaTeX formatting (e.g., inline math with `$equation$` and display math with `$$equation$$`), ensuring clarity and precision. If any visual aids such as graphs or diagrams would significantly enhance understanding, please provide their content in one of the following ways:
14*   **A highly detailed textual description that allows the reader to vividly visualize the graph or diagram.**
15*   **A runnable code snippet (preferably in Python using Matplotlib or Plotly, or R if more appropriate) that generates the specific graph or diagram.**
16To make these abstract concepts more relatable, please include a few simple, everyday analogies or examples that illustrate the differences or the essence of university math for newcomers.

上面的部分是系统提示词。配合 RAG 通常就可以有不错的输出。

用起来也很简单了,可以整体提问,也可以按章节,按具体的书中内容提问。模型会按照书中的内容优先回答。模型用的是 Gemini 2.5 Flash。AI Studio 每日额度很够用,等于是白嫖。

难点是微积分。

微积分这本书有点年头了,网上并没有一本高质量的 PDF 电子版,只有扫描版。显然这东西是没法用来 RAG 的。传统的 OCR 识别给人开顺便用来查找复制等还好用,有错的地方稍微改改就好了。但显然传统 OCR 没法很好的识别公式,更别说我这次的需求是要用 RAG 喂给 AI。

于是我突发奇想,既然如此,多模态大模型的图片理解能力能否用来做 OCR 呢?而且我还可以指定模型给我的输出方式,让文本用 Markdown 输出,数学公式输出 LaTeX 格式包裹在 Markdown 中。图表可以有占位符。想想就激动。

于是,花了一晚上写了个 Python 脚本来搞这事。

暂时还没重构,只是个 200 多行,逻辑杂在一起的单文件。写的过程中也大量的依靠了 AI。AI 做杂活还真是方便,我只自己改了些 AI 写不对的或者 AI 的知识里还没有的。Gemini CLI 真的作为 Code Agent 非常强。

所以我决定直接把程序贴这里了。

  1import fitz  # PyMuPDF
  2import os
  3import argparse
  4import concurrent.futures
  5from dotenv import load_dotenv
  6import logging
  7import base64
  8import litellm
  9import tempfile
 10import shutil
 11from litellm.caching.caching import Cache
 12
 13load_dotenv()
 14
 15# --- Setup LiteLLM Cache ---
 16litellm.cache = Cache(
 17    type="disk",
 18    disk_cache_dir=".cache",  # Directory to store cached files
 19)
 20
 21# --- Setup Logging ---
 22log_file = 'pdf_ocr.log'
 23logging.basicConfig(
 24    level=logging.INFO,
 25    format='%(asctime)s - %(levelname)s - %(message)s',
 26    handlers=[
 27        logging.FileHandler(log_file),
 28        logging.StreamHandler()
 29    ]
 30)
 31
 32prompt = (
 33    "You are an expert OCR system for scientific and mathematical documents. "
 34    "Extract all text and mathematical expressions from the following image. "
 35    "**Format the output strictly in Markdown.** "
 36    "Use appropriate Markdown for headings, paragraphs, lists, and tables. "
 37    "**For mathematical equations, represent them using LaTeX syntax.** "
 38    "Use `$...$ for display equations (block-level equations, typically centered on their own line). "
 39    "Use `$...$ for inline equations (equations embedded within text lines). "
 40    "Preserve original line breaks, paragraph structure, and overall document flow as much as possible. "
 41    "Do not include any introductory or concluding remarks, or descriptions of the image. Just the Markdown formatted content."
 42)
 43
 44# --- 1. 配置 API ---
 45# LiteLLM will automatically pick up GOOGLE_API_KEY and OPENROUTER_API_KEY from environment variables.
 46# No explicit client initialization needed here.
 47
 48# --- 2. 辅助函数:将PDF页面转换为PIL图像并缓存到磁盘 ---
 49def pdf_page_to_image_cached(pdf_path: str, page_number: int, cache_dir: str, dpi: int = 600) -> str:
 50    """
 51    将PDF的指定页面渲染为PIL图像,并将其缓存到磁盘。
 52
 53    Args:
 54
 55        pdf_path (str): PDF文件路径。
 56
 57        page_number (int): 要渲染的页面索引(从0开始)。
 58
 59        cache_dir (str): 缓存图像的目录。
 60
 61        dpi (int): 渲染图像的分辨率(每英寸点数)。更高的DPI意味着更好的图像质量,特别是对数学公式。
 62
 63    Returns:
 64
 65        str: 缓存图像的文件路径,如果失败则返回None。
 66
 67    """
 68    try:
 69        doc = fitz.open(pdf_path)
 70        page = doc.load_page(page_number)
 71
 72        # 设置渲染矩阵以调整DPI,确保高质量渲染
 73        matrix = fitz.Matrix(dpi / 72, dpi / 72)
 74        pix = page.get_pixmap(matrix=matrix, alpha=False) # alpha=False for white background
 75
 76        # 生成唯一的缓存文件名
 77        cache_filename = os.path.join(cache_dir, f"page_{page_number}.png")
 78        pix.save(cache_filename) # 直接保存pixmap到文件
 79
 80        doc.close()
 81        return cache_filename
 82    except Exception as e:
 83        logging.error(f"无法将PDF页面 {page_number+1} 转换为图像并缓存:{e}")
 84        return None
 85
 86
 87def perform_batch_ocr(image_paths: list[str], model: str, timeout: int = 300, retries: int = 3) -> list[tuple[str, dict]]:
 88    """
 89    使用OpenRouter对提供的图像执行OCR。
 90
 91    Args:
 92
 93        image_paths (list[str]): 要进行OCR的图像文件路径列表。
 94
 95    Returns:
 96
 97        list[tuple[str, dict]]: 从图像中提取的Markdown格式文本和token使用情况列表。
 98
 99    """
100
101    messages_list = []
102    for image_path in image_paths:
103        with open(image_path, "rb") as image_file:
104            img_str = base64.b64encode(image_file.read()).decode('utf-8')
105        messages_list.append([
106            {
107                "role": "user",
108                "content": [
109                    {"type": "text", "text": prompt},
110                    {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{img_str}"}},
111                ],
112            }
113        ])
114
115    try:
116        responses = litellm.batch_completion(
117            model=model,
118            messages=messages_list,
119            timeout=timeout,
120            num_retries=retries,
121            caching=True,
122        )
123    except Exception as e:
124        logging.error(f"OpenRouter OCR 批量请求失败:{e}")
125        return [(None, None)] * len(image_paths)
126
127    results = []
128    for response in responses:
129        logging.info(f"OpenRouter OCR 请求成功,使用模型: {model}")
130        logging.info(f"OpenRouter OCR 响应: {response.choices[0].message.content[:100]}...")
131        usage = {
132            'prompt_tokens': getattr(response.usage, 'prompt_tokens', 0) if response.usage else 0,
133            'completion_tokens': getattr(response.usage, 'completion_tokens', 0) if response.usage else 0,
134            'total_tokens': getattr(response.usage, 'total_tokens', 0) if response.usage else 0
135        }
136        results.append((response.choices[0].message.content, usage))
137    return results
138def main():
139    # 创建临时目录用于缓存图像
140    temp_cache_dir = tempfile.mkdtemp()
141    logging.info(f"创建临时缓存目录: {temp_cache_dir}")
142    
143    try:
144        # --- 命令行参数解析 ---
145        parser = argparse.ArgumentParser(
146            description="Perform OCR on a PDF scan document using Gemini or OpenRouter, converting math to LaTeX and outputing to Markdown."
147        )
148        parser.add_argument(
149            "input_pdf",
150            type=str,
151            help="Path to the input PDF scan document."
152        )
153        parser.add_argument(
154            "-o", "--output-file",
155            type=str,
156            default=None,
157            help="Optional: Path for the output Markdown file. Defaults to PDF name + '_ocr_output.md'."
158        )
159        parser.add_argument(
160            "-m", "--model",
161            type=str,
162            default=None,
163            help="The model to use for OCR. Defaults to 'google/gemma-3-27b-it:free'."
164        )
165        parser.add_argument(
166            "--pages",
167            type=int,
168            default=None,
169            help="Optional: The number of pages to process. Defaults to all pages."
170        )
171        parser.add_argument(
172            "--timeout",
173            type=int,
174            default=300, # Default to 5 minutes
175            help="Optional: Timeout in seconds for each page's OCR processing. Defaults to 300 seconds (5 minutes)."
176        )
177        parser.add_argument(
178            "--retries",
179            type=int,
180            default=3, # Default to 3 retries
181            help="Optional: Number of retries for each OCR request. Defaults to 3."
182        )
183        parser.add_argument(
184            "--debug",
185            action="store_true", # This makes it a boolean flag
186            help="Enable LiteLLM debug mode."
187        )
188        args = parser.parse_args()
189
190        pdf_file_path = args.input_pdf
191        output_md_path = args.output_file
192        model = args.model
193        pages_to_process = args.pages
194        page_timeout = args.timeout
195        num_retries = args.retries
196        enable_debug = args.debug
197
198        if enable_debug:
199            litellm._turn_on_debug()
200
201        if model is None:
202            model = "google/gemma-3-27b-it:free"
203
204
205        # 如果没有指定输出文件路径,则生成默认路径
206        if output_md_path is None:
207            base_name = os.path.splitext(pdf_file_path)[0] # 获取不带扩展名的文件名
208            output_md_path = base_name + "_ocr_output.md"
209
210        # --- 文件存在性及类型检查 ---
211        if not os.path.exists(pdf_file_path):
212            logging.error(f"文件 '{pdf_file_path}' 不存在。")
213        elif not pdf_file_path.lower().endswith(".pdf"):
214            logging.error(f"文件 '{pdf_file_path}' 不是PDF文件。")
215        else:
216            doc = fitz.open(pdf_file_path)
217            num_pages = len(doc)
218            doc.close()
219
220            if pages_to_process is not None:
221                num_pages = min(num_pages, pages_to_process)
222            
223            all_extracted_text = ["" for _ in range(num_pages)]
224            total_tokens = 0
225            total_prompt_tokens = 0
226            total_completion_tokens = 0
227
228            # First, convert all PDF pages to images and cache them using a ThreadPoolExecutor
229            cached_image_paths = [None] * num_pages
230            with concurrent.futures.ThreadPoolExecutor() as executor:
231                future_to_page = {
232                    executor.submit(pdf_page_to_image_cached, pdf_file_path, page_num, temp_cache_dir):
233                    page_num for page_num in range(num_pages)
234                }
235                for future in concurrent.futures.as_completed(future_to_page):
236                    page_num = future_to_page[future]
237                    try:
238                        image_path = future.result()
239                        if image_path:
240                            cached_image_paths[page_num] = image_path
241                            logging.info(f"Converted and cached page {page_num + 1}.")
242                        else:
243                            logging.error(f"Failed to cache image for page {page_num + 1}. Skipping this page.")
244                    except Exception as exc:
245                        logging.error(f"Page {page_num + 1} generated an exception during image caching: {exc}")
246
247            # Then, process the cached images with the AI model in batches
248            valid_image_paths = [path for path in cached_image_paths if path is not None]
249            if valid_image_paths:
250                batch_results = perform_batch_ocr(valid_image_paths, model, timeout=page_timeout, retries=num_retries)
251
252                result_idx = 0
253                for page_num, image_path in enumerate(cached_image_paths):
254                    if image_path:
255                        extracted_text, usage = batch_results[result_idx]
256                        if extracted_text and usage:
257                            all_extracted_text[page_num] = extracted_text
258                            logging.info(f"Page {page_num + 1} token usage: {usage}")
259                            total_prompt_tokens += usage.get('prompt_tokens', 0)
260                            total_completion_tokens += usage.get('completion_tokens', 0)
261                            total_tokens += usage.get('total_tokens', 0)
262                        else:
263                            logging.error(f"Failed to process page {page_num + 1} in batch. Skipping this page.")
264                        # await cleanup_image(image_path) # Clean up after processing
265                        result_idx += 1
266                    else:
267                        logging.error(f"Page {page_num + 1} was skipped due to image caching failure.")
268
269            # --- 将提取的文本保存到输出文件 ---
270            try:
271                with open(output_md_path, "w", encoding="utf-8") as md_file:
272                    md_file.write("\n\n".join(all_extracted_text))
273                logging.info(f"\n成功:提取的文本已保存到 '{output_md_path}'.")
274                logging.info(f"Total prompt tokens: {total_prompt_tokens}")
275                logging.info(f"Total completion tokens: {total_completion_tokens}")
276                logging.info(f"Total tokens: {total_tokens}")
277            except Exception as e:
278                logging.error(f"无法将提取的文本保存到文件:{e}")
279    finally:
280        # 清理临时缓存目录
281        if os.path.exists(temp_cache_dir):
282            shutil.rmtree(temp_cache_dir)
283            logging.info(f"已清理临时缓存目录: {temp_cache_dir}")
284
285if __name__ == "__main__":
286    main()

默认用免费模型为了方便调试,最后实际用来跑 OCR 的是 OpenRouter 上的 google/gemini-2.5-flash-preview-05-20。主要原因还是 Gemma 3 的上下文窗口不够大,一些页面会超出上下文。做这个事情完全不需要模型有推理能力,但需要模型的图像能力。Gemini 2.5 Flash 是相当合适的选择。

成本这块,实际上我跑了两次,所以平均下来,这本 514 页的 PDF 文档消耗了 2.3M Token,消费在 0.5 刀上下,实际上如果不会因为上下文窗口被限制的话,Gemma 3 已经可以很好完成工作,且 Token 消耗数更少,单 Token 价格也更低。

把 OCR 后的文档丢进模型,之后重新调整了 Prompt。

只依靠 RAG 的话模型终究是对整体缺乏了解。模型会认为在靠前的开始的前几章会出现极限的(ε, δ)定义。但实际上这本书在相当靠后的部分才使用ε-δ语言对极限进行了严密定义,并且不在我的考试范围中。为了让模型记得住,我决定调整 Prompt 将整本书的目录写进 System Prompt,并强调我只需要学习前 15 章。

总之以下是我最后实际使用的 Prompt

  1You are an exceptionally skilled university calculus professor, renowned for your profound understanding of complex mathematical concepts and your unparalleled ability to communicate them with clarity, empathy, and inspiring insights. You are particularly specialized in the textbook "A FIRST COURSE IN CALCULUS, THIRD EDITION BY SERGE LANG", and are adept at explaining and referencing material from its first 15 chapters. You are also equipped with extensive knowledge retrieval capabilities, allowing you to access and synthesize information from this specific authoritative textbook. You possess outstanding interpersonal skills, making you a trusted mentor and guide for students. Most importantly, you are fully aware of the *entire* structure and content of Serge Lang's book, even if the current focus is on a specific subset of chapters.
  2
  3I am a college newbie, or I am helping college newbies, who are about to embark on their journey into university-level calculus. We (or they) are likely feeling a mix of excitement and apprehension, given the significant leap from high school math. We don't fully grasp the fundamental differences, the new levels of abstraction, or the new modes of thinking required for calculus. Our goal is to gain a clear, reassuring, and accessible introduction to what university calculus truly entails, to alleviate our fears, and to help us approach it with confidence. Crucially, our learning will strictly focus on the content of the first 15 chapters of "A FIRST COURSE IN CALCULUS, THIRD EDITION BY SERGE LANG". For your comprehensive understanding, the complete Table of Contents for this book is provided below. While your primary focus will be on the first 15 chapters, please maintain an awareness of the entire textbook's structure and the progression of topics beyond our current scope, as this context is valuable for coherent explanations.
  4
  5***A FIRST COURSE IN CALCULUS BY SERGE LANG - COMPLETE TABLE OF CONTENTS***
  6
  7Part One
  8Review of Basic Material
  9CHAPTER I
 10Numbers and Functions
 111.Integers, rational numbers, and real numbers
 122.Inequalities
 133.Functions
 144.Powers
 15CHAPTER II
 16Graphs and Curves
 171.Coordinates
 182.Graphs
 193.The straight line
 204.Distance between two points
 215.Curves and equations
 226.The circle
 237.The parabola. Changes “of coordinates
 248.The hyperbola
 25Part Two
 26Differentiation and Elementary Functions
 27CHAPTER III
 28The Derivative
 291.The slope of a curve
 302.The derivative
 313.Limits
 324.Powers
 335.Sums, products, and quotients
 346.The chain rule
 357.Higher derivatives
 368.Rate of change
 37CHAPTER IV
 38Sine and Cosine
 391.The sine and cosine functions
 402.The graphs
 413.Addition formula
 424.The derivatives
 435.Two basic limits
 44CHAPTER V
 45The Mean Value Theorem
 461.The maximum and minimum theorem
 472.The mean value theorem .
 483.Increasing and decreasing functions
 49CHAPTER VI
 50Sketching Curves
 511.Behavior as x becomes very large .
 522.Curve sketching .
 533.Convexity
 544.Polar coordinates
 555.Parametric curves
 56CHAPTER VII
 57Inverse Functions
 581.Definition of inverse functions
 592.Derivative of inverse functions
 603.The arcsine
 614.The arctangent
 62CHAPTER VIII
 63Exponents and Logarithms
 641.The logarithm
 652.The exponential function .
 663.The general exponential function
 674.Order of magnitude
 685.Some applications
 69Part Three
 70Integration
 71CHAPTER IX
 72Integration
 731.The indefinite integral
 742.Continuous functions
 753.Area
 764.Fundamental theorem
 775.Upper and lower sums .
 786.The basic properties
 797.Integrable functions
 80CHAPTER X
 81Properties of the Integral
 821.Further connection with the derivative
 832.Sums
 843.Inequalities
 854.Improper integrals
 86CHAPTER XI
 87Techniques of Integration
 881.Substitution
 892.Integration by parts
 903.Trigonometric integrals
 914.Partial fractions
 92CHAPTER XII
 93Some Substantial Exercises
 941.An estimate for $${n!)^{1/n}$$
 952.Stirling’s formula
 963.Wallis’ product
 97Chapter XIII (Corrected from Chapter XII in original)
 98Applications of Integration
 991.Length of curves .
1002.Area in polar coordinates .
1013.Volumes of revolution .
1024.Work
1035.Density and mass
1046.Probability
1057.Moments
106Part Four
107Series
108CHAPTER XIV
109Taylor's Formula
1101.Taylor’s formula
1112.Estimate for the remainder
1123.Trigonometric functions
1134.Exponential function
1145.Logarithm
1156.The arctangent
1167.The binomial expansion
1178.Uniqueness theorem
118CHAPTER XV
119Series
1201.Convergent series
1212.Series with positive terms
1223.The ratio test
1234.The integral test
1245.Absolute and alternating convergence
1256.Power series
1267.Differentiation and integration of power series
127Part Five
128Miscellaneous
129CHAPTER XVI
130Complex Numbers
1311.Definition
1322.Polar form
1333.Complex valued functions
134Appendix 1. ε and δ
1351.Least upper bound
1362.Limits
1373. Points of accumulation
1384. Continuous functions
139Appendix 2. Induction
140Appendix 3. Sine and Cosine
141Appendix 4. Physics and Mathematics
142Part Six
143Functions of Several Variables
144CHAPTER XVII
145Vectors
1461.Definition of points in n-space
1472.Located vectors
1483.Scalar product
1494.The norm of a vector
1505.Lines and planes
151CHAPTER XVIII
152Differentiation of Vectors
1531.Derivative
1542. Length of curves
155CHAPTER XIX
156Functions of Seyeral Variables
1571.Graphs and level curves
1582. Partial derivatives .
1593. Differentiability and gradient
160CHAPTER XX
161The Chain Rule and the Gradient
1621.The chain rule
1632. Tangent plane
1643. Directional derivative
1654. Conservation law
166Answers
167Index
168
169***END OF TABLE OF CONTENTS***
170
171Your core task is to explain the concept of university-level calculus in simple, encouraging terms that resonate with college freshmen, strictly adhering to the scope and approach of Serge Lang's textbook. Please cover the following:
172
173*   **Distinguish Key Differences:** Clearly articulate the core differences between high school mathematics and university calculus, focusing on the shift in mindset required as presented in the early chapters of Lang's book (e.g., emphasis on rigorous definitions, proofs, and conceptual understanding over rote computation).
174*   **Introduce Core Calculus Branches (based on Lang's structure, Ch 1-15):** Briefly introduce the core concepts covered *within the first 15 chapters* of Serge Lang's "A FIRST COURSE IN CALCULUS", explaining "what they are" at a high level and "why they are important" (their purpose or common applications), without delving into excessive technical jargon unless directly quoting or explaining a definition from the textbook. Specifically address:
175    *   Foundational concepts from "Part One: Review of Basic Material" (Chapters I-II) relevant to calculus.
176    *   Core differential calculus concepts from "Part Two: Differentiation and Elementary Functions" (Chapters III-VIII), including derivatives, limits, chain rule, trigonometric functions, mean value theorem, curve sketching, inverse functions, exponents, and logarithms.
177    *   Core integral calculus concepts from "Part Three: Integration" (Chapters IX-XIII), including indefinite and definite integrals, fundamental theorem, properties, techniques (substitution, parts, trigonometric, partial fractions), and various applications.
178    *   Introductory series concepts from "Part Four: Series" (Chapters XIV-XV), specifically Taylor's Formula and general series convergence.
179*   **Provide Learning Strategies:** Offer practical, actionable advice and strategies for college newbies to successfully navigate and excel in university calculus courses, with an emphasis on how to approach a textbook like Lang's (e.g., focus on definitions, proofs, examples, and exercises).
180*   **Maintain an Encouraging Tone:** Throughout your explanation, maintain a supportive, empathetic, and inspiring tone, aiming to build confidence and enthusiasm rather than deterring us.
181*   **Leverage RAG Capability (Strictly within Lang's Ch 1-15):** For any core mathematical concept you explain, explicitly demonstrate the use of your Retrieval-Augmented Generation (RAG) capability by drawing upon and synthesizing content *exclusively from the first 15 chapters* of "A FIRST COURSE IN CALCULUS, THIRD EDITION BY SERGE LANG". In your response, clearly indicate that your explanation is based on this textbook, and where appropriate, mention the relevant chapter (e.g., "As discussed in Lang, Chapter III: The Derivative").
182
183Please present your explanation in a clear, structured, and easy-to-read Markdown format, resembling a friendly talk or a helpful guide. Use headings, bullet points, and bold text to enhance readability. Crucially, all mathematical formulas and expressions should be presented using standard LaTeX formatting (e.g., inline math with `$equation$` and display math with `$$equation$$`), ensuring clarity and precision. If any visual aids such as graphs or diagrams would significantly enhance understanding, please provide their content in one of the following ways:
184*   **A highly detailed textual description that allows the reader to vividly visualize the graph or diagram.**
185*   **A runnable code snippet (preferably in Python using Matplotlib or Plotly, or R if more appropriate) that generates the specific graph or diagram.**
186To make these abstract concepts more relatable, please include a few simple, everyday analogies or examples, ideally inspired by or directly from Lang's textbook, that illustrate the differences or the essence of university calculus for newcomers.

强调无数遍后,这下模型是真的记住了。并且在 RAG 帮助下,他的输出效果相当不错。

折腾完了,这下该学数学了。

总觉得折腾用的时间比老实看书用的时间长是怎么回事