ollama версия 0.9.6
def run_prompt(messages, model: str, format_schema = None, tools: dict[str, Callable] = None) -> str:
conversation = messages.copy()
while True:
try:
# Send the request to the Ollama server
response: ChatResponse = client.chat(
model=model,
messages=conversation,
format=format_schema.model_json_schema() if format_schema else None,
tools=list(tools.values()) if tools else None,
stream=False,
)
message = response.message
# Check if the message contains tool calls
if message.tool_calls:
for tool_call in message.tool_calls:
logger.info(f"Tool call detected: {tool_call.function.name}")
if function_to_call := tools.get(tool_call.function.name):
logger.info(f"Calling tool: {tool_call.function.name}")
output = function_to_call(**tool_call.function.arguments)
conversation.append({
'role': 'tool',
'name': tool_call.function.name,
'content': output
})
else:
logger.warning(f"Tool not found: {tool_call.function.name}")
# Continue loop to get next message after tool call result
continue
# Final response received
return message.get('content')
except requests.RequestException as e:
logger.error(f"Error running prompt: {e}")
raise
< /code>
Я передаю функцию таким образом: < /p>
Код: Выделить всё
available_tools = {
'rag_search': rag_search,
}
< /code>
где rag_search < /code> является вызовом.
Это то, на что выглядит функция: < /p>
def rag_search(query: str, top_k: int = 5) -> list:
"""
Perform a semantic search over indexed documentation or CSV descriptions.
This tool retrieves the most relevant textual documents or file descriptions
based on a natural language query. It is used to ground reasoning steps in
up-to-date or domain-specific context.
Args:
query (str): Natural language question or goal.
top_k (int, optional): Maximum number of relevant documents to return.
Returns:
list: A list of documents, each with its source, content, and metadata.
"""
results = retriever.semantic_search(query, top_k)
return [
{
"source": r.metadata.get("source", "Unknown"),
"content": r.page_content,
"metadata": r.metadata,
} for r in results
]
Код: Выделить всё
# Compose LLM prompt
user_input = {
"input_json": json.loads(query),
}
messages = [
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": json.dumps(user_input, indent=2, ensure_ascii=False)}
]
response = ""
for _ in range(MAX_RETRIES):
response = run_prompt(
messages=messages,
model=OLLAMA_MODEL,
format_schema=Agent4Output,
tools=available_tools
)
Вот пример того, что я отправляю в качестве пользователя ввода:
Код: Выделить всё
You are a data visualization assistant.
You MUST use the tool rag_search before returning ANY JSON.
TOOLS AVAILABLE:
- rag_search(query: str): use this to get info about chart types.
STRICT WORKFLOW:
1. For each possible chart (bar, pie, line, etc.), you MUST call rag_search with a query like "bar chart" or "pie chart".
2. Wait for the tool result.
3. Then build the JSON "visualisations" using that info.
[...]
< /code>
Вот ответ от LLM с этой подсказкой: < /p>
model='granite3.3:8b' created_at='2025-07-23T08:22:36.686825Z' done=True done_reason='stop' total_duration=24844374458 load_duration=47660708 prompt_eval_count=808 prompt_eval_duration=8809000292 eval_count=164 eval_duration=15971681708 message=Message(role='assistant', content='{[...]}', thinking=None, images=None, tool_calls=None)
Спасибо за вашу помощь!
Подробнее здесь: https://stackoverflow.com/questions/797 ... hat-intera