LLM应用工程
- 针对幻觉、提示词规范: 采用“提示词工程”和“检索增强生成(RAG)”。为医疗助手设计严谨、系统的提示词模板,并强制模型在回答前先从权威、实时的医疗知识库中检索信息,而不是凭记忆回答。
- 针对模型切换: 使用 LLM API 抽象层(如 LangChain)。这些中间件统一了不同模型的接口,让开发者通过配置而非修改代码实现切换模型。
- 针对非结构化输出: 采用“输出解析”技术。强制要求模型以 JSON 等格式输出,并在提示词中严格指定 JSON 的 Schema。一些框架(如 LangChain)可以自动将模型输出解析为预定义的 Pydantic 对象。
- 针对知识限制: 主要依靠 RAG 来注入实时、外部的知识。
- 针对连接外部工具: 采用“智能体(Agent)”框架。让 LLM 作为大脑,根据用户请求规划步骤,选择工具(如计算器、数据库 API、搜索引擎),并执行任务。
初识LangChain
- 使用管道符号 “|”进行标注一个chain
- 可以使用
init_model对于模型进行统一创建和改变
# 使用 LangChain 调整模型
from langchain.chat_models import init_chat_model
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from openai import api_key
from sympy.physics.units import temperature
model = init_chat_model(
model="gpt-4o-mini",
model_provider="openai",
base_url="https://openai.moenet.top/v1/",
temperature=0.1,
configurable_fields=("temperature", "model","model_provider","api_key"),
config_prefix="first",
)
messages = [
SystemMessage("故事续写,不超过100字"),
HumanMessage("小猫叫汉堡,____"),
]
result = model.invoke(messages)
print(result)
# 对于模型进行配置
new_result = model.invoke(
input=messages,
config={
"configurable": {
"first_temperature": 10,
"first_model": "auto",
"first_model_provider": "openai",
}
}
)
print(new_result)
定义工具向LLM提问
定义工具的方式
@tool
必须加上doc string(给LLM看的)
@tool
def add(first: int, b: int) -> int:
"""
两数相加
Args:
first: 第一个数
b: 第二个数
Returns:
返回两数相加结果
"""
return first + b
- pydantic中的
BaseModel
用这种方法,将参数的描述移动到BaseModel中进行说明
class AddInput(BaseModel):
"""两数相加"""
a: int = Field(..., description="第一个数")
b: int = Field(..., description="第二个数")
@tool(args_schema=AddInput)
def add2(a: int, b: int) -> int:
return a + b
- 使用
Annotated
doc string还是不能省略,只是将参数的描述换了个地方。
@tool
def add3(a: Annotated[int, ..., "第一个数3"],
b: Annotated[int, ..., "第二个数3"]) -> int:
"""两数相加3"""
return a + b
StructuredTool
将参数与doc string都统一到一个地方进行描述。
def add4(a: int, b: int) -> int:
return a + b
class AddInput4(BaseModel):
a: int = Field(..., description="第一个数4")
b: int = Field(..., description="第二个数4")
add_tool = StructuredTool.from_function(
func=add4, # 定义对应的函数
args_schema=AddInput4, # 定义参数
description="两数相加4" # 定义描述
)
当在from_function中使用response_format,并且设置为”content_and_artifact”时,会将调用的工具的第一个返回值(str类型的自然语言)作为返回给LLM/用户的语义信息,第二个返回值(结构化的数据)作为后续代码使用的数据。
def add(a: int, b: int) -> Tuple[str, List[int]]:
# 记录一下是谁和谁相加
nums = [a, b]
content = f"{nums}相加的结果是{a + b}"
return content, nums
calculator_tool = StructuredTool.from_function(
func=add,
name="calculate sum",
description="计算两数之和",
args_schema=AddInput,
response_format="content_and_artifact",
)
使用绑定工具
绑定工具,直接使用bind_tools:
tools = [
add,
subtract,
]
model_with_tools = model.bind_tools(tools)
res = model_with_tools.invoke("3+2? 3-2? 1+2?")
定义好工具之后,需要根据问题,LLM自动选择该调用哪个工具。
发送给LLM的时候,需要发送三种信息:
- HumanMessage:人类提问
- ToolMessage:调用工具的返回值
- Ai Message:模型调用的工具、模型的种类等ai相关信息
将打包好的Message发送给LLM,其会整合信息,返回一段由自然语言组成的答案。
message = [
HumanMessage("2-3等于多少?6加6等于多少?")
]
ai_msg = model_with_tools.invoke(message) # 这里只是调用工具
print(ai_msg.tool_calls) # 调用工具的信息
for tool_call in ai_msg.tool_calls:
# 给大模型要发送的信息里添加工具信息
selected_tool = {"add": add, "subtract": subtract}[tool_call["name"].lower()]
tool_msg = selected_tool.invoke(tool_call)
message.append(tool_msg)
print(message) # 将拼接好的三种信息,发给llm
print(model_with_tools.invoke(message).content)
1096

被折叠的 条评论
为什么被折叠?



