Python 流水账(Java 开发者视角)
Python 流水账(Java 开发者视角)
摘要:本文面向有 Java 背景的开发者,系统梳理 Python 与 Java 的核心差异,涵盖类型系统、内置类型、类与异常、集合推导式、async/await、dataclass、虚拟环境与包管理,以及 PyTorch/CUDA 的定位。适合转型 AI 应用工程师(LangChain / RAG / FastAPI)时作为入门参考。
标签:Python · Java · AI应用工程师 · LangChain · 转型笔记
前言:为什么 Java 开发者要先学 Python?
AI 应用生态(LangChain、LlamaIndex、OpenAI SDK、向量库客户端)以 Python 为第一语言。如果你已有 Java 对接第三方 API 的经验——HTTP 封装、鉴权、重试、异常处理、分层架构——这些能力可以直接迁移。
你需要补齐的主要是:
- Python 语法与 Java 的差异
- 动态类型 + 鸭子类型的思维切换
- asyncio 异步模型(LLM 流式/并发调用必备)
- pip + venv 环境管理
本文不是 Python 零基础教程,而是 「用 Java 知识理解 Python」 的对照式笔记。
一、Java vs Python 总览
1.1 核心差异对照表
| 特性 | Java | Python |
|---|---|---|
| 类型 | 强类型,编译期检查 | 动态类型,可选 Type Hints |
| 入口 | public static void main |
if __name__ == "__main__" |
| 集合 | List<String> |
list[str] |
| 空值 | null |
None |
| 接口 | interface + implements |
无需声明,鸭子类型 |
| 包管理 | Maven / Gradle | pip + venv |
| 并发 | Thread / Executor / CompletableFuture | asyncio(IO 密集首选) |
| 资源管理 | try-with-resources | with 语句 |
| DTO | Lombok POJO | @dataclass / Pydantic |
1.2 思维映射(AI 应用方向)
| Java 概念 | Python / AI 应用 |
|---|---|
| Interface + Impl | Protocol / ABC / Duck Typing |
Spring @Service |
模块级函数 + FastAPI Depends |
| DTO / VO | Pydantic BaseModel |
| RestTemplate / Feign | httpx / openai SDK |
| 线程池异步 | asyncio + async/await |
| Maven 多模块 | 虚拟环境 + requirements.txt |
| JUnit | pytest |
1.3 两种语言的执行模型差异
Java:
写代码 → javac 编译(含类型检查)→ 编译失败则无法运行 → JVM 执行
Python(默认):
写代码 → 解释器加载(仅语法检查)→ 可以启动 → 运行到某行才暴露类型等错误
这是 Java 开发者转 Python 时最需要适应的一点:Python 默认没有 Java 那种编译期类型检查。
二、动态类型与鸭子类型
2.1 动态类型(Dynamic Typing)
变量的类型在运行时才知道,不是写代码时就固定死的。
Java(静态类型):
String name = "hello";
name = 123; // ❌ 编译报错:类型不匹配
Python(动态类型):
name = "hello" # 此时 name 是 str
name = 123 # ✅ 合法,现在 name 变成 int
name = [1, 2, 3] # ✅ 又变成 list
要点:
- Python 里变量没有固定类型,类型属于值(对象)
- 写错类型:Java 编译期发现;Python 运行到那行才报错
示例:
def process(data):
return data.upper() # 假设 data 是字符串
process("hello") # ✅ 正常
process(123) # ❌ 运行时报错:AttributeError: 'int' object has no attribute 'upper'
2.2 鸭子类型(Duck Typing)
「如果它走起来像鸭子、叫起来像鸭子,那就当它是鸭子。」
意思是:不关心对象是什么类,只关心它有没有你需要的方法/行为。
Java 通常要声明接口:
interface Embedder {
List<float[]> embed(List<String> texts);
}
class OpenAIEmbedder implements Embedder { ... }
void index(Embedder embedder) {
embedder.embed(...);
}
Python 鸭子类型:
def index(embedder): # 没有 interface 声明
return embedder.embed(["文档1", "文档2"])
# 只要对象有 embed 方法,都能传进来
index(OpenAIEmbedder())
index(LocalEmbedder())
更直观的例子:
class Dog:
def speak(self):
return "汪汪"
class Cat:
def speak(self):
return "喵喵"
def make_sound(animal): # 参数类型不限
print(animal.speak()) # 只要求有 speak()
make_sound(Dog()) # 汪汪
make_sound(Cat()) # 喵喵
2.3 两者如何配合
def batch_embed(embedder, texts: list[str]) -> list[list[float]]:
return embedder.embed(texts)
- 动态类型:
embedder不必声明成某个具体类 - 鸭子类型:只要它有
.embed(texts),函数就能工作
LangChain 等框架中,不同 LLM、VectorStore 组件可以互换,很大程度上就是因为这种设计。
三、Python 有编译期类型检查吗?
3.1 结论
Python 解释器默认不做 Java 那种编译期类型检查,但有语法检查:
| 阶段 | Java | Python(默认) |
|---|---|---|
| 语法错误 | 编译失败 | 启动/导入失败 |
| 类型错误 | 编译失败 | 运行到才报错 |
3.2 类型检查发生在什么时候?
以这段代码为例:
def make_sound(animal: str) -> None:
if not isinstance(animal, str):
raise TypeError(f"期望 str,实际 {type(animal)}")
print(animal.upper())
执行顺序:
1. 加载 .py 文件(解析语法)
2. 执行模块顶层代码(import、赋值、def 定义函数…)
3. 有人调用 make_sound(...) 时,才进入函数体
4. 这时才执行 isinstance,不对才 raise TypeError
| 时机 | animal: str(Type Hints) |
isinstance 检查 |
|---|---|---|
| 启动、加载模块 | 不检查 | 不检查 |
定义 def make_sound(...) |
不检查 | 不检查 |
调用 make_sound("hello") |
不检查 | ✅ 通过 |
调用 make_sound(123) |
不检查 | ❌ 此时才 TypeError |
重要:def 只是登记函数,不会在启动时跑函数体里的校验逻辑。
3.3 如何「提前发现错误」?
| 工具 | 作用 | 类似 Java 的 |
|---|---|---|
| Type Hints | 标注类型,给 IDE 用 | 方法签名 |
| mypy | 静态类型分析 | 编译期检查 |
| Pyright / Pylance | IDE 红线提示 | IDEA 警告 |
| Pydantic | 运行时校验 API 入参 | Bean Validation |
工程化建议:
- 内部逻辑:习惯写 Type Hints
- 对外 API(FastAPI):用 Pydantic 做运行时强校验
- CI 流水线:跑 mypy + pytest
四、参数类型如何限制?
Python 默认不强制参数类型,但可以用多种方式表达或校验约束。
4.1 Type Hints(类型注解)— 最常用
def make_sound(animal: str) -> None:
print(animal.upper())
- 类似 Java 方法签名
- 主要给 IDE、mypy 用
- 运行时 Python 不会自动拦你
4.2 运行时手动校验 — 真正限制住
def make_sound(animal: str) -> None:
if not isinstance(animal, str):
raise TypeError(f"期望 str,实际 {type(animal)}")
print(animal.upper())
isinstance(x, str)≈ Java 的x instanceof Stringhasattr(obj, "speak")≈ 鸭子类型检查:「有没有这个方法」
4.3 Protocol — 鸭子类型 + 类型注解
from typing import Protocol
class Speaker(Protocol):
def speak(self) -> str: ...
def make_sound(animal: Speaker) -> None:
print(animal.speak())
# Dog、Cat 不用 implements Speaker,只要有 speak 就行
class Dog:
def speak(self) -> str:
return "汪汪"
make_sound(Dog()) # ✅
≈ Java 的 interface,但运行时仍不强制实现接口。
4.4 Pydantic — AI 项目里很常见
from pydantic import BaseModel
class LLMRequest(BaseModel):
model: str
prompt: str
temperature: float = 0.7
# LLMRequest(model="gpt-4", prompt="hi", temperature="高") # ❌ ValidationError
req = LLMRequest(model="gpt-4", prompt="hi", temperature=0.7) # ✅
适合 API 入参、配置对象,运行时会真正校验。
4.5 对照总结
| 方式 | 是否运行时强制 | 适用场景 |
|---|---|---|
| 无注解 | 否 | 快速脚本、鸭子类型 |
| Type Hints | 否(除非配合工具) | 日常开发、IDE 提示 |
isinstance / hasattr |
是 | 库内部防御性编程 |
Protocol |
静态检查 | 鸭子类型 + 类型安全 |
Pydantic BaseModel |
是 | HTTP API、配置、DTO |
五、Python 基本类型详解
5.1 常用内置类型一览
| Python 类型 | 示例 | Java 大致对应 | 说明 |
|---|---|---|---|
str |
"hello" |
String |
字符串 |
int |
42 |
int / long |
整数,位数不限 |
float |
3.14 |
double |
浮点数 |
bool |
True / False |
boolean |
注意首字母大写 |
None |
None |
null |
空值 |
list |
[1, 2, 3] |
ArrayList |
有序、可变 |
tuple |
(1, 2, 3) |
无直接对应 | 有序、不可变 |
dict |
{"a": 1} |
HashMap |
键值对 |
set |
{1, 2, 3} |
HashSet |
无序、不重复 |
bytes |
b"abc" |
byte[] |
字节序列 |
查看类型:
type("hello") # <class 'str'>
type(123) # <class 'int'>
type(True) # <class 'bool'>
5.2 有 Java 的 String 类吗?
没有 String 这个名字,Python 字符串类型叫 str。
name = "hello" # 字面量
name = str(123) # 转成字符串 "123"
name.upper() # 转大写,类似 Java toUpperCase()
len(name) # 长度
name[0] # 'h',类似 charAt(0)
f"学习 {name}" # f-string 格式化
| 特性 | Java String |
Python str |
|---|---|---|
| 是否可变 | 不可变 | 不可变 |
| 类型名 | String |
str |
| 单/双引号 | 只能用 " |
"hello" 和 'hello' 等价 |
upper() 方法: 把字母转大写,返回新字符串,原字符串不变。
text = "hello"
result = text.upper() # HELLO
text # hello(没变)
5.3 没有 Java 的基本类型
Java 有 int 基本类型和 Integer 包装类之分;Python 全是对象:
x = 10
type(x) # <class 'int'>
x.bit_length() # int 也有方法
| Java | Python |
|---|---|
int / Integer |
只有 int |
boolean |
只有 bool |
null |
只有 None |
5.4 实体类(POJO)怎么写?
方式一:普通 class
class LLMRequest:
"""类似 Java POJO,Python 用 __init__ 构造"""
def __init__(self, model: str, prompt: str, temperature: float = 0.7):
self.model = model
self.prompt = prompt
self.temperature = temperature
def __repr__(self) -> str:
return f"LLMRequest(model={self.model!r}, prompt={self.prompt!r})"
对照 Java:
| Python | Java |
|---|---|
__init__ |
构造方法 |
self |
this |
__repr__ |
toString() |
默认参数 temperature=0.7 |
方法重载的简化替代 |
方式二:dataclass(类似 Lombok)
from dataclasses import dataclass
from typing import Optional
@dataclass
class ChatMessage:
role: str
content: str
@dataclass
class ChatResponse:
content: str
model: str
tokens_used: Optional[int] = None
方式三:Pydantic(AI 项目对外 API 常用)
from pydantic import BaseModel
class LLMRequest(BaseModel):
model: str
prompt: str
temperature: float = 0.7
5.5 dict 取值:AI 解析 API 响应必备
raw = {"model": "gpt-4o-mini", "usage": {"total_tokens": 42}}
raw["model"] # 必须存在,否则 KeyError
raw.get("model") # 安全取值,不存在返回 None
raw.get("model", "unknown") # 带默认值
raw.get("usage") or {} # 若为 None 则用 {}
| 写法 | 含义 | Java 类比 |
|---|---|---|
raw["key"] |
必须存在 | map.get("key") 但会抛异常 |
raw.get("key", "default") |
安全取值 | Optional.ofNullable(...).orElse(...) |
完整解析 OpenAI 风格响应示例:
def parse_response(raw: dict) -> ChatResponse:
usage = raw.get("usage") or {}
return ChatResponse(
content=raw["choices"][0]["message"]["content"],
model=raw.get("model", "unknown"),
tokens_used=usage.get("total_tokens"),
)
六、list、tuple、dict、set 深入理解
6.1 list — 可变列表
messages = ["system", "user"]
messages.append("assistant")
messages[0] = "new_system"
≈ Java ArrayList。
6.2 tuple — 创建后不可变
「固定长度」的准确含义: 不是事先声明长度,而是 创建后不能增删改元素。
# list — 可变
items = [1, 2, 3]
items.append(4) # ✅
items[0] = 99 # ✅
# tuple — 不可变
items = (1, 2, 3)
items.append(4) # ❌ 没有 append
items[0] = 99 # ❌ TypeError
list |
tuple |
|
|---|---|---|
| 能否改元素 | ✅ | ❌ |
| 长度 | 可变 | 创建后固定 |
| 写法 | [1, 2, 3] |
(1, 2, 3) |
常见用途:
# 1. 函数返回多个值
def min_max(nums):
return min(nums), max(nums)
low, high = min_max([1, 5, 3])
# 2. 当 dict 的 key(list 不能当 key)
cache = {("gpt-4", 0.7): "某次结果"}
# 3. 表示不应被改的数据
RGB = (255, 128, 0)
6.3 set — 只去重,不排序
s = set()
for x in [3, 1, 2, 5, 2, 1]:
s.add(x)
print(s) # 可能是 {1, 2, 3, 5},也可能不是 — 都不代表已排序
print(sorted(s)) # [1, 2, 3, 5] — 这才是从小到大
数字和字符串都不会自动排序:
words = {"banana", "apple", "cherry", "apple"}
# 只去重,不会自动变成 {'apple', 'banana', 'cherry'}
sorted(words) # ['apple', 'banana', 'cherry']
| 特性 | set |
|---|---|
| 去重 | ✅ |
| 排序 | ❌ |
| 保序 | ❌ |
| Python | Java |
|---|---|
set |
HashSet — 无序 |
sorted(set(...)) |
TreeSet — 要排序用这个 |
6.4 列表推导式 — AI 数据处理高频写法
≈ Java Stream 的 filter + map,一行搞定。
documents = [
{"id": 1, "title": "RAG 简介", "tokens": 120},
{"id": 2, "title": "向量检索", "tokens": 200},
{"id": 3, "title": "Agent 设计", "tokens": 350},
]
# 列表推导式
titles = [doc["title"] for doc in documents if doc["tokens"] < 300]
# ['RAG 简介', '向量检索']
# 字典推导式
token_map = {doc["id"]: doc["tokens"] for doc in documents}
# {1: 120, 2: 200, 3: 350}
Java 等价思路:
documents.stream()
.filter(doc -> doc.get("tokens") < 300)
.map(doc -> doc.get("title"))
.toList();
6.5 解包与 enumerate
# 解包
first, *rest = ["system", "user", "assistant"]
# first = "system", rest = ["user", "assistant"]
# 带索引遍历
for i, doc in enumerate(documents):
print(f"[{i}] {doc['title']}")
七、函数、异常与程序入口
7.1 函数与类型注解
def build_messages(system: str, user: str) -> list[dict[str, str]]:
"""返回 OpenAI 风格 messages 列表"""
return [
{"role": "system", "content": system},
{"role": "user", "content": user},
]
list[dict[str, str]]≈List<Map<String, String>>- 缩进即作用域,没有
{}
7.2 异常处理
def safe_divide(a: float, b: float) -> float:
try:
return a / b
except ZeroDivisionError as e:
raise ValueError("除数不能为零") from e
| Java | Python |
|---|---|
catch (ZeroDivisionException e) |
except ZeroDivisionError as e |
throw new IllegalArgumentException(...) |
raise ValueError(...) |
| 异常 cause 链 | raise ... from e |
7.3 程序入口
if __name__ == "__main__":
req = LLMRequest("gpt-4o-mini", "你好")
print(req)
if __name__ == "__main__":≈public static void main(String[] args)- 直接
python xxx.py时执行;被import时不执行
7.4 *args 与 **kwargs
def log_request(*args, **kwargs):
print("位置参数:", args) # tuple
print("关键字参数:", kwargs) # dict
log_request("gpt-4", temperature=0.7, stream=True)
# args = ('gpt-4',)
# kwargs = {'temperature': 0.7, 'stream': True}
*args:收多余位置参数 ≈ JavaObject... args**kwargs:收多余关键字参数
传参时解包:
params = {"temperature": 0.7, "stream": True}
client.chat(model="gpt-4", **params)
7.5 with 语句 ≈ try-with-resources
with open("doc.txt", encoding="utf-8") as f:
content = f.read()
# 离开 with 块自动 close
async with httpx.AsyncClient() as client:
resp = await client.get(url)
八、asyncio 异步编程 — LLM 并发必备
Java 里可能用 CompletableFuture.allOf() 做并发 HTTP;Python AI 生态更常见 asyncio。
8.1 async def 与 await
import asyncio
async def mock_llm_call(prompt: str, delay: float = 0.5) -> str:
"""模拟异步 LLM 调用"""
await asyncio.sleep(delay)
return f"回复: {prompt[:20]}..."
| 概念 | Java | Python |
|---|---|---|
| 异步函数 | 返回 CompletableFuture<T> |
async def,返回 coroutine |
| 等待 | .get() / .join() |
await |
| 非阻塞等待 | 线程阻塞 | await asyncio.sleep() 让出控制权 |
关键规则:
async def定义的函数不能直接当普通函数调用- 必须在 async 函数里
await,或在顶层用asyncio.run(main())
8.2 并发批量调用
async def batch_call(prompts: list[str]) -> list[str]:
"""并发调用多个 prompt(类似 CompletableFuture.allOf)"""
tasks = [mock_llm_call(p) for p in prompts]
return await asyncio.gather(*tasks)
async def main() -> None:
result = await mock_llm_call("什么是 RAG?")
print(result)
prompts = ["问题1", "问题2", "问题3"]
results = await batch_call(prompts)
for r in results:
print(r)
if __name__ == "__main__":
asyncio.run(main())
asyncio.gather(*tasks)≈CompletableFuture.allOf(...)- 3 个 prompt 各 0.5s:串行约 1.5s,并发约 0.5s
AI 场景: OpenAI SDK、httpx、FastAPI 都支持 async;流式 async for chunk in response 在后续开发中频繁出现。
九、环境管理与包管理
9.1 venv vs conda
两者都做环境隔离,类似 Java「每个项目一套独立依赖」。
| venv | conda | |
|---|---|---|
| 来源 | Python 标准库自带 | Anaconda / Miniconda |
| 主要管什么 | Python 包(pip) | Python 版本 + 包 + 系统级库 |
| 装包命令 | pip install |
conda install 或 pip install |
| Python 版本切换 | 不便 | conda create -n x python=3.11 |
venv 用法(AI 应用开发推荐):
python -m venv venv
# Windows 激活
venv\Scripts\activate
# Linux/Mac 激活
source venv/bin/activate
pip install -r requirements.txt
deactivate
什么时候用 conda:
- 需要固定 Python 3.10 / 3.11 且本机不好装多版本
- 安装 PyTorch + CUDA、科学计算栈
- 依赖复杂 binary 库
9.2 Miniconda vs Anaconda
| Miniconda | Anaconda | |
|---|---|---|
| 体积 | 小(几十 MB 起) | 大(几 GB) |
| 自带内容 | conda + Python + 少量基础 | 大量预装包(numpy、pandas、jupyter…) |
| 适合 | 轻量、自己控制 | 开箱即用 |
| Python 世界 | Java 世界(近似) |
|---|---|
| Miniconda | 只装 JDK + Maven |
| Anaconda | JDK + Maven + 全家桶 |
9.3 pip 与 PyPI
pip = Python 的包安装工具,从网上下载并安装第三方库。
pip install openai
pip install -r requirements.txt
pip list
pip uninstall openai
| Python | Java |
|---|---|
| pip | Maven / Gradle |
| requirements.txt | pom.xml |
pip install xxx |
添加 dependency 后下载 |
PyPI = Python Package Index(https://pypi.org),Python 的公共包仓库。
| Python | Java |
|---|---|
| PyPI | Maven Central |
pip install openai |
pom 里写 dependency |
流程:
pip install openai → pip 去 PyPI 下载 → 装到当前 venv/conda 环境 → import openai
conda 与 pip 别搞混:
| 工具 | 仓库 | 常见用途 |
|---|---|---|
| pip | PyPI | LangChain、FastAPI、OpenAI SDK |
| conda install | conda-forge 等 | Python 版本、numpy、CUDA |
十、PyTorch 与 CUDA 是什么?我需要学吗?
10.1 PyTorch
Python 主流深度学习框架,用于构建神经网络、训练和推理模型。
import torch
x = torch.tensor([1.0, 2.0, 3.0])
y = x * 2
10.2 CUDA
NVIDIA 的 GPU 并行计算平台,让程序能用 NVIDIA 显卡做大规模矩阵运算。
| 概念 | 说明 |
|---|---|
| CPU | 通用计算,适合业务逻辑、API |
| GPU | 大量并行,适合矩阵、模型计算 |
| CUDA | 让 PyTorch 等框架「会用 NVIDIA GPU」 |
10.3 为什么常一起提「PyTorch + CUDA」?
装 PyTorch 时要选是否 GPU 版、对应哪个 CUDA 版本。没有 GPU/CUDA 时 PyTorch 只能跑 CPU,大模型会很慢。conda 在这种场景里常能把 Python + PyTorch + CUDA 相关库一起配好。
10.4 AI 应用工程师需要吗?
| 方向 | 需要什么 | 典型技术 |
|---|---|---|
| AI 应用工程师 | API、向量库、Prompt | OpenAI SDK、LangChain、FastAPI |
| 算法/训练工程师 | 本地 GPU、大数据 | PyTorch + CUDA |
| 本地部署开源模型 | GPU + 推理框架 | PyTorch、llama.cpp、vLLM |
| 概念 | 近似理解 |
|---|---|
| 调 OpenAI API | 像调第三方支付 API,算力在对方 |
| PyTorch 本地推理 | 像在自己机房部署清算引擎 |
结论:转型 AI 应用工程师、以 LangChain/RAG/Agent 为主,通常不需要先装 PyTorch + CUDA。
十一、动手练习
练习 1 — 类与函数
# 1. 给 LLMRequest 增加 max_tokens: int = 2048
# 2. build_messages 支持传入多个 user 消息
练习 2 — 集合推导式
documents = [
{"id": 1, "title": "RAG 简介", "tokens": 120},
{"id": 2, "title": "向量检索", "tokens": 200},
{"id": 3, "title": "Agent 设计", "tokens": 350},
]
# 求 tokens 总和
total = sum(doc["tokens"] for doc in documents)
# 求 tokens 最大的文档 title
max_doc = max(documents, key=lambda d: d["tokens"])
print(max_doc["title"])
练习 3 — 异步
# 对比串行 vs 并发耗时
import asyncio
import time
async def main():
prompts = ["问题1", "问题2", "问题3"]
start = time.time()
for p in prompts:
await mock_llm_call(p)
print(f"串行: {time.time() - start:.2f}s")
start = time.time()
await batch_call(prompts)
print(f"并发: {time.time() - start:.2f}s")
练习 4 — DTO
# 新增 ChatRequest dataclass: model, messages: list[ChatMessage]
# 写一个 to_openai_payload() -> dict 方法
十二、学习检查清单
- 能解释动态类型与鸭子类型的区别
- 能解释 Python 为何没有 Java 那种编译期类型检查
- 知道 Type Hints、isinstance、Pydantic 各自何时报错
- 能解释
*args/**kwargs的含义 - 能写出带类型注解的函数签名
- 理解
async def与await的调用关系 - 能使用列表推导式替代简单 for 循环
- 理解
with语句(类似 Java try-with-resources) - 知道
str、list、dict、tuple、set的区别与用途 - 知道 tuple 不可变、set 只去重不排序
- 知道 venv、pip、PyPI、conda 分别是什么
- 知道 AI 应用路线暂不需要 PyTorch + CUDA
十三、总结
| 主题 | 核心要点 |
|---|---|
| 类型系统 | 动态类型 + 鸭子类型;无默认编译期检查 |
| 类型约束 | Type Hints 提示;Pydantic 强校验 |
| 基本类型 | str 即字符串;无 String 类名 |
| 容器 | list 可变;tuple 不可变;set 去重不排序 |
| 异步 | async/await + asyncio.gather 做 LLM 并发 |
| DTO | @dataclass 或 Pydantic BaseModel |
| 环境 | AI 应用开发优先 venv + pip + PyPI |
| PyTorch | 训练/本地推理才需要,调 API 不需要 |
Java 开发者转型 AI 应用工程师,HTTP 对接、异常处理、分层架构经验可以直接复用。重点补齐 Python 语法、异步模型和 pip 生态,即可顺利进入 Prompt Engineering、LLM API 封装、RAG 等后续阶段。
附录:推荐阅读顺序
- 本文笔记(建立 Java → Python 映射)
- Prompt Engineering(System/User Prompt、Few-shot)
- LLM API 客户端封装(复用 Java 对接经验)
- LangChain → RAG → Agent → FastAPI 服务化
本文为个人学习笔记,欢迎交流指正。
更多推荐
所有评论(0)