refactor
This commit is contained in:
92
systems/dialog_system.gd
Normal file
92
systems/dialog_system.gd
Normal file
@@ -0,0 +1,92 @@
|
||||
extends Node
|
||||
|
||||
const OLLAMA_URL: String = "http://127.0.0.1:11434/api/generate"
|
||||
const DEFAULT_MODEL: String = "qwen2.5:0.5b"
|
||||
const REQUEST_TIMEOUT: float = 25.0
|
||||
|
||||
var _http: HTTPRequest
|
||||
var _pending: Dictionary = {}
|
||||
var _pending_target: Node = null
|
||||
|
||||
func _ready() -> void:
|
||||
_http = HTTPRequest.new()
|
||||
_http.timeout = REQUEST_TIMEOUT
|
||||
add_child(_http)
|
||||
_http.request_completed.connect(_on_response)
|
||||
|
||||
func ask(npc: Node, player: Node, question: String) -> void:
|
||||
if not (multiplayer.is_server() or multiplayer.multiplayer_peer == null):
|
||||
request_ask.rpc_id(1, npc.get_path(), player.get_path(), question)
|
||||
return
|
||||
var profile: NpcProfile = npc.profile
|
||||
var system_prompt: String = "Du bist %s, eine NPC in einem mittelalterlichen Dorf. Lore: %s. Persönlichkeit: %s. Antworte knapp (max 2 Sätze) auf Deutsch und bleibe immer in deiner Rolle. Erfinde keine Fakten über die Welt." % [profile.display_name, profile.lore, profile.personality]
|
||||
var prompt: String = "Spieler: %s\n%s:" % [question, profile.display_name]
|
||||
_send_request(npc, player, system_prompt, prompt)
|
||||
|
||||
@rpc("any_peer", "reliable")
|
||||
func request_ask(npc_path: NodePath, player_path: NodePath, question: String) -> void:
|
||||
var npc: Node = get_node_or_null(npc_path)
|
||||
var player: Node = get_node_or_null(player_path)
|
||||
if npc and player:
|
||||
ask(npc, player, question)
|
||||
|
||||
func _send_request(npc: Node, player: Node, system_prompt: String, prompt: String) -> void:
|
||||
var body: Dictionary = {
|
||||
"model": DEFAULT_MODEL,
|
||||
"prompt": prompt,
|
||||
"system": system_prompt,
|
||||
"stream": false,
|
||||
"options": {"temperature": 0.7, "num_predict": 120}
|
||||
}
|
||||
var headers := PackedStringArray(["Content-Type: application/json"])
|
||||
var json := JSON.stringify(body)
|
||||
var token: int = randi()
|
||||
_pending[token] = {"npc": npc, "player": player}
|
||||
_pending_target = player
|
||||
var err := _http.request(OLLAMA_URL, headers, HTTPClient.METHOD_POST, json)
|
||||
if err != OK:
|
||||
_send_fallback(npc, player)
|
||||
|
||||
func _on_response(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||
var entry_keys: Array = _pending.keys()
|
||||
if entry_keys.is_empty():
|
||||
return
|
||||
var token: int = entry_keys[0]
|
||||
var entry: Dictionary = _pending[token]
|
||||
_pending.erase(token)
|
||||
var npc: Node = entry.npc
|
||||
var player: Node = entry.player
|
||||
if result != HTTPRequest.RESULT_SUCCESS or response_code != 200:
|
||||
_send_fallback(npc, player)
|
||||
return
|
||||
var text: String = body.get_string_from_utf8()
|
||||
var data: Variant = JSON.parse_string(text)
|
||||
if typeof(data) != TYPE_DICTIONARY or not "response" in data:
|
||||
_send_fallback(npc, player)
|
||||
return
|
||||
var answer: String = (data.response as String).strip_edges()
|
||||
if answer == "":
|
||||
_send_fallback(npc, player)
|
||||
return
|
||||
_deliver(player, npc, answer)
|
||||
|
||||
func _send_fallback(npc: Node, player: Node) -> void:
|
||||
if not is_instance_valid(npc):
|
||||
return
|
||||
var profile: NpcProfile = npc.profile
|
||||
_deliver(player, npc, profile.fallback_text)
|
||||
|
||||
func _deliver(player: Node, npc: Node, text: String) -> void:
|
||||
if player == null or not is_instance_valid(player):
|
||||
return
|
||||
var auth: int = player.get_multiplayer_authority()
|
||||
_on_dialog_answer.rpc_id(auth, npc.get_path(), text)
|
||||
|
||||
@rpc("authority", "reliable", "call_local")
|
||||
func _on_dialog_answer(npc_path: NodePath, text: String) -> void:
|
||||
var npc: Node = get_node_or_null(npc_path)
|
||||
if npc:
|
||||
EventBus.chat_message.emit(0, npc.profile.display_name if npc.has_method("get") else "NPC", text)
|
||||
for hud in get_tree().get_nodes_in_group("dialog_ui"):
|
||||
if hud.has_method("show_answer"):
|
||||
hud.show_answer(text)
|
||||
Reference in New Issue
Block a user